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