1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car;
18 
19 import android.annotation.MainThread;
20 import android.app.ActivityManager;
21 import android.app.ActivityOptions;
22 import android.app.UiModeManager;
23 import android.car.Car;
24 import android.car.ICar;
25 import android.car.cluster.renderer.IInstrumentClusterNavigation;
26 import android.car.userlib.CarUserManagerHelper;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.PackageManager;
31 import android.content.res.Resources;
32 import android.hardware.automotive.vehicle.V2_0.IVehicle;
33 import android.hardware.automotive.vehicle.V2_0.VehicleArea;
34 import android.os.Binder;
35 import android.os.Build;
36 import android.os.IBinder;
37 import android.os.Process;
38 import android.os.SystemClock;
39 import android.os.Trace;
40 import android.util.Log;
41 import android.util.Slog;
42 import android.util.TimingsTraceLog;
43 import android.view.KeyEvent;
44 
45 import com.android.car.am.FixedActivityService;
46 import com.android.car.audio.CarAudioService;
47 import com.android.car.cluster.InstrumentClusterService;
48 import com.android.car.garagemode.GarageModeService;
49 import com.android.car.hal.InputHalService;
50 import com.android.car.hal.VehicleHal;
51 import com.android.car.internal.FeatureConfiguration;
52 import com.android.car.pm.CarPackageManagerService;
53 import com.android.car.stats.CarStatsService;
54 import com.android.car.systeminterface.SystemInterface;
55 import com.android.car.trust.CarTrustedDeviceService;
56 import com.android.car.user.CarUserNoticeService;
57 import com.android.car.user.CarUserService;
58 import com.android.car.vms.VmsBrokerService;
59 import com.android.car.vms.VmsClientManager;
60 import com.android.internal.annotations.GuardedBy;
61 import com.android.internal.car.ICarServiceHelper;
62 
63 import java.io.FileDescriptor;
64 import java.io.PrintWriter;
65 import java.util.ArrayList;
66 import java.util.Arrays;
67 import java.util.List;
68 
69 public class ICarImpl extends ICar.Stub {
70 
71     public static final String INTERNAL_INPUT_SERVICE = "internal_input";
72     public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE =
73             "system_activity_monitoring";
74     public static final String INTERNAL_VMS_MANAGER = "vms_manager";
75 
76     private final Context mContext;
77     private final VehicleHal mHal;
78 
79     private final SystemInterface mSystemInterface;
80 
81     private final SystemActivityMonitoringService mSystemActivityMonitoringService;
82     private final CarPowerManagementService mCarPowerManagementService;
83     private final CarPackageManagerService mCarPackageManagerService;
84     private final CarInputService mCarInputService;
85     private final CarDrivingStateService mCarDrivingStateService;
86     private final CarUxRestrictionsManagerService mCarUXRestrictionsService;
87     private final CarAudioService mCarAudioService;
88     private final CarProjectionService mCarProjectionService;
89     private final CarPropertyService mCarPropertyService;
90     private final CarNightService mCarNightService;
91     private final AppFocusService mAppFocusService;
92     private final FixedActivityService mFixedActivityService;
93     private final GarageModeService mGarageModeService;
94     private final InstrumentClusterService mInstrumentClusterService;
95     private final CarLocationService mCarLocationService;
96     private final SystemStateControllerService mSystemStateControllerService;
97     private final CarBluetoothService mCarBluetoothService;
98     private final PerUserCarServiceHelper mPerUserCarServiceHelper;
99     private final CarDiagnosticService mCarDiagnosticService;
100     private final CarStorageMonitoringService mCarStorageMonitoringService;
101     private final CarConfigurationService mCarConfigurationService;
102     private final CarTrustedDeviceService mCarTrustedDeviceService;
103     private final CarMediaService mCarMediaService;
104     private final CarUserManagerHelper mUserManagerHelper;
105     private final CarUserService mCarUserService;
106     private final CarUserNoticeService mCarUserNoticeService;
107     private final VmsClientManager mVmsClientManager;
108     private final VmsBrokerService mVmsBrokerService;
109     private final VmsSubscriberService mVmsSubscriberService;
110     private final VmsPublisherService mVmsPublisherService;
111     private final CarBugreportManagerService mCarBugreportManagerService;
112     private final CarStatsService mCarStatsService;
113 
114     private final CarServiceBase[] mAllServices;
115 
116     private static final String TAG = "ICarImpl";
117     private static final String VHAL_TIMING_TAG = "VehicleHalTiming";
118 
119     private TimingsTraceLog mBootTiming;
120 
121     /** Test only service. Populate it only when necessary. */
122     @GuardedBy("this")
123     private CarTestService mCarTestService;
124 
125     @GuardedBy("this")
126     private ICarServiceHelper mICarServiceHelper;
127 
128     private final String mVehicleInterfaceName;
129 
ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface, CanBusErrorNotifier errorNotifier, String vehicleInterfaceName)130     public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
131             CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
132         mContext = serviceContext;
133         mSystemInterface = systemInterface;
134         mHal = new VehicleHal(serviceContext, vehicle);
135         mVehicleInterfaceName = vehicleInterfaceName;
136         mUserManagerHelper = new CarUserManagerHelper(serviceContext);
137         final Resources res = mContext.getResources();
138         final int maxRunningUsers = res.getInteger(
139                 com.android.internal.R.integer.config_multiuserMaxRunningUsers);
140         mCarUserService = new CarUserService(serviceContext, mUserManagerHelper,
141                 ActivityManager.getService(), maxRunningUsers);
142         mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
143         mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),
144                 systemInterface, mUserManagerHelper);
145         mCarUserNoticeService = new CarUserNoticeService(serviceContext);
146         mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
147         mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarPropertyService);
148         mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext,
149                 mCarDrivingStateService, mCarPropertyService);
150         mCarPackageManagerService = new CarPackageManagerService(serviceContext,
151                 mCarUXRestrictionsService,
152                 mSystemActivityMonitoringService,
153                 mUserManagerHelper);
154         mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
155         mCarBluetoothService = new CarBluetoothService(serviceContext, mPerUserCarServiceHelper);
156         mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
157         mCarProjectionService = new CarProjectionService(
158                 serviceContext, null /* handler */, mCarInputService, mCarBluetoothService);
159         mGarageModeService = new GarageModeService(mContext);
160         mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
161         mCarAudioService = new CarAudioService(serviceContext);
162         mCarNightService = new CarNightService(serviceContext, mCarPropertyService);
163         mFixedActivityService = new FixedActivityService(serviceContext);
164         mInstrumentClusterService = new InstrumentClusterService(serviceContext,
165                 mAppFocusService, mCarInputService);
166         mSystemStateControllerService = new SystemStateControllerService(
167                 serviceContext, mCarAudioService, this);
168         mCarStatsService = new CarStatsService(serviceContext);
169         mVmsBrokerService = new VmsBrokerService();
170         mVmsClientManager = new VmsClientManager(
171                 // CarStatsService needs to be passed to the constructor due to HAL init order
172                 serviceContext, mCarStatsService, mCarUserService, mVmsBrokerService,
173                 mHal.getVmsHal());
174         mVmsSubscriberService = new VmsSubscriberService(
175                 serviceContext, mVmsBrokerService, mVmsClientManager, mHal.getVmsHal());
176         mVmsPublisherService = new VmsPublisherService(
177                 serviceContext, mCarStatsService, mVmsBrokerService, mVmsClientManager);
178         mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
179         mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,
180                 systemInterface);
181         mCarConfigurationService =
182                 new CarConfigurationService(serviceContext, new JsonReaderImpl());
183         mCarLocationService = new CarLocationService(mContext, mUserManagerHelper);
184         mCarTrustedDeviceService = new CarTrustedDeviceService(serviceContext);
185         mCarMediaService = new CarMediaService(serviceContext);
186         mCarBugreportManagerService = new CarBugreportManagerService(serviceContext);
187 
188         CarLocalServices.addService(CarPowerManagementService.class, mCarPowerManagementService);
189         CarLocalServices.addService(CarUserService.class, mCarUserService);
190         CarLocalServices.addService(CarTrustedDeviceService.class, mCarTrustedDeviceService);
191         CarLocalServices.addService(CarUserNoticeService.class, mCarUserNoticeService);
192         CarLocalServices.addService(SystemInterface.class, mSystemInterface);
193         CarLocalServices.addService(CarDrivingStateService.class, mCarDrivingStateService);
194         CarLocalServices.addService(PerUserCarServiceHelper.class, mPerUserCarServiceHelper);
195         CarLocalServices.addService(FixedActivityService.class, mFixedActivityService);
196 
197         // Be careful with order. Service depending on other service should be inited later.
198         List<CarServiceBase> allServices = new ArrayList<>();
199         allServices.add(mCarUserService);
200         allServices.add(mSystemActivityMonitoringService);
201         allServices.add(mCarPowerManagementService);
202         allServices.add(mCarPropertyService);
203         allServices.add(mCarDrivingStateService);
204         allServices.add(mCarUXRestrictionsService);
205         allServices.add(mCarPackageManagerService);
206         allServices.add(mCarInputService);
207         allServices.add(mGarageModeService);
208         allServices.add(mCarUserNoticeService);
209         allServices.add(mAppFocusService);
210         allServices.add(mCarAudioService);
211         allServices.add(mCarNightService);
212         allServices.add(mFixedActivityService);
213         allServices.add(mInstrumentClusterService);
214         allServices.add(mSystemStateControllerService);
215         allServices.add(mPerUserCarServiceHelper);
216         allServices.add(mCarBluetoothService);
217         allServices.add(mCarProjectionService);
218         allServices.add(mCarDiagnosticService);
219         allServices.add(mCarStorageMonitoringService);
220         allServices.add(mCarConfigurationService);
221         allServices.add(mVmsClientManager);
222         allServices.add(mVmsSubscriberService);
223         allServices.add(mVmsPublisherService);
224         allServices.add(mCarTrustedDeviceService);
225         allServices.add(mCarMediaService);
226         allServices.add(mCarLocationService);
227         allServices.add(mCarBugreportManagerService);
228         mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
229     }
230 
231     @MainThread
init()232     void init() {
233         mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG, Trace.TRACE_TAG_HAL);
234         traceBegin("VehicleHal.init");
235         mHal.init();
236         traceEnd();
237         traceBegin("CarService.initAllServices");
238         for (CarServiceBase service : mAllServices) {
239             service.init();
240         }
241         traceEnd();
242         mSystemInterface.reconfigureSecondaryDisplays();
243     }
244 
release()245     void release() {
246         // release done in opposite order from init
247         for (int i = mAllServices.length - 1; i >= 0; i--) {
248             mAllServices[i].release();
249         }
250         mHal.release();
251     }
252 
vehicleHalReconnected(IVehicle vehicle)253     void vehicleHalReconnected(IVehicle vehicle) {
254         mHal.vehicleHalReconnected(vehicle);
255         for (CarServiceBase service : mAllServices) {
256             service.vehicleHalReconnected();
257         }
258     }
259 
260     @Override
setCarServiceHelper(IBinder helper)261     public void setCarServiceHelper(IBinder helper) {
262         assertCallingFromSystemProcess();
263         synchronized (this) {
264             mICarServiceHelper = ICarServiceHelper.Stub.asInterface(helper);
265             mSystemInterface.setCarServiceHelper(mICarServiceHelper);
266         }
267     }
268 
269     @Override
setUserLockStatus(int userHandle, int unlocked)270     public void setUserLockStatus(int userHandle, int unlocked) {
271         assertCallingFromSystemProcess();
272         mCarUserService.setUserLockStatus(userHandle, unlocked == 1);
273         mCarMediaService.setUserLockStatus(userHandle, unlocked == 1);
274     }
275 
276     @Override
onSwitchUser(int userHandle)277     public void onSwitchUser(int userHandle) {
278         assertCallingFromSystemProcess();
279 
280         Log.i(TAG, "Foreground user switched to " + userHandle);
281         mCarUserService.onSwitchUser(userHandle);
282     }
283 
assertCallingFromSystemProcess()284     static void assertCallingFromSystemProcess() {
285         int uid = Binder.getCallingUid();
286         if (uid != Process.SYSTEM_UID) {
287             throw new SecurityException("Only allowed from system");
288         }
289     }
290 
291     /**
292      * Assert if binder call is coming from system process like system server or if it is called
293      * from its own process even if it is not system. The latter can happen in test environment.
294      * Note that car service runs as system user but test like car service test will not.
295      */
assertCallingFromSystemProcessOrSelf()296     static void assertCallingFromSystemProcessOrSelf() {
297         int uid = Binder.getCallingUid();
298         int pid = Binder.getCallingPid();
299         if (uid != Process.SYSTEM_UID && pid != Process.myPid()) {
300             throw new SecurityException("Only allowed from system or self");
301         }
302     }
303 
304     @Override
getCarService(String serviceName)305     public IBinder getCarService(String serviceName) {
306         switch (serviceName) {
307             case Car.AUDIO_SERVICE:
308                 return mCarAudioService;
309             case Car.APP_FOCUS_SERVICE:
310                 return mAppFocusService;
311             case Car.PACKAGE_SERVICE:
312                 return mCarPackageManagerService;
313             case Car.DIAGNOSTIC_SERVICE:
314                 assertAnyDiagnosticPermission(mContext);
315                 return mCarDiagnosticService;
316             case Car.POWER_SERVICE:
317                 assertPowerPermission(mContext);
318                 return mCarPowerManagementService;
319             case Car.CABIN_SERVICE:
320             case Car.HVAC_SERVICE:
321             case Car.INFO_SERVICE:
322             case Car.PROPERTY_SERVICE:
323             case Car.SENSOR_SERVICE:
324             case Car.VENDOR_EXTENSION_SERVICE:
325                 return mCarPropertyService;
326             case Car.CAR_NAVIGATION_SERVICE:
327                 assertNavigationManagerPermission(mContext);
328                 IInstrumentClusterNavigation navService =
329                         mInstrumentClusterService.getNavigationService();
330                 return navService == null ? null : navService.asBinder();
331             case Car.CAR_INSTRUMENT_CLUSTER_SERVICE:
332                 assertClusterManagerPermission(mContext);
333                 return mInstrumentClusterService.getManagerService();
334             case Car.PROJECTION_SERVICE:
335                 return mCarProjectionService;
336             case Car.VMS_SUBSCRIBER_SERVICE:
337                 assertVmsSubscriberPermission(mContext);
338                 return mVmsSubscriberService;
339             case Car.TEST_SERVICE: {
340                 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
341                 synchronized (this) {
342                     if (mCarTestService == null) {
343                         mCarTestService = new CarTestService(mContext, this);
344                     }
345                     return mCarTestService;
346                 }
347             }
348             case Car.BLUETOOTH_SERVICE:
349                 return mCarBluetoothService;
350             case Car.STORAGE_MONITORING_SERVICE:
351                 assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
352                 return mCarStorageMonitoringService;
353             case Car.CAR_DRIVING_STATE_SERVICE:
354                 assertDrivingStatePermission(mContext);
355                 return mCarDrivingStateService;
356             case Car.CAR_UX_RESTRICTION_SERVICE:
357                 return mCarUXRestrictionsService;
358             case Car.CAR_CONFIGURATION_SERVICE:
359                 return mCarConfigurationService;
360             case Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE:
361                 assertTrustAgentEnrollmentPermission(mContext);
362                 return mCarTrustedDeviceService.getCarTrustAgentEnrollmentService();
363             case Car.CAR_MEDIA_SERVICE:
364                 return mCarMediaService;
365             case Car.CAR_BUGREPORT_SERVICE:
366                 return mCarBugreportManagerService;
367             default:
368                 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
369                 return null;
370         }
371     }
372 
373     @Override
getCarConnectionType()374     public int getCarConnectionType() {
375         return Car.CONNECTION_TYPE_EMBEDDED;
376     }
377 
getCarInternalService(String serviceName)378     public CarServiceBase getCarInternalService(String serviceName) {
379         switch (serviceName) {
380             case INTERNAL_INPUT_SERVICE:
381                 return mCarInputService;
382             case INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE:
383                 return mSystemActivityMonitoringService;
384             case INTERNAL_VMS_MANAGER:
385                 return mVmsClientManager;
386             default:
387                 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" +
388                         serviceName);
389                 return null;
390         }
391     }
392 
getStatsService()393     CarStatsService getStatsService() {
394         return mCarStatsService;
395     }
396 
assertVehicleHalMockPermission(Context context)397     public static void assertVehicleHalMockPermission(Context context) {
398         assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL);
399     }
400 
assertNavigationManagerPermission(Context context)401     public static void assertNavigationManagerPermission(Context context) {
402         assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER);
403     }
404 
assertClusterManagerPermission(Context context)405     public static void assertClusterManagerPermission(Context context) {
406         assertPermission(context, Car.PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL);
407     }
408 
assertPowerPermission(Context context)409     public static void assertPowerPermission(Context context) {
410         assertPermission(context, Car.PERMISSION_CAR_POWER);
411     }
412 
assertProjectionPermission(Context context)413     public static void assertProjectionPermission(Context context) {
414         assertPermission(context, Car.PERMISSION_CAR_PROJECTION);
415     }
416 
417     /** Verify the calling context has the {@link Car#PERMISSION_CAR_PROJECTION_STATUS} */
assertProjectionStatusPermission(Context context)418     public static void assertProjectionStatusPermission(Context context) {
419         assertPermission(context, Car.PERMISSION_CAR_PROJECTION_STATUS);
420     }
421 
assertAnyDiagnosticPermission(Context context)422     public static void assertAnyDiagnosticPermission(Context context) {
423         assertAnyPermission(context,
424                 Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL,
425                 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR);
426     }
427 
assertDrivingStatePermission(Context context)428     public static void assertDrivingStatePermission(Context context) {
429         assertPermission(context, Car.PERMISSION_CAR_DRIVING_STATE);
430     }
431 
assertVmsPublisherPermission(Context context)432     public static void assertVmsPublisherPermission(Context context) {
433         assertPermission(context, Car.PERMISSION_VMS_PUBLISHER);
434     }
435 
assertVmsSubscriberPermission(Context context)436     public static void assertVmsSubscriberPermission(Context context) {
437         assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER);
438     }
439 
440     /**
441      * Ensures the caller has the permission to enroll a Trust Agent.
442      */
assertTrustAgentEnrollmentPermission(Context context)443     public static void assertTrustAgentEnrollmentPermission(Context context) {
444         assertPermission(context, Car.PERMISSION_CAR_ENROLL_TRUST);
445     }
446 
assertPermission(Context context, String permission)447     public static void assertPermission(Context context, String permission) {
448         if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
449             throw new SecurityException("requires " + permission);
450         }
451     }
452 
453     /**
454      * Checks to see if the caller has a permission.
455      *
456      * @return boolean TRUE if caller has the permission.
457      */
hasPermission(Context context, String permission)458     public static boolean hasPermission(Context context, String permission) {
459         return context.checkCallingOrSelfPermission(permission)
460                 == PackageManager.PERMISSION_GRANTED;
461     }
462 
assertAnyPermission(Context context, String... permissions)463     public static void assertAnyPermission(Context context, String... permissions) {
464         for (String permission : permissions) {
465             if (context.checkCallingOrSelfPermission(permission) ==
466                     PackageManager.PERMISSION_GRANTED) {
467                 return;
468             }
469         }
470         throw new SecurityException("requires any of " + Arrays.toString(permissions));
471     }
472 
473     @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)474     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
475         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
476                 != PackageManager.PERMISSION_GRANTED) {
477             writer.println("Permission Denial: can't dump CarService from from pid="
478                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
479                     + " without permission " + android.Manifest.permission.DUMP);
480             return;
481         }
482 
483         if (args == null || args.length == 0 || (args.length > 0 && "-a".equals(args[0]))) {
484             writer.println("*Dump car service*");
485             writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT);
486             writer.println("*Dump all services*");
487 
488             dumpAllServices(writer);
489 
490             writer.println("*Dump Vehicle HAL*");
491             writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName);
492             try {
493                 // TODO dump all feature flags by creating a dumpable interface
494                 mHal.dump(writer);
495             } catch (Exception e) {
496                 writer.println("Failed dumping: " + mHal.getClass().getName());
497                 e.printStackTrace(writer);
498             }
499         } else if ("--metrics".equals(args[0])) {
500             // Strip the --metrics flag when passing dumpsys arguments to CarStatsService
501             // allowing for nested flag selection
502             mCarStatsService.dump(fd, writer, Arrays.copyOfRange(args, 1, args.length));
503         } else if ("--vms-hal".equals(args[0])) {
504             mHal.getVmsHal().dumpMetrics(fd);
505         } else if (Build.IS_USERDEBUG || Build.IS_ENG) {
506             execShellCmd(args, writer);
507         } else {
508             writer.println("Commands not supported in " + Build.TYPE);
509         }
510     }
511 
dumpAllServices(PrintWriter writer)512     private void dumpAllServices(PrintWriter writer) {
513         for (CarServiceBase service : mAllServices) {
514             dumpService(service, writer);
515         }
516         if (mCarTestService != null) {
517             dumpService(mCarTestService, writer);
518         }
519     }
520 
dumpService(CarServiceBase service, PrintWriter writer)521     private void dumpService(CarServiceBase service, PrintWriter writer) {
522         try {
523             service.dump(writer);
524         } catch (Exception e) {
525             writer.println("Failed dumping: " + service.getClass().getName());
526             e.printStackTrace(writer);
527         }
528     }
529 
execShellCmd(String[] args, PrintWriter writer)530     void execShellCmd(String[] args, PrintWriter writer) {
531         new CarShellCommand().exec(args, writer);
532     }
533 
534     @MainThread
traceBegin(String name)535     private void traceBegin(String name) {
536         Slog.i(TAG, name);
537         mBootTiming.traceBegin(name);
538     }
539 
540     @MainThread
traceEnd()541     private void traceEnd() {
542         mBootTiming.traceEnd();
543     }
544 
545     private class CarShellCommand {
546         private static final String COMMAND_HELP = "-h";
547         private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode";
548         private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event";
549         private static final String COMMAND_INJECT_ERROR_EVENT = "inject-error-event";
550         private static final String COMMAND_ENABLE_UXR = "enable-uxr";
551         private static final String COMMAND_GARAGE_MODE = "garage-mode";
552         private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities";
553         private static final String COMMAND_GET_CARPROPERTYCONFIG = "get-carpropertyconfig";
554         private static final String COMMAND_GET_PROPERTY_VALUE = "get-property-value";
555         private static final String COMMAND_PROJECTION_AP_TETHERING = "projection-tethering";
556         private static final String COMMAND_PROJECTION_UI_MODE = "projection-ui-mode";
557         private static final String COMMAND_RESUME = "resume";
558         private static final String COMMAND_SUSPEND = "suspend";
559         private static final String COMMAND_ENABLE_TRUSTED_DEVICE = "enable-trusted-device";
560         private static final String COMMAND_REMOVE_TRUSTED_DEVICES = "remove-trusted-devices";
561         private static final String COMMAND_START_FIXED_ACTIVITY_MODE = "start-fixed-activity-mode";
562         private static final String COMMAND_STOP_FIXED_ACTIVITY_MODE = "stop-fixed-activity-mode";
563         private static final String COMMAND_INJECT_KEY = "inject-key";
564 
565         private static final String PARAM_DAY_MODE = "day";
566         private static final String PARAM_NIGHT_MODE = "night";
567         private static final String PARAM_SENSOR_MODE = "sensor";
568         private static final String PARAM_VEHICLE_PROPERTY_AREA_GLOBAL = "0";
569         private static final String PARAM_ON_MODE = "on";
570         private static final String PARAM_OFF_MODE = "off";
571         private static final String PARAM_QUERY_MODE = "query";
572         private static final String PARAM_REBOOT = "reboot";
573 
574 
dumpHelp(PrintWriter pw)575         private void dumpHelp(PrintWriter pw) {
576             pw.println("Car service commands:");
577             pw.println("\t-h");
578             pw.println("\t  Print this help text.");
579             pw.println("\tday-night-mode [day|night|sensor]");
580             pw.println("\t  Force into day/night mode or restore to auto.");
581             pw.println("\tinject-vhal-event property [zone] data(can be comma separated list)");
582             pw.println("\t  Inject a vehicle property for testing.");
583             pw.println("\tinject-error-event property zone errorCode");
584             pw.println("\t  Inject an error event from VHAL for testing.");
585             pw.println("\tenable-uxr true|false");
586             pw.println("\t  Enable/Disable UX restrictions and App blocking.");
587             pw.println("\tgarage-mode [on|off|query|reboot]");
588             pw.println("\t  Force into or out of garage mode, or check status.");
589             pw.println("\t  With 'reboot', enter garage mode, then reboot when it completes.");
590             pw.println("\tget-do-activities pkgname");
591             pw.println("\t  Get Distraction Optimized activities in given package.");
592             pw.println("\tget-carpropertyconfig [propertyId]");
593             pw.println("\t  Get a CarPropertyConfig by Id in Hex or list all CarPropertyConfigs");
594             pw.println("\tget-property-value [propertyId] [areaId]");
595             pw.println("\t  Get a vehicle property value by property id in Hex and areaId");
596             pw.println("\t  or list all property values for all areaId");
597             pw.println("\tsuspend");
598             pw.println("\t  Suspend the system to Deep Sleep.");
599             pw.println("\tresume");
600             pw.println("\t  Wake the system up after a 'suspend.'");
601             pw.println("\tenable-trusted-device true|false");
602             pw.println("\t  Enable/Disable Trusted device feature.");
603             pw.println("\tremove-trusted-devices");
604             pw.println("\t  Remove all trusted devices for the current foreground user.");
605             pw.println("\tprojection-tethering [true|false]");
606             pw.println("\t  Whether tethering should be used when creating access point for"
607                     + " wireless projection");
608             pw.println("\t--metrics");
609             pw.println("\t  When used with dumpsys, only metrics will be in the dumpsys output.");
610             pw.println("\tstart-fixed-activity displayId packageName activityName");
611             pw.println("\t  Start an Activity the specified display as fixed mode");
612             pw.println("\tstop-fixed-mode displayId");
613             pw.println("\t  Stop fixed Activity mode for the given display. "
614                     + "The Activity will not be restarted upon crash.");
615             pw.println("\tinject-key [-d display] [-t down_delay_ms] key_code");
616             pw.println("\t  inject key down / up event to car service");
617             pw.println("\t  display: 0 for main, 1 for cluster. If not specified, it will be 0.");
618             pw.println("\t  down_delay_ms: delay from down to up key event. If not specified,");
619             pw.println("\t                 it will be 0");
620             pw.println("\t  key_code: int key code defined in android KeyEvent");
621         }
622 
exec(String[] args, PrintWriter writer)623         public void exec(String[] args, PrintWriter writer) {
624             String arg = args[0];
625             switch (arg) {
626                 case COMMAND_HELP:
627                     dumpHelp(writer);
628                     break;
629                 case COMMAND_DAY_NIGHT_MODE: {
630                     String value = args.length < 2 ? "" : args[1];
631                     forceDayNightMode(value, writer);
632                     break;
633                 }
634                 case COMMAND_GARAGE_MODE: {
635                     String value = args.length < 2 ? "" : args[1];
636                     forceGarageMode(value, writer);
637                     break;
638                 }
639                 case COMMAND_INJECT_VHAL_EVENT:
640                     String zone = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL;
641                     String data;
642                     if (args.length != 3 && args.length != 4) {
643                         writer.println("Incorrect number of arguments.");
644                         dumpHelp(writer);
645                         break;
646                     } else if (args.length == 4) {
647                         // Zoned
648                         zone = args[2];
649                         data = args[3];
650                     } else {
651                         // Global
652                         data = args[2];
653                     }
654                     injectVhalEvent(args[1], zone, data, false, writer);
655                     break;
656                 case COMMAND_INJECT_ERROR_EVENT:
657                     if (args.length != 4) {
658                         writer.println("Incorrect number of arguments");
659                         dumpHelp(writer);
660                         break;
661                     }
662                     String errorAreaId = args[2];
663                     String errorCode = args[3];
664                     injectVhalEvent(args[1], errorAreaId, errorCode, true, writer);
665                     break;
666                 case COMMAND_ENABLE_UXR:
667                     if (args.length != 2) {
668                         writer.println("Incorrect number of arguments");
669                         dumpHelp(writer);
670                         break;
671                     }
672                     boolean enableBlocking = Boolean.valueOf(args[1]);
673                     if (mCarPackageManagerService != null) {
674                         mCarPackageManagerService.setEnableActivityBlocking(enableBlocking);
675                     }
676                     break;
677                 case COMMAND_GET_DO_ACTIVITIES:
678                     if (args.length != 2) {
679                         writer.println("Incorrect number of arguments");
680                         dumpHelp(writer);
681                         break;
682                     }
683                     String pkgName = args[1].toLowerCase();
684                     if (mCarPackageManagerService != null) {
685                         String[] doActivities =
686                                 mCarPackageManagerService.getDistractionOptimizedActivities(
687                                         pkgName);
688                         if (doActivities != null) {
689                             writer.println("DO Activities for " + pkgName);
690                             for (String a : doActivities) {
691                                 writer.println(a);
692                             }
693                         } else {
694                             writer.println("No DO Activities for " + pkgName);
695                         }
696                     }
697                     break;
698                 case COMMAND_GET_CARPROPERTYCONFIG:
699                     String propertyId = args.length < 2 ? "" : args[1];
700                     mHal.dumpPropertyConfigs(writer, propertyId);
701                     break;
702                 case COMMAND_GET_PROPERTY_VALUE:
703                     String propId = args.length < 2 ? "" : args[1];
704                     String areaId = args.length < 3 ? "" : args[2];
705                     mHal.dumpPropertyValueByCommend(writer, propId, areaId);
706                     break;
707                 case COMMAND_PROJECTION_UI_MODE:
708                     if (args.length != 2) {
709                         writer.println("Incorrect number of arguments");
710                         dumpHelp(writer);
711                         break;
712                     }
713                     mCarProjectionService.setUiMode(Integer.valueOf(args[1]));
714                     break;
715                 case COMMAND_PROJECTION_AP_TETHERING:
716                     if (args.length != 2) {
717                         writer.println("Incorrect number of arguments");
718                         dumpHelp(writer);
719                         break;
720                     }
721                     mCarProjectionService.setAccessPointTethering(Boolean.valueOf(args[1]));
722                     break;
723                 case COMMAND_RESUME:
724                     mCarPowerManagementService.forceSimulatedResume();
725                     writer.println("Resume: Simulating resuming from Deep Sleep");
726                     break;
727                 case COMMAND_SUSPEND:
728                     mCarPowerManagementService.forceSuspendAndMaybeReboot(false);
729                     writer.println("Resume: Simulating powering down to Deep Sleep");
730                     break;
731                 case COMMAND_ENABLE_TRUSTED_DEVICE:
732                     if (args.length != 2) {
733                         writer.println("Incorrect number of arguments");
734                         dumpHelp(writer);
735                         break;
736                     }
737                     mCarTrustedDeviceService.getCarTrustAgentEnrollmentService()
738                             .setTrustedDeviceEnrollmentEnabled(Boolean.valueOf(args[1]));
739                     mCarTrustedDeviceService.getCarTrustAgentUnlockService()
740                             .setTrustedDeviceUnlockEnabled(Boolean.valueOf(args[1]));
741                     break;
742                 case COMMAND_REMOVE_TRUSTED_DEVICES:
743                     mCarTrustedDeviceService.getCarTrustAgentEnrollmentService()
744                             .removeAllTrustedDevices(
745                                     mUserManagerHelper.getCurrentForegroundUserId());
746                     break;
747                 case COMMAND_START_FIXED_ACTIVITY_MODE:
748                     handleStartFixedActivity(args, writer);
749                     break;
750                 case COMMAND_STOP_FIXED_ACTIVITY_MODE:
751                     handleStopFixedMode(args, writer);
752                     break;
753 
754                 case COMMAND_INJECT_KEY:
755                     if (args.length < 2) {
756                         writer.println("Incorrect number of arguments");
757                         dumpHelp(writer);
758                         break;
759                     }
760                     handleInjectKey(args, writer);
761                     break;
762                 default:
763                     writer.println("Unknown command: \"" + arg + "\"");
764                     dumpHelp(writer);
765             }
766         }
767 
768         private void handleStartFixedActivity(String[] args, PrintWriter writer) {
769             if (args.length != 4) {
770                 writer.println("Incorrect number of arguments");
771                 dumpHelp(writer);
772                 return;
773             }
774             int displayId;
775             try {
776                 displayId = Integer.parseInt(args[1]);
777             } catch (NumberFormatException e) {
778                 writer.println("Wrong display id:" + args[1]);
779                 return;
780             }
781             String packageName = args[2];
782             String activityName = args[3];
783             Intent intent = new Intent();
784             intent.setComponent(new ComponentName(packageName, activityName));
785             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
786             ActivityOptions options = ActivityOptions.makeBasic();
787             options.setLaunchDisplayId(displayId);
788             if (!mFixedActivityService.startFixedActivityModeForDisplayAndUser(intent, options,
789                     displayId, ActivityManager.getCurrentUser())) {
790                 writer.println("Failed to start");
791                 return;
792             }
793             writer.println("Succeeded");
794         }
795 
796         private void handleStopFixedMode(String[] args, PrintWriter writer) {
797             if (args.length != 2) {
798                 writer.println("Incorrect number of arguments");
799                 dumpHelp(writer);
800                 return;
801             }
802             int displayId;
803             try {
804                 displayId = Integer.parseInt(args[1]);
805             } catch (NumberFormatException e) {
806                 writer.println("Wrong display id:" + args[1]);
807                 return;
808             }
809             mFixedActivityService.stopFixedActivityMode(displayId);
810         }
811 
812         private void handleInjectKey(String[] args, PrintWriter writer) {
813             int i = 1; // 0 is command itself
814             int display = InputHalService.DISPLAY_MAIN;
815             int delayMs = 0;
816             int keyCode = KeyEvent.KEYCODE_UNKNOWN;
817             try {
818                 while (i < args.length) {
819                     switch (args[i]) {
820                         case "-d":
821                             i++;
822                             display = Integer.parseInt(args[i]);
823                             break;
824                         case "-t":
825                             i++;
826                             delayMs = Integer.parseInt(args[i]);
827                             break;
828                         default:
829                             if (keyCode != KeyEvent.KEYCODE_UNKNOWN) {
830                                 throw new IllegalArgumentException("key_code already set:"
831                                         + keyCode);
832                             }
833                             keyCode = Integer.parseInt(args[i]);
834                     }
835                     i++;
836                 }
837             } catch (Exception e) {
838                 writer.println("Invalid args:" + e);
839                 dumpHelp(writer);
840                 return;
841             }
842             if (keyCode == KeyEvent.KEYCODE_UNKNOWN) {
843                 writer.println("Missing key code or invalid keycode");
844                 dumpHelp(writer);
845                 return;
846             }
847             if (display != InputHalService.DISPLAY_MAIN
848                     && display != InputHalService.DISPLAY_INSTRUMENT_CLUSTER) {
849                 writer.println("Invalid display:" + display);
850                 dumpHelp(writer);
851                 return;
852             }
853             if (delayMs < 0) {
854                 writer.println("Invalid delay:" + delayMs);
855                 dumpHelp(writer);
856                 return;
857             }
858             KeyEvent keyDown = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
859             mCarInputService.onKeyEvent(keyDown, display);
860             SystemClock.sleep(delayMs);
861             KeyEvent keyUp = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
862             mCarInputService.onKeyEvent(keyUp, display);
863             writer.println("Succeeded");
864         }
865 
866         private void forceDayNightMode(String arg, PrintWriter writer) {
867             int mode;
868             switch (arg) {
869                 case PARAM_DAY_MODE:
870                     mode = CarNightService.FORCED_DAY_MODE;
871                     break;
872                 case PARAM_NIGHT_MODE:
873                     mode = CarNightService.FORCED_NIGHT_MODE;
874                     break;
875                 case PARAM_SENSOR_MODE:
876                     mode = CarNightService.FORCED_SENSOR_MODE;
877                     break;
878                 default:
879                     writer.println("Unknown value. Valid argument: " + PARAM_DAY_MODE + "|"
880                             + PARAM_NIGHT_MODE + "|" + PARAM_SENSOR_MODE);
881                     return;
882             }
883             int current = mCarNightService.forceDayNightMode(mode);
884             String currentMode = null;
885             switch (current) {
886                 case UiModeManager.MODE_NIGHT_AUTO:
887                     currentMode = PARAM_SENSOR_MODE;
888                     break;
889                 case UiModeManager.MODE_NIGHT_YES:
890                     currentMode = PARAM_NIGHT_MODE;
891                     break;
892                 case UiModeManager.MODE_NIGHT_NO:
893                     currentMode = PARAM_DAY_MODE;
894                     break;
895             }
896             writer.println("DayNightMode changed to: " + currentMode);
897         }
898 
899         private void forceGarageMode(String arg, PrintWriter writer) {
900             switch (arg) {
901                 case PARAM_ON_MODE:
902                     mGarageModeService.forceStartGarageMode();
903                     writer.println("Garage mode: " + mGarageModeService.isGarageModeActive());
904                     break;
905                 case PARAM_OFF_MODE:
906                     mGarageModeService.stopAndResetGarageMode();
907                     writer.println("Garage mode: " + mGarageModeService.isGarageModeActive());
908                     break;
909                 case PARAM_QUERY_MODE:
910                     mGarageModeService.dump(writer);
911                     break;
912                 case PARAM_REBOOT:
913                     mCarPowerManagementService.forceSuspendAndMaybeReboot(true);
914                     writer.println("Entering Garage Mode. Will reboot when it completes.");
915                     break;
916                 default:
917                     writer.println("Unknown value. Valid argument: " + PARAM_ON_MODE + "|"
918                             + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE + "|" + PARAM_REBOOT);
919             }
920         }
921 
922         /**
923          * Inject a fake  VHAL event
924          *
925          * @param property the Vehicle property Id as defined in the HAL
926          * @param zone     Zone that this event services
927          * @param isErrorEvent indicates the type of event
928          * @param value    Data value of the event
929          * @param writer   PrintWriter
930          */
931         private void injectVhalEvent(String property, String zone, String value,
932                 boolean isErrorEvent, PrintWriter writer) {
933             if (zone != null && (zone.equalsIgnoreCase(PARAM_VEHICLE_PROPERTY_AREA_GLOBAL))) {
934                 if (!isPropertyAreaTypeGlobal(property)) {
935                     writer.println("Property area type inconsistent with given zone");
936                     return;
937                 }
938             }
939             try {
940                 if (isErrorEvent) {
941                     mHal.injectOnPropertySetError(property, zone, value);
942                 } else {
943                     mHal.injectVhalEvent(property, zone, value);
944                 }
945             } catch (NumberFormatException e) {
946                 writer.println("Invalid property Id zone Id or value" + e);
947                 dumpHelp(writer);
948             }
949         }
950 
951         // Check if the given property is global
952         private boolean isPropertyAreaTypeGlobal(String property) {
953             if (property == null) {
954                 return false;
955             }
956             return (Integer.decode(property) & VehicleArea.MASK) == VehicleArea.GLOBAL;
957         }
958     }
959 }
960