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