Home | History | Annotate | Download | only in car
      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.UiModeManager;
     21 import android.car.Car;
     22 import android.car.ICar;
     23 import android.car.cluster.renderer.IInstrumentClusterNavigation;
     24 import android.car.user.CarUserManagerHelper;
     25 import android.content.Context;
     26 import android.content.pm.PackageManager;
     27 import android.hardware.automotive.vehicle.V2_0.IVehicle;
     28 import android.hardware.automotive.vehicle.V2_0.VehicleArea;
     29 import android.os.Binder;
     30 import android.os.Build;
     31 import android.os.IBinder;
     32 import android.os.Process;
     33 import android.os.Trace;
     34 import android.util.Log;
     35 import android.util.Slog;
     36 import android.util.TimingsTraceLog;
     37 
     38 import com.android.car.cluster.InstrumentClusterService;
     39 import com.android.car.hal.VehicleHal;
     40 import com.android.car.internal.FeatureConfiguration;
     41 import com.android.car.pm.CarPackageManagerService;
     42 import com.android.car.systeminterface.SystemInterface;
     43 import com.android.car.user.CarUserService;
     44 import com.android.internal.annotations.GuardedBy;
     45 import com.android.internal.car.ICarServiceHelper;
     46 
     47 import java.io.FileDescriptor;
     48 import java.io.PrintWriter;
     49 import java.util.ArrayList;
     50 import java.util.Arrays;
     51 import java.util.List;
     52 
     53 public class ICarImpl extends ICar.Stub {
     54 
     55     public static final String INTERNAL_INPUT_SERVICE = "internal_input";
     56     public static final String INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE =
     57             "system_activity_monitoring";
     58 
     59     private final Context mContext;
     60     private final VehicleHal mHal;
     61 
     62     private final SystemInterface mSystemInterface;
     63 
     64     private final SystemActivityMonitoringService mSystemActivityMonitoringService;
     65     private final CarPowerManagementService mCarPowerManagementService;
     66     private final CarPackageManagerService mCarPackageManagerService;
     67     private final CarInputService mCarInputService;
     68     private final CarDrivingStateService mCarDrivingStateService;
     69     private final CarUxRestrictionsManagerService mCarUXRestrictionsService;
     70     private final CarAudioService mCarAudioService;
     71     private final CarProjectionService mCarProjectionService;
     72     private final CarPropertyService mCarPropertyService;
     73     private final CarNightService mCarNightService;
     74     private final AppFocusService mAppFocusService;
     75     private final GarageModeService mGarageModeService;
     76     private final InstrumentClusterService mInstrumentClusterService;
     77     private final CarLocationService mCarLocationService;
     78     private final SystemStateControllerService mSystemStateControllerService;
     79     private final CarBluetoothService mCarBluetoothService;
     80     private final PerUserCarServiceHelper mPerUserCarServiceHelper;
     81     private final CarDiagnosticService mCarDiagnosticService;
     82     private final CarStorageMonitoringService mCarStorageMonitoringService;
     83     private final CarConfigurationService mCarConfigurationService;
     84 
     85     private final CarUserManagerHelper mUserManagerHelper;
     86     private CarUserService mCarUserService;
     87     private VmsSubscriberService mVmsSubscriberService;
     88     private VmsPublisherService mVmsPublisherService;
     89 
     90     private final CarServiceBase[] mAllServices;
     91 
     92     private static final String TAG = "ICarImpl";
     93     private static final String VHAL_TIMING_TAG = "VehicleHalTiming";
     94     private static final TimingsTraceLog mBootTiming = new TimingsTraceLog(VHAL_TIMING_TAG,
     95             Trace.TRACE_TAG_HAL);
     96 
     97     /** Test only service. Populate it only when necessary. */
     98     @GuardedBy("this")
     99     private CarTestService mCarTestService;
    100 
    101     @GuardedBy("this")
    102     private ICarServiceHelper mICarServiceHelper;
    103 
    104     private final String mVehicleInterfaceName;
    105 
    106     public ICarImpl(Context serviceContext, IVehicle vehicle, SystemInterface systemInterface,
    107             CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
    108         mContext = serviceContext;
    109         mSystemInterface = systemInterface;
    110         mHal = new VehicleHal(vehicle);
    111         mVehicleInterfaceName = vehicleInterfaceName;
    112         mSystemActivityMonitoringService = new SystemActivityMonitoringService(serviceContext);
    113         mCarPowerManagementService = new CarPowerManagementService(mContext, mHal.getPowerHal(),
    114                 systemInterface);
    115         mCarPropertyService = new CarPropertyService(serviceContext, mHal.getPropertyHal());
    116         mCarDrivingStateService = new CarDrivingStateService(serviceContext, mCarPropertyService);
    117         mCarUXRestrictionsService = new CarUxRestrictionsManagerService(serviceContext,
    118                 mCarDrivingStateService, mCarPropertyService);
    119         mCarPackageManagerService = new CarPackageManagerService(serviceContext,
    120                 mCarUXRestrictionsService,
    121                 mSystemActivityMonitoringService);
    122         mCarInputService = new CarInputService(serviceContext, mHal.getInputHal());
    123         mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService);
    124         mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
    125         mCarLocationService = new CarLocationService(mContext, mCarPowerManagementService,
    126                 mCarPropertyService);
    127         mAppFocusService = new AppFocusService(serviceContext, mSystemActivityMonitoringService);
    128         mCarAudioService = new CarAudioService(serviceContext);
    129         mCarNightService = new CarNightService(serviceContext, mCarPropertyService);
    130         mInstrumentClusterService = new InstrumentClusterService(serviceContext,
    131                 mAppFocusService, mCarInputService);
    132         mSystemStateControllerService = new SystemStateControllerService(serviceContext,
    133                 mCarPowerManagementService, mCarAudioService, this);
    134         mPerUserCarServiceHelper = new PerUserCarServiceHelper(serviceContext);
    135         mCarBluetoothService = new CarBluetoothService(serviceContext, mCarPropertyService,
    136                 mPerUserCarServiceHelper, mCarUXRestrictionsService);
    137         mVmsSubscriberService = new VmsSubscriberService(serviceContext, mHal.getVmsHal());
    138         mVmsPublisherService = new VmsPublisherService(serviceContext, mHal.getVmsHal());
    139         mCarDiagnosticService = new CarDiagnosticService(serviceContext, mHal.getDiagnosticHal());
    140         mCarStorageMonitoringService = new CarStorageMonitoringService(serviceContext,
    141                 systemInterface);
    142         mCarConfigurationService =
    143                 new CarConfigurationService(serviceContext, new JsonReaderImpl());
    144         mUserManagerHelper = new CarUserManagerHelper(serviceContext);
    145 
    146         // Be careful with order. Service depending on other service should be inited later.
    147         List<CarServiceBase> allServices = new ArrayList<>();
    148         allServices.add(mSystemActivityMonitoringService);
    149         allServices.add(mCarPowerManagementService);
    150         allServices.add(mCarPropertyService);
    151         allServices.add(mCarDrivingStateService);
    152         allServices.add(mCarUXRestrictionsService);
    153         allServices.add(mCarPackageManagerService);
    154         allServices.add(mCarInputService);
    155         allServices.add(mCarLocationService);
    156         allServices.add(mGarageModeService);
    157         allServices.add(mAppFocusService);
    158         allServices.add(mCarAudioService);
    159         allServices.add(mCarNightService);
    160         allServices.add(mInstrumentClusterService);
    161         allServices.add(mCarProjectionService);
    162         allServices.add(mSystemStateControllerService);
    163         allServices.add(mCarBluetoothService);
    164         allServices.add(mCarDiagnosticService);
    165         allServices.add(mPerUserCarServiceHelper);
    166         allServices.add(mCarStorageMonitoringService);
    167         allServices.add(mCarConfigurationService);
    168         allServices.add(mVmsSubscriberService);
    169         allServices.add(mVmsPublisherService);
    170 
    171         if (mUserManagerHelper.isHeadlessSystemUser()) {
    172             mCarUserService = new CarUserService(serviceContext, mUserManagerHelper);
    173             allServices.add(mCarUserService);
    174         }
    175 
    176         mAllServices = allServices.toArray(new CarServiceBase[allServices.size()]);
    177     }
    178 
    179     @MainThread
    180     void init() {
    181         traceBegin("VehicleHal.init");
    182         mHal.init();
    183         traceEnd();
    184         traceBegin("CarService.initAllServices");
    185         for (CarServiceBase service : mAllServices) {
    186             service.init();
    187         }
    188         traceEnd();
    189     }
    190 
    191     void release() {
    192         // release done in opposite order from init
    193         for (int i = mAllServices.length - 1; i >= 0; i--) {
    194             mAllServices[i].release();
    195         }
    196         mHal.release();
    197     }
    198 
    199     void vehicleHalReconnected(IVehicle vehicle) {
    200         mHal.vehicleHalReconnected(vehicle);
    201         for (CarServiceBase service : mAllServices) {
    202             service.vehicleHalReconnected();
    203         }
    204     }
    205 
    206     @Override
    207     public void setCarServiceHelper(IBinder helper) {
    208         int uid = Binder.getCallingUid();
    209         if (uid != Process.SYSTEM_UID) {
    210             throw new SecurityException("Only allowed from system");
    211         }
    212         synchronized (this) {
    213             mICarServiceHelper = ICarServiceHelper.Stub.asInterface(helper);
    214             mSystemInterface.setCarServiceHelper(mICarServiceHelper);
    215         }
    216     }
    217 
    218     @Override
    219     public IBinder getCarService(String serviceName) {
    220         switch (serviceName) {
    221             case Car.AUDIO_SERVICE:
    222                 return mCarAudioService;
    223             case Car.APP_FOCUS_SERVICE:
    224                 return mAppFocusService;
    225             case Car.PACKAGE_SERVICE:
    226                 return mCarPackageManagerService;
    227             case Car.DIAGNOSTIC_SERVICE:
    228                 assertAnyDiagnosticPermission(mContext);
    229                 return mCarDiagnosticService;
    230             case Car.POWER_SERVICE:
    231                 assertPowerPermission(mContext);
    232                 return mCarPowerManagementService;
    233             case Car.CABIN_SERVICE:
    234             case Car.HVAC_SERVICE:
    235             case Car.INFO_SERVICE:
    236             case Car.PROPERTY_SERVICE:
    237             case Car.SENSOR_SERVICE:
    238             case Car.VENDOR_EXTENSION_SERVICE:
    239                 return mCarPropertyService;
    240             case Car.CAR_NAVIGATION_SERVICE:
    241                 assertNavigationManagerPermission(mContext);
    242                 IInstrumentClusterNavigation navService =
    243                         mInstrumentClusterService.getNavigationService();
    244                 return navService == null ? null : navService.asBinder();
    245             case Car.CAR_INSTRUMENT_CLUSTER_SERVICE:
    246                 assertClusterManagerPermission(mContext);
    247                 return mInstrumentClusterService.getManagerService();
    248             case Car.PROJECTION_SERVICE:
    249                 assertProjectionPermission(mContext);
    250                 return mCarProjectionService;
    251             case Car.VMS_SUBSCRIBER_SERVICE:
    252                 assertVmsSubscriberPermission(mContext);
    253                 return mVmsSubscriberService;
    254             case Car.TEST_SERVICE: {
    255                 assertPermission(mContext, Car.PERMISSION_CAR_TEST_SERVICE);
    256                 synchronized (this) {
    257                     if (mCarTestService == null) {
    258                         mCarTestService = new CarTestService(mContext, this);
    259                     }
    260                     return mCarTestService;
    261                 }
    262             }
    263             case Car.BLUETOOTH_SERVICE:
    264                 return mCarBluetoothService;
    265             case Car.STORAGE_MONITORING_SERVICE:
    266                 assertPermission(mContext, Car.PERMISSION_STORAGE_MONITORING);
    267                 return mCarStorageMonitoringService;
    268             case Car.CAR_DRIVING_STATE_SERVICE:
    269                 assertDrivingStatePermission(mContext);
    270                 return mCarDrivingStateService;
    271             case Car.CAR_UX_RESTRICTION_SERVICE:
    272                 return mCarUXRestrictionsService;
    273             case Car.CAR_CONFIGURATION_SERVICE:
    274                 return mCarConfigurationService;
    275             default:
    276                 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
    277                 return null;
    278         }
    279     }
    280 
    281     @Override
    282     public int getCarConnectionType() {
    283         return Car.CONNECTION_TYPE_EMBEDDED;
    284     }
    285 
    286     public CarServiceBase getCarInternalService(String serviceName) {
    287         switch (serviceName) {
    288             case INTERNAL_INPUT_SERVICE:
    289                 return mCarInputService;
    290             case INTERNAL_SYSTEM_ACTIVITY_MONITORING_SERVICE:
    291                 return mSystemActivityMonitoringService;
    292             default:
    293                 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" +
    294                         serviceName);
    295                 return null;
    296         }
    297     }
    298 
    299     public static void assertVehicleHalMockPermission(Context context) {
    300         assertPermission(context, Car.PERMISSION_MOCK_VEHICLE_HAL);
    301     }
    302 
    303     public static void assertNavigationManagerPermission(Context context) {
    304         assertPermission(context, Car.PERMISSION_CAR_NAVIGATION_MANAGER);
    305     }
    306 
    307     public static void assertClusterManagerPermission(Context context) {
    308         assertPermission(context, Car.PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL);
    309     }
    310 
    311     public static void assertPowerPermission(Context context) {
    312         assertPermission(context, Car.PERMISSION_CAR_POWER);
    313     }
    314 
    315     public static void assertProjectionPermission(Context context) {
    316         assertPermission(context, Car.PERMISSION_CAR_PROJECTION);
    317     }
    318 
    319     public static void assertAnyDiagnosticPermission(Context context) {
    320         assertAnyPermission(context,
    321                 Car.PERMISSION_CAR_DIAGNOSTIC_READ_ALL,
    322                 Car.PERMISSION_CAR_DIAGNOSTIC_CLEAR);
    323     }
    324 
    325     public static void assertDrivingStatePermission(Context context) {
    326         assertPermission(context, Car.PERMISSION_CAR_DRIVING_STATE);
    327     }
    328 
    329     public static void assertVmsPublisherPermission(Context context) {
    330         assertPermission(context, Car.PERMISSION_VMS_PUBLISHER);
    331     }
    332 
    333     public static void assertVmsSubscriberPermission(Context context) {
    334         assertPermission(context, Car.PERMISSION_VMS_SUBSCRIBER);
    335     }
    336 
    337     public static void assertPermission(Context context, String permission) {
    338         if (context.checkCallingOrSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
    339             throw new SecurityException("requires " + permission);
    340         }
    341     }
    342 
    343     /**
    344      * Checks to see if the caller has a permission.
    345      * @param context
    346      * @param permission
    347      *
    348      * @return boolean TRUE if caller has the permission.
    349      */
    350     public static boolean hasPermission(Context context, String permission) {
    351         return context.checkCallingOrSelfPermission(permission)
    352                 == PackageManager.PERMISSION_GRANTED;
    353     }
    354 
    355     public static void assertAnyPermission(Context context, String... permissions) {
    356         for (String permission : permissions) {
    357             if (context.checkCallingOrSelfPermission(permission) ==
    358                     PackageManager.PERMISSION_GRANTED) {
    359                 return;
    360             }
    361         }
    362         throw new SecurityException("requires any of " + Arrays.toString(permissions));
    363     }
    364 
    365     @Override
    366     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
    367         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
    368                 != PackageManager.PERMISSION_GRANTED) {
    369             writer.println("Permission Denial: can't dump CarService from from pid="
    370                     + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
    371                     + " without permission " + android.Manifest.permission.DUMP);
    372             return;
    373         }
    374         if (args == null || args.length == 0) {
    375             writer.println("*dump car service*");
    376 
    377             writer.println("*FutureConfig, DEFAULT:" + FeatureConfiguration.DEFAULT);
    378             writer.println("*Dump all services*");
    379             for (CarServiceBase service : mAllServices) {
    380                 dumpService(service, writer);
    381             }
    382             if (mCarTestService != null) {
    383                 dumpService(mCarTestService, writer);
    384             }
    385             writer.println("*Dump Vehicle HAL*");
    386             writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName);
    387             try {
    388                 // TODO dump all feature flags by creating a dumpable interface
    389                 mHal.dump(writer);
    390             } catch (Exception e) {
    391                 writer.println("Failed dumping: " + mHal.getClass().getName());
    392                 e.printStackTrace(writer);
    393             }
    394         } else if (Build.IS_USERDEBUG || Build.IS_ENG) {
    395             execShellCmd(args, writer);
    396         } else {
    397             writer.println("Commands not supported in " + Build.TYPE);
    398         }
    399     }
    400 
    401     private void dumpService(CarServiceBase service, PrintWriter writer) {
    402         try {
    403             service.dump(writer);
    404         } catch (Exception e) {
    405             writer.println("Failed dumping: " + service.getClass().getName());
    406             e.printStackTrace(writer);
    407         }
    408     }
    409 
    410     void execShellCmd(String[] args, PrintWriter writer) {
    411         new CarShellCommand().exec(args, writer);
    412     }
    413 
    414     @MainThread
    415     private static void traceBegin(String name) {
    416         Slog.i(TAG, name);
    417         mBootTiming.traceBegin(name);
    418     }
    419 
    420     @MainThread
    421     private static void traceEnd() {
    422         mBootTiming.traceEnd();
    423     }
    424 
    425     private class CarShellCommand {
    426         private static final String COMMAND_HELP = "-h";
    427         private static final String COMMAND_DAY_NIGHT_MODE = "day-night-mode";
    428         private static final String COMMAND_INJECT_VHAL_EVENT = "inject-vhal-event";
    429         private static final String COMMAND_ENABLE_UXR = "enable-uxr";
    430         private static final String COMMAND_GARAGE_MODE = "garage-mode";
    431         private static final String COMMAND_GET_DO_ACTIVITIES = "get-do-activities";
    432 
    433         private static final String PARAM_DAY_MODE = "day";
    434         private static final String PARAM_NIGHT_MODE = "night";
    435         private static final String PARAM_SENSOR_MODE = "sensor";
    436         private static final String PARAM_VEHICLE_PROPERTY_AREA_GLOBAL = "0";
    437         private static final String PARAM_ON_MODE = "on";
    438         private static final String PARAM_OFF_MODE = "off";
    439         private static final String PARAM_QUERY_MODE = "query";
    440 
    441 
    442         private void dumpHelp(PrintWriter pw) {
    443             pw.println("Car service commands:");
    444             pw.println("\t-h");
    445             pw.println("\t  Print this help text.");
    446             pw.println("\tday-night-mode [day|night|sensor]");
    447             pw.println("\t  Force into day/night mode or restore to auto.");
    448             pw.println("\tinject-vhal-event property [zone] data(can be comma separated list)");
    449             pw.println("\t  Inject a vehicle property for testing");
    450             pw.println("\tdisable-uxr true|false");
    451             pw.println("\t  Disable UX restrictions and App blocking.");
    452             pw.println("\tgarage-mode [on|off|query]");
    453             pw.println("\t  Force into garage mode or check status.");
    454             pw.println("\tget-do-activities pkgname");
    455             pw.println("\t Get Distraction Optimized activities in given package");
    456         }
    457 
    458         public void exec(String[] args, PrintWriter writer) {
    459             String arg = args[0];
    460             switch (arg) {
    461                 case COMMAND_HELP:
    462                     dumpHelp(writer);
    463                     break;
    464                 case COMMAND_DAY_NIGHT_MODE: {
    465                     String value = args.length < 1 ? "" : args[1];
    466                     forceDayNightMode(value, writer);
    467                     break;
    468                 }
    469                 case COMMAND_GARAGE_MODE: {
    470                     String value = args.length < 1 ? "" : args[1];
    471                     forceGarageMode(value, writer);
    472                     break;
    473                 }
    474                 case COMMAND_INJECT_VHAL_EVENT:
    475                     String zone = PARAM_VEHICLE_PROPERTY_AREA_GLOBAL;
    476                     String data;
    477                     if (args.length < 3) {
    478                         writer.println("Incorrect number of arguments.");
    479                         dumpHelp(writer);
    480                         break;
    481                     } else if (args.length > 3) {
    482                         // Zoned
    483                         zone = args[2];
    484                         data = args[3];
    485                     } else {
    486                         // Global
    487                         data = args[2];
    488                     }
    489                     injectVhalEvent(args[1], zone, data, writer);
    490                     break;
    491                 case COMMAND_ENABLE_UXR:
    492                     if (args.length < 2) {
    493                         writer.println("Incorrect number of arguments");
    494                         dumpHelp(writer);
    495                         break;
    496                     }
    497                     boolean enableBlocking = Boolean.valueOf(args[1]);
    498                     if (mCarPackageManagerService != null) {
    499                         mCarPackageManagerService.setEnableActivityBlocking(enableBlocking);
    500                     }
    501                     break;
    502                 case COMMAND_GET_DO_ACTIVITIES:
    503                     if (args.length < 2) {
    504                         writer.println("Incorrect number of arguments");
    505                         dumpHelp(writer);
    506                         break;
    507                     }
    508                     String pkgName = args[1].toLowerCase();
    509                     if (mCarPackageManagerService != null) {
    510                         String[] doActivities =
    511                                 mCarPackageManagerService.getDistractionOptimizedActivities(
    512                                         pkgName);
    513                         if (doActivities != null) {
    514                             writer.println("DO Activities for " + pkgName);
    515                             for (String a : doActivities) {
    516                                 writer.println(a);
    517                             }
    518                         } else {
    519                             writer.println("No DO Activities for " + pkgName);
    520                         }
    521                     }
    522                     break;
    523                 default:
    524                     writer.println("Unknown command.");
    525                     dumpHelp(writer);
    526             }
    527         }
    528 
    529         private void forceDayNightMode(String arg, PrintWriter writer) {
    530             int mode;
    531             switch (arg) {
    532                 case PARAM_DAY_MODE:
    533                     mode = CarNightService.FORCED_DAY_MODE;
    534                     break;
    535                 case PARAM_NIGHT_MODE:
    536                     mode = CarNightService.FORCED_NIGHT_MODE;
    537                     break;
    538                 case PARAM_SENSOR_MODE:
    539                     mode = CarNightService.FORCED_SENSOR_MODE;
    540                     break;
    541                 default:
    542                     writer.println("Unknown value. Valid argument: " + PARAM_DAY_MODE + "|"
    543                             + PARAM_NIGHT_MODE + "|" + PARAM_SENSOR_MODE);
    544                     return;
    545             }
    546             int current = mCarNightService.forceDayNightMode(mode);
    547             String currentMode = null;
    548             switch (current) {
    549                 case UiModeManager.MODE_NIGHT_AUTO:
    550                     currentMode = PARAM_SENSOR_MODE;
    551                     break;
    552                 case UiModeManager.MODE_NIGHT_YES:
    553                     currentMode = PARAM_NIGHT_MODE;
    554                     break;
    555                 case UiModeManager.MODE_NIGHT_NO:
    556                     currentMode = PARAM_DAY_MODE;
    557                     break;
    558             }
    559             writer.println("DayNightMode changed to: " + currentMode);
    560         }
    561 
    562         private void forceGarageMode(String arg, PrintWriter writer) {
    563             switch (arg) {
    564                 case PARAM_ON_MODE:
    565                     mGarageModeService.onPrepareShutdown(false);
    566                     break;
    567                 case PARAM_OFF_MODE:
    568                     mGarageModeService.onSleepEntry();
    569                     break;
    570                 case PARAM_QUERY_MODE:
    571                     // Nothing to do. Always query at the end anyway.
    572                     break;
    573                 default:
    574                     writer.println("Unknown value. Valid argument: " + PARAM_ON_MODE + "|"
    575                             + PARAM_OFF_MODE + "|" + PARAM_QUERY_MODE);
    576                     return;
    577             }
    578             writer.println("Garage mode: " + mGarageModeService.isInGarageMode());
    579         }
    580 
    581         /**
    582          * Inject a fake  VHAL event
    583          *
    584          * @param property the Vehicle property Id as defined in the HAL
    585          * @param zone     Zone that this event services
    586          * @param value    Data value of the event
    587          * @param writer   PrintWriter
    588          */
    589         private void injectVhalEvent(String property, String zone, String value,
    590                 PrintWriter writer) {
    591             if (zone != null && (zone.equalsIgnoreCase(PARAM_VEHICLE_PROPERTY_AREA_GLOBAL))) {
    592                 if (!isPropertyAreaTypeGlobal(property)) {
    593                     writer.println("Property area type inconsistent with given zone");
    594                     return;
    595                 }
    596             }
    597             try {
    598                 mHal.injectVhalEvent(property, zone, value);
    599             } catch (NumberFormatException e) {
    600                 writer.println("Invalid property Id zone Id or value" + e);
    601                 dumpHelp(writer);
    602             }
    603         }
    604 
    605         // Check if the given property is global
    606         private boolean isPropertyAreaTypeGlobal(String property) {
    607             if (property == null) {
    608                 return false;
    609             }
    610             return (Integer.decode(property) & VehicleArea.MASK) == VehicleArea.GLOBAL;
    611         }
    612     }
    613 }
    614