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 android.car;
     18 
     19 import android.annotation.IntDef;
     20 import android.annotation.Nullable;
     21 import android.annotation.SystemApi;
     22 import android.car.cluster.CarInstrumentClusterManager;
     23 import android.car.content.pm.CarPackageManager;
     24 import android.car.diagnostic.CarDiagnosticManager;
     25 import android.car.drivingstate.CarDrivingStateManager;
     26 import android.car.drivingstate.CarUxRestrictionsManager;
     27 import android.car.hardware.CarSensorManager;
     28 import android.car.hardware.CarVendorExtensionManager;
     29 import android.car.hardware.cabin.CarCabinManager;
     30 import android.car.hardware.hvac.CarHvacManager;
     31 import android.car.hardware.power.CarPowerManager;
     32 import android.car.hardware.property.CarPropertyManager;
     33 import android.car.media.CarAudioManager;
     34 import android.car.navigation.CarNavigationStatusManager;
     35 import android.car.settings.CarConfigurationManager;
     36 import android.car.storagemonitoring.CarStorageMonitoringManager;
     37 import android.car.test.CarTestManagerBinderWrapper;
     38 import android.car.vms.VmsSubscriberManager;
     39 import android.content.ComponentName;
     40 import android.content.Context;
     41 import android.content.Intent;
     42 import android.content.ServiceConnection;
     43 import android.content.pm.PackageManager;
     44 import android.os.Handler;
     45 import android.os.IBinder;
     46 import android.os.Looper;
     47 import android.os.RemoteException;
     48 import android.os.UserHandle;
     49 import android.util.Log;
     50 
     51 import com.android.internal.annotations.GuardedBy;
     52 
     53 import java.lang.annotation.Retention;
     54 import java.lang.annotation.RetentionPolicy;
     55 import java.util.HashMap;
     56 
     57 /**
     58  *   Top level car API for embedded Android Auto deployments.
     59  *   This API works only for devices with {@link PackageManager#FEATURE_AUTOMOTIVE}
     60  *   Calling this API on a device with no such feature will lead to an exception.
     61  */
     62 public final class Car {
     63 
     64     /**
     65      * Represent the version of Car API. This is only updated when there is API change.
     66      * 1 : N
     67      * 2 : O
     68      * 3 : O-MR1
     69      */
     70     public static final int VERSION = 3;
     71 
     72     /** Service name for {@link CarSensorManager}, to be used in {@link #getCarManager(String)}. */
     73     public static final String SENSOR_SERVICE = "sensor";
     74 
     75     /** Service name for {@link CarInfoManager}, to be used in {@link #getCarManager(String)}. */
     76     public static final String INFO_SERVICE = "info";
     77 
     78     /** Service name for {@link CarAppFocusManager}. */
     79     public static final String APP_FOCUS_SERVICE = "app_focus";
     80 
     81     /** Service name for {@link CarPackageManager} */
     82     public static final String PACKAGE_SERVICE = "package";
     83 
     84     /** Service name for {@link CarAudioManager} */
     85     public static final String AUDIO_SERVICE = "audio";
     86 
     87     /** Service name for {@link CarNavigationStatusManager} */
     88     public static final String CAR_NAVIGATION_SERVICE = "car_navigation_service";
     89 
     90     /**
     91      * Service name for {@link CarInstrumentClusterManager}
     92      * @hide
     93      */
     94     public static final String CAR_INSTRUMENT_CLUSTER_SERVICE = "cluster_service";
     95 
     96     /**
     97      * @hide
     98      */
     99     @SystemApi
    100     public static final String CABIN_SERVICE = "cabin";
    101 
    102     /**
    103      * @hide
    104      */
    105     @SystemApi
    106     public static final String DIAGNOSTIC_SERVICE = "diagnostic";
    107 
    108     /**
    109      * @hide
    110      */
    111     @SystemApi
    112     public static final String HVAC_SERVICE = "hvac";
    113 
    114     /**
    115      * @hide
    116      */
    117     @SystemApi
    118     public static final String POWER_SERVICE = "power";
    119 
    120     /**
    121      * @hide
    122      */
    123     @SystemApi
    124     public static final String PROJECTION_SERVICE = "projection";
    125 
    126     /**
    127      * @hide
    128      */
    129     @SystemApi
    130     public static final String PROPERTY_SERVICE = "property";
    131 
    132     /**
    133      * @hide
    134      */
    135     @SystemApi
    136     public static final String VENDOR_EXTENSION_SERVICE = "vendor_extension";
    137 
    138     /**
    139      * @hide
    140      */
    141     public static final String BLUETOOTH_SERVICE = "car_bluetooth";
    142 
    143     /**
    144      * @hide
    145      */
    146     @SystemApi
    147     public static final String VMS_SUBSCRIBER_SERVICE = "vehicle_map_subscriber_service";
    148 
    149     /**
    150      * Service name for {@link CarDrivingStateManager}
    151      * @hide
    152      */
    153     @SystemApi
    154     public static final String CAR_DRIVING_STATE_SERVICE = "drivingstate";
    155 
    156     /**
    157      * Service name for {@link CarUxRestrictionsManager}
    158      */
    159     public static final String CAR_UX_RESTRICTION_SERVICE = "uxrestriction";
    160 
    161     /**
    162      * Service name for {@link android.car.settings.CarConfigurationManager}
    163      */
    164     public static final String CAR_CONFIGURATION_SERVICE = "configuration";
    165 
    166     /**
    167      * @hide
    168      */
    169     @SystemApi
    170     public static final String STORAGE_MONITORING_SERVICE = "storage_monitoring";
    171 
    172     /**
    173      * Service for testing. This is system app only feature.
    174      * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}.
    175      * @hide
    176      */
    177     @SystemApi
    178     public static final String TEST_SERVICE = "car-service-test";
    179 
    180     /** Permission necessary to access car's mileage information.
    181      *  @hide
    182      */
    183     @SystemApi
    184     public static final String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
    185 
    186     /** Permission necessary to access car's energy information. */
    187     public static final String PERMISSION_ENERGY = "android.car.permission.CAR_ENERGY";
    188 
    189     /** Permission necessary to access car's VIN information */
    190     public static final String PERMISSION_IDENTIFICATION =
    191             "android.car.permission.CAR_IDENTIFICATION";
    192 
    193     /** Permission necessary to access car's speed. */
    194     public static final String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
    195 
    196     /** Permission necessary to access car's dynamics state.
    197      *  @hide
    198      */
    199     @SystemApi
    200     public static final String PERMISSION_CAR_DYNAMICS_STATE =
    201             "android.car.permission.CAR_DYNAMICS_STATE";
    202 
    203     /** Permission necessary to access car's fuel door and ev charge port. */
    204     public static final String PERMISSION_ENERGY_PORTS = "android.car.permission.CAR_ENERGY_PORTS";
    205 
    206     /** Permission necessary to read car's lights information.
    207      *  @hide
    208      */
    209     @SystemApi
    210     public static final String PERMISSION_EXTERIOR_LIGHTS =
    211             "android.car.permission.CAR_EXTERIOR_LIGHTS";
    212 
    213     /** Permission necessary to control car's exterior lights.
    214      *  @hide
    215      */
    216     @SystemApi
    217     public static final String PERMISSION_CONTROL_EXTERIOR_LIGHTS =
    218             "android.car.permission.CONTROL_CAR_EXTERIOR_LIGHTS";
    219 
    220     /** Permission necessary to access car's powertrain information.*/
    221     public static final String PERMISSION_POWERTRAIN = "android.car.permission.CAR_POWERTRAIN";
    222 
    223     /**
    224      * Permission necessary to change car audio volume through {@link CarAudioManager}.
    225      */
    226     public static final String PERMISSION_CAR_CONTROL_AUDIO_VOLUME =
    227             "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
    228 
    229     /**
    230      * Permission necessary to change car audio settings through {@link CarAudioManager}.
    231      * @hide
    232      */
    233     public static final String PERMISSION_CAR_CONTROL_AUDIO_SETTINGS =
    234             "android.car.permission.CAR_CONTROL_AUDIO_SETTINGS";
    235 
    236     /**
    237      * Permission necessary to use {@link CarNavigationStatusManager}.
    238      */
    239     public static final String PERMISSION_CAR_NAVIGATION_MANAGER =
    240             "android.car.permission.CAR_NAVIGATION_MANAGER";
    241 
    242     /**
    243      * Permission necessary to start activities in the instrument cluster through
    244      * {@link CarInstrumentClusterManager}
    245      *
    246      * @hide
    247      */
    248     @SystemApi
    249     public static final String PERMISSION_CAR_INSTRUMENT_CLUSTER_CONTROL =
    250             "android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL";
    251 
    252     /**
    253      * Application must have this permission in order to be launched in the instrument cluster
    254      * display.
    255      *
    256      * @hide
    257      */
    258     public static final String PERMISSION_CAR_DISPLAY_IN_CLUSTER =
    259             "android.car.permission.CAR_DISPLAY_IN_CLUSTER";
    260 
    261     /** Permission necessary to use {@link CarInfoManager}. */
    262     public static final String PERMISSION_CAR_INFO = "android.car.permission.CAR_INFO";
    263 
    264     /** Permission necessary to read temperature of car's exterior environment. */
    265     public static final String PERMISSION_EXTERIOR_ENVIRONMENT =
    266             "android.car.permission.CAR_EXTERIOR_ENVIRONMENT";
    267 
    268     /**
    269      * Permission necessary to access car specific communication channel.
    270      * @hide
    271      */
    272     @SystemApi
    273     public static final String PERMISSION_VENDOR_EXTENSION =
    274             "android.car.permission.CAR_VENDOR_EXTENSION";
    275 
    276     /**
    277      * @hide
    278      */
    279     @SystemApi
    280     public static final String PERMISSION_CONTROL_APP_BLOCKING =
    281             "android.car.permission.CONTROL_APP_BLOCKING";
    282 
    283     /**
    284      * Permission necessary to access Car Cabin APIs.
    285      * @hide
    286      */
    287     @SystemApi
    288     public static final String PERMISSION_ADJUST_CAR_CABIN =
    289             "android.car.permission.ADJUST_CAR_CABIN";
    290 
    291     /**
    292      * Permission necessary to access car's engine information.
    293      * @hide
    294      */
    295     @SystemApi
    296     public static final String PERMISSION_CAR_ENGINE_DETAILED =
    297             "android.car.permission.CAR_ENGINE_DETAILED";
    298 
    299     /**
    300      * Permission necessary to access car's tire pressure information.
    301      * @hide
    302      */
    303     @SystemApi
    304     public static final String PERMISSION_TIRES = "android.car.permission.CAR_TIRES";
    305 
    306     /**
    307      * Permission necessary to control car's door.
    308      * @hide
    309      */
    310     @SystemApi
    311     public static final String PERMISSION_CONTROL_CAR_DOORS =
    312             "android.car.permission.CONTROL_CAR_DOORS";
    313 
    314     /**
    315      * Permission necessary to control car's windows.
    316      * @hide
    317      */
    318     @SystemApi
    319     public static final String PERMISSION_CONTROL_CAR_WINDOWS =
    320             "android.car.permission.CONTROL_CAR_WINDOWS";
    321 
    322     /**
    323      * Permission necessary to control car's seats.
    324      * @hide
    325      */
    326     @SystemApi
    327     public static final String PERMISSION_CONTROL_CAR_SEATS =
    328             "android.car.permission.CONTROL_CAR_SEATS";
    329 
    330     /**
    331      * Permission necessary to control car's mirrors.
    332      * @hide
    333      */
    334     @SystemApi
    335     public static final String PERMISSION_CONTROL_CAR_MIRRORS =
    336             "android.car.permission.CONTROL_CAR_MIRRORS";
    337 
    338     /**
    339      * Permission necessary to access Car HVAC APIs.
    340      * @hide
    341      */
    342     @SystemApi
    343     public static final String PERMISSION_CONTROL_CAR_CLIMATE =
    344             "android.car.permission.CONTROL_CAR_CLIMATE";
    345 
    346     /**
    347      * Permission necessary to access Car POWER APIs.
    348      * @hide
    349      */
    350     @SystemApi
    351     public static final String PERMISSION_CAR_POWER = "android.car.permission.CAR_POWER";
    352 
    353     /**
    354      * Permission necessary to access Car PROJECTION system APIs.
    355      * @hide
    356      */
    357     @SystemApi
    358     public static final String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
    359 
    360     /**
    361      * Permission necessary to mock vehicle hal for testing.
    362      * @hide
    363      * @deprecated mocking vehicle HAL in car service is no longer supported.
    364      */
    365     @SystemApi
    366     public static final String PERMISSION_MOCK_VEHICLE_HAL =
    367             "android.car.permission.CAR_MOCK_VEHICLE_HAL";
    368 
    369     /**
    370      * Permission necessary to access CarTestService.
    371      * @hide
    372      */
    373     @SystemApi
    374     public static final String PERMISSION_CAR_TEST_SERVICE =
    375             "android.car.permission.CAR_TEST_SERVICE";
    376 
    377     /**
    378      * Permission necessary to access CarDrivingStateService to get a Car's driving state.
    379      * @hide
    380      */
    381     @SystemApi
    382     public static final String PERMISSION_CAR_DRIVING_STATE =
    383             "android.car.permission.CAR_DRIVING_STATE";
    384 
    385     /**
    386      * Permissions necessary to access VMS publisher APIs.
    387      *
    388      * @hide
    389      */
    390     @SystemApi
    391     public static final String PERMISSION_VMS_PUBLISHER = "android.car.permission.VMS_PUBLISHER";
    392 
    393     /**
    394      * Permissions necessary to access VMS subscriber APIs.
    395      *
    396      * @hide
    397      */
    398     @SystemApi
    399     public static final String PERMISSION_VMS_SUBSCRIBER = "android.car.permission.VMS_SUBSCRIBER";
    400 
    401     /**
    402      * Permissions necessary to read diagnostic information, including vendor-specific bits.
    403      *
    404      * @hide
    405      */
    406     @SystemApi
    407     public static final String PERMISSION_CAR_DIAGNOSTIC_READ_ALL =
    408         "android.car.permission.CAR_DIAGNOSTICS";
    409 
    410     /**
    411      * Permissions necessary to clear diagnostic information.
    412      *
    413      * @hide
    414      */
    415     @SystemApi
    416     public static final String PERMISSION_CAR_DIAGNOSTIC_CLEAR = "android.car.permission.CLEAR_CAR_DIAGNOSTICS";
    417 
    418     /**
    419      * Permissions necessary to clear diagnostic information.
    420      *
    421      * @hide
    422      */
    423     @SystemApi
    424     public static final String PERMISSION_STORAGE_MONITORING = "android.car.permission.STORAGE_MONITORING";
    425 
    426     /** Type of car connection: platform runs directly in car. */
    427     public static final int CONNECTION_TYPE_EMBEDDED = 5;
    428 
    429 
    430     /** @hide */
    431     @IntDef({CONNECTION_TYPE_EMBEDDED})
    432     @Retention(RetentionPolicy.SOURCE)
    433     public @interface ConnectionType {}
    434 
    435     /**
    436      * CarXyzService throws IllegalStateException with this message is re-thrown as
    437      * {@link CarNotConnectedException}.
    438      *
    439      * @hide
    440      */
    441     public static final String CAR_NOT_CONNECTED_EXCEPTION_MSG = "CarNotConnected";
    442 
    443     /**
    444      * Activity Action: Provide media playing through a media template app.
    445      * <p>Input: String extra mapped by {@link android.app.SearchManager#QUERY} is the query
    446      * used to start the media. String extra mapped by {@link #CAR_EXTRA_MEDIA_PACKAGE} is the
    447      * package name of the media app which user wants to play media on.
    448      * <p>Output: nothing.
    449      */
    450     public static final String CAR_INTENT_ACTION_MEDIA_TEMPLATE =
    451             "android.car.intent.action.MEDIA_TEMPLATE";
    452 
    453     /**
    454      * Used as a string extra field with {@link #CAR_INTENT_ACTION_MEDIA_TEMPLATE} to specify the
    455      * media app that user wants to start the media on. Note: this is not the templated media app.
    456      */
    457     public static final String CAR_EXTRA_MEDIA_PACKAGE = "android.car.intent.extra.MEDIA_PACKAGE";
    458 
    459     /** @hide */
    460     public static final String CAR_SERVICE_INTERFACE_NAME = "android.car.ICar";
    461 
    462     private static final String CAR_SERVICE_PACKAGE = "com.android.car";
    463 
    464     private static final String CAR_SERVICE_CLASS = "com.android.car.CarService";
    465 
    466     private static final long CAR_SERVICE_BIND_RETRY_INTERVAL_MS = 500;
    467     private static final long CAR_SERVICE_BIND_MAX_RETRY = 20;
    468 
    469     private final Context mContext;
    470     @GuardedBy("this")
    471     private ICar mService;
    472     private final boolean mOwnsService;
    473     private static final int STATE_DISCONNECTED = 0;
    474     private static final int STATE_CONNECTING = 1;
    475     private static final int STATE_CONNECTED = 2;
    476     @GuardedBy("this")
    477     private int mConnectionState;
    478     @GuardedBy("this")
    479     private int mConnectionRetryCount;
    480 
    481     private final Runnable mConnectionRetryRunnable = new Runnable() {
    482         @Override
    483         public void run() {
    484             startCarService();
    485         }
    486     };
    487 
    488     private final Runnable mConnectionRetryFailedRunnable = new Runnable() {
    489         @Override
    490         public void run() {
    491             mServiceConnectionListener.onServiceDisconnected(new ComponentName(CAR_SERVICE_PACKAGE,
    492                     CAR_SERVICE_CLASS));
    493         }
    494     };
    495 
    496     private final ServiceConnection mServiceConnectionListener =
    497             new ServiceConnection () {
    498         public void onServiceConnected(ComponentName name, IBinder service) {
    499             synchronized (Car.this) {
    500                 mService = ICar.Stub.asInterface(service);
    501                 mConnectionState = STATE_CONNECTED;
    502             }
    503             mServiceConnectionListenerClient.onServiceConnected(name, service);
    504         }
    505 
    506         public void onServiceDisconnected(ComponentName name) {
    507             synchronized (Car.this) {
    508                 mService = null;
    509                 if (mConnectionState  == STATE_DISCONNECTED) {
    510                     return;
    511                 }
    512                 mConnectionState = STATE_DISCONNECTED;
    513             }
    514             // unbind explicitly here.
    515             disconnect();
    516             mServiceConnectionListenerClient.onServiceDisconnected(name);
    517         }
    518     };
    519 
    520     private final ServiceConnection mServiceConnectionListenerClient;
    521     private final Object mCarManagerLock = new Object();
    522     @GuardedBy("mCarManagerLock")
    523     private final HashMap<String, CarManagerBase> mServiceMap = new HashMap<>();
    524 
    525     /** Handler for generic event dispatching. */
    526     private final Handler mEventHandler;
    527 
    528     private final Handler mMainThreadEventHandler;
    529 
    530     /**
    531      * A factory method that creates Car instance for all Car API access.
    532      * @param context
    533      * @param serviceConnectionListener listener for monitoring service connection.
    534      * @param handler the handler on which the callback should execute, or null to execute on the
    535      * service's main thread. Note: the service connection listener will be always on the main
    536      * thread regardless of the handler given.
    537      * @return Car instance if system is in car environment and returns {@code null} otherwise.
    538      */
    539     public static Car createCar(Context context, ServiceConnection serviceConnectionListener,
    540             @Nullable Handler handler) {
    541         if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
    542             Log.e(CarLibLog.TAG_CAR, "FEATURE_AUTOMOTIVE not declared while android.car is used");
    543             return null;
    544         }
    545         try {
    546           return new Car(context, serviceConnectionListener, handler);
    547         } catch (IllegalArgumentException e) {
    548           // Expected when car service loader is not available.
    549         }
    550         return null;
    551     }
    552 
    553     /**
    554      * A factory method that creates Car instance for all Car API access using main thread {@code
    555      * Looper}.
    556      *
    557      * @see #createCar(Context, ServiceConnection, Handler)
    558      */
    559     public static Car createCar(Context context, ServiceConnection serviceConnectionListener) {
    560       return createCar(context, serviceConnectionListener, null);
    561     }
    562 
    563     private Car(Context context, ServiceConnection serviceConnectionListener,
    564             @Nullable Handler handler) {
    565         mContext = context;
    566         mEventHandler = determineEventHandler(handler);
    567         mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
    568 
    569         mService = null;
    570         mOwnsService = true;
    571         mServiceConnectionListenerClient = serviceConnectionListener;
    572     }
    573 
    574 
    575     /**
    576      * Car constructor when ICar binder is already available.
    577      * @hide
    578      */
    579     public Car(Context context, ICar service, @Nullable Handler handler) {
    580         mContext = context;
    581         mEventHandler = determineEventHandler(handler);
    582         mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
    583 
    584         mService = service;
    585         mOwnsService = false;
    586         mConnectionState = STATE_CONNECTED;
    587         mServiceConnectionListenerClient = null;
    588     }
    589 
    590     private static Handler determineMainThreadEventHandler(Handler eventHandler) {
    591         Looper mainLooper = Looper.getMainLooper();
    592         return (eventHandler.getLooper() == mainLooper) ? eventHandler : new Handler(mainLooper);
    593     }
    594 
    595     private static Handler determineEventHandler(@Nullable Handler handler) {
    596         if (handler == null) {
    597             Looper looper = Looper.getMainLooper();
    598             handler = new Handler(looper);
    599         }
    600         return handler;
    601     }
    602 
    603     /**
    604      * Connect to car service. This can be called while it is disconnected.
    605      * @throws IllegalStateException If connection is still on-going from previous
    606      *         connect call or it is already connected
    607      */
    608     public void connect() throws IllegalStateException {
    609         synchronized (this) {
    610             if (mConnectionState != STATE_DISCONNECTED) {
    611                 throw new IllegalStateException("already connected or connecting");
    612             }
    613             mConnectionState = STATE_CONNECTING;
    614             startCarService();
    615         }
    616     }
    617 
    618     /**
    619      * Disconnect from car service. This can be called while disconnected. Once disconnect is
    620      * called, all Car*Managers from this instance becomes invalid, and
    621      * {@link Car#getCarManager(String)} will return different instance if it is connected again.
    622      */
    623     public void disconnect() {
    624         synchronized (this) {
    625             if (mConnectionState == STATE_DISCONNECTED) {
    626                 return;
    627             }
    628             mEventHandler.removeCallbacks(mConnectionRetryRunnable);
    629             mMainThreadEventHandler.removeCallbacks(mConnectionRetryFailedRunnable);
    630             mConnectionRetryCount = 0;
    631             tearDownCarManagers();
    632             mService = null;
    633             mConnectionState = STATE_DISCONNECTED;
    634 
    635             if (mOwnsService) {
    636                 mContext.unbindService(mServiceConnectionListener);
    637             }
    638         }
    639     }
    640 
    641     /**
    642      * Tells if it is connected to the service or not. This will return false if it is still
    643      * connecting.
    644      * @return
    645      */
    646     public boolean isConnected() {
    647         synchronized (this) {
    648             return mService != null;
    649         }
    650     }
    651 
    652     /**
    653      * Tells if this instance is already connecting to car service or not.
    654      * @return
    655      */
    656     public boolean isConnecting() {
    657         synchronized (this) {
    658             return mConnectionState == STATE_CONNECTING;
    659         }
    660     }
    661 
    662     /**
    663      * Get car specific service as in {@link Context#getSystemService(String)}. Returned
    664      * {@link Object} should be type-casted to the desired service.
    665      * For example, to get sensor service,
    666      * SensorManagerService sensorManagerService = car.getCarManager(Car.SENSOR_SERVICE);
    667      * @param serviceName Name of service that should be created like {@link #SENSOR_SERVICE}.
    668      * @return Matching service manager or null if there is no such service.
    669      * @throws CarNotConnectedException if the connection to the car service has been lost.
    670      */
    671     public Object getCarManager(String serviceName) throws CarNotConnectedException {
    672         CarManagerBase manager;
    673         ICar service = getICarOrThrow();
    674         synchronized (mCarManagerLock) {
    675             manager = mServiceMap.get(serviceName);
    676             if (manager == null) {
    677                 try {
    678                     IBinder binder = service.getCarService(serviceName);
    679                     if (binder == null) {
    680                         Log.w(CarLibLog.TAG_CAR, "getCarManager could not get binder for service:" +
    681                                 serviceName);
    682                         return null;
    683                     }
    684                     manager = createCarManager(serviceName, binder);
    685                     if (manager == null) {
    686                         Log.w(CarLibLog.TAG_CAR,
    687                                 "getCarManager could not create manager for service:" +
    688                                         serviceName);
    689                         return null;
    690                     }
    691                     mServiceMap.put(serviceName, manager);
    692                 } catch (RemoteException e) {
    693                     handleRemoteException(e);
    694                 }
    695             }
    696         }
    697         return manager;
    698     }
    699 
    700     /**
    701      * Return the type of currently connected car.
    702      * @return
    703      */
    704     @ConnectionType
    705     public int getCarConnectionType() {
    706         return CONNECTION_TYPE_EMBEDDED;
    707     }
    708 
    709     /**
    710      * IllegalStateException from XyzCarService with special message is re-thrown as a different
    711      * exception. If the IllegalStateException is not understood then this message will throw the
    712      * original exception.
    713      *
    714      * @param e exception from XyzCarService.
    715      * @throws CarNotConnectedException if the connection to the car service has been lost.
    716      * @hide
    717      */
    718     public static void checkCarNotConnectedExceptionFromCarService(
    719             IllegalStateException e) throws CarNotConnectedException, IllegalStateException {
    720         String message = e.getMessage();
    721         if (CAR_NOT_CONNECTED_EXCEPTION_MSG.equals(message)) {
    722             throw new CarNotConnectedException();
    723         } else {
    724             throw e;
    725         }
    726     }
    727 
    728     /** @hide */
    729     public static void hideCarNotConnectedExceptionFromCarService(
    730             IllegalStateException e) throws IllegalStateException {
    731         String message = e.getMessage();
    732         if (CAR_NOT_CONNECTED_EXCEPTION_MSG.equals(message)) {
    733             return; //ignore
    734         } else {
    735             throw e;
    736         }
    737     }
    738 
    739     private CarManagerBase createCarManager(String serviceName, IBinder binder)
    740             throws CarNotConnectedException {
    741         CarManagerBase manager = null;
    742         switch (serviceName) {
    743             case AUDIO_SERVICE:
    744                 manager = new CarAudioManager(binder, mContext, mEventHandler);
    745                 break;
    746             case SENSOR_SERVICE:
    747                 manager = new CarSensorManager(binder, mContext, mEventHandler);
    748                 break;
    749             case INFO_SERVICE:
    750                 manager = new CarInfoManager(binder);
    751                 break;
    752             case APP_FOCUS_SERVICE:
    753                 manager = new CarAppFocusManager(binder, mEventHandler);
    754                 break;
    755             case PACKAGE_SERVICE:
    756                 manager = new CarPackageManager(binder, mContext);
    757                 break;
    758             case CAR_NAVIGATION_SERVICE:
    759                 manager = new CarNavigationStatusManager(binder);
    760                 break;
    761             case CABIN_SERVICE:
    762                 manager = new CarCabinManager(binder, mContext, mEventHandler);
    763                 break;
    764             case DIAGNOSTIC_SERVICE:
    765                 manager = new CarDiagnosticManager(binder, mContext, mEventHandler);
    766                 break;
    767             case HVAC_SERVICE:
    768                 manager = new CarHvacManager(binder, mContext, mEventHandler);
    769                 break;
    770             case POWER_SERVICE:
    771                 manager = new CarPowerManager(binder, mContext, mEventHandler);
    772                 break;
    773             case PROJECTION_SERVICE:
    774                 manager = new CarProjectionManager(binder, mEventHandler);
    775                 break;
    776             case PROPERTY_SERVICE:
    777                 manager = new CarPropertyManager(binder, mEventHandler, false,
    778                                                  "CarPropertyManager");
    779                 break;
    780             case VENDOR_EXTENSION_SERVICE:
    781                 manager = new CarVendorExtensionManager(binder, mEventHandler);
    782                 break;
    783             case CAR_INSTRUMENT_CLUSTER_SERVICE:
    784                 manager = new CarInstrumentClusterManager(binder, mEventHandler);
    785                 break;
    786             case TEST_SERVICE:
    787                 /* CarTestManager exist in static library. So instead of constructing it here,
    788                  * only pass binder wrapper so that CarTestManager can be constructed outside. */
    789                 manager = new CarTestManagerBinderWrapper(binder);
    790                 break;
    791             case VMS_SUBSCRIBER_SERVICE:
    792                 manager = new VmsSubscriberManager(binder);
    793                 break;
    794             case BLUETOOTH_SERVICE:
    795                 manager = new CarBluetoothManager(binder, mContext);
    796                 break;
    797             case STORAGE_MONITORING_SERVICE:
    798                 manager = new CarStorageMonitoringManager(binder, mEventHandler);
    799                 break;
    800             case CAR_DRIVING_STATE_SERVICE:
    801                 manager = new CarDrivingStateManager(binder, mContext, mEventHandler);
    802                 break;
    803             case CAR_UX_RESTRICTION_SERVICE:
    804                 manager = new CarUxRestrictionsManager(binder, mContext, mEventHandler);
    805                 break;
    806             case CAR_CONFIGURATION_SERVICE:
    807                 manager = new CarConfigurationManager(binder);
    808                 break;
    809             default:
    810                 break;
    811         }
    812         return manager;
    813     }
    814 
    815     private void startCarService() {
    816         Intent intent = new Intent();
    817         intent.setPackage(CAR_SERVICE_PACKAGE);
    818         intent.setAction(Car.CAR_SERVICE_INTERFACE_NAME);
    819         boolean bound = mContext.bindServiceAsUser(intent, mServiceConnectionListener,
    820                 Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF);
    821         if (!bound) {
    822             mConnectionRetryCount++;
    823             if (mConnectionRetryCount > CAR_SERVICE_BIND_MAX_RETRY) {
    824                 Log.w(CarLibLog.TAG_CAR, "cannot bind to car service after max retry");
    825                 mMainThreadEventHandler.post(mConnectionRetryFailedRunnable);
    826             } else {
    827                 mEventHandler.postDelayed(mConnectionRetryRunnable,
    828                         CAR_SERVICE_BIND_RETRY_INTERVAL_MS);
    829             }
    830         } else {
    831             mConnectionRetryCount = 0;
    832         }
    833     }
    834 
    835     private synchronized ICar getICarOrThrow() throws IllegalStateException {
    836         if (mService == null) {
    837             throw new IllegalStateException("not connected");
    838         }
    839         return mService;
    840     }
    841 
    842     private void handleRemoteException(RemoteException e) {
    843         Log.w(CarLibLog.TAG_CAR, "RemoteException", e);
    844         disconnect();
    845     }
    846 
    847     private void tearDownCarManagers() {
    848         synchronized (mCarManagerLock) {
    849             for (CarManagerBase manager: mServiceMap.values()) {
    850                 manager.onCarDisconnected();
    851             }
    852             mServiceMap.clear();
    853         }
    854     }
    855 }
    856