Car.java revision 150d8de43e71a624106e90bcc04067414c42ef18
1ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/*
2ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Copyright (C) 2015 The Android Open Source Project
3ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
4ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Licensed under the Apache License, Version 2.0 (the "License");
5ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * you may not use this file except in compliance with the License.
6ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * You may obtain a copy of the License at
7ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
8ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *      http://www.apache.org/licenses/LICENSE-2.0
9ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung *
10ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * Unless required by applicable law or agreed to in writing, software
11ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * distributed under the License is distributed on an "AS IS" BASIS,
12ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * See the License for the specific language governing permissions and
14ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung * limitations under the License.
15ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */
16ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
17e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkpackage android.car;
18ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
19e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.annotation.IntDef;
20e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.annotation.Nullable;
21e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.annotation.SystemApi;
226e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.content.pm.CarPackageManager;
236e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.CarSensorManager;
2443c04a7c87404d078db60e09d2da0061d72357c2Steve Paikimport android.car.hardware.cabin.CarCabinManager;
25634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsevimport android.car.hardware.CarVendorExtensionManager;
266e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.camera.CarCameraManager;
276e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.hvac.CarHvacManager;
286e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.radio.CarRadioManager;
296e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.media.CarAudioManager;
303388e7848f3a30029935463afafe9b8280939127Keun-young Parkimport android.car.navigation.CarNavigationStatusManager;
316e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.test.CarTestManagerBinderWrapper;
32ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.ComponentName;
33ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.Context;
34e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.content.Intent;
35e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.content.ServiceConnection;
36ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.pm.PackageManager;
376b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoungimport android.os.Handler;
38ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.IBinder;
39ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.Looper;
40ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.RemoteException;
4144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Parkimport android.os.UserHandle;
42ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.util.Log;
43ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
44e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport com.android.internal.annotations.GuardedBy;
45e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
46ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.lang.annotation.Retention;
47ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.lang.annotation.RetentionPolicy;
48ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.util.HashMap;
496b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung
50ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/**
51e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup *   Top level car API for embedded Android Auto deployments.
52e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup *   This API works only for devices with {@link PackageManager#FEATURE_AUTOMOTIVE}
53e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup *   Calling this API on a device with no such feature will lead to an exception.
54ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */
554cf6911619b9fe6ffeba7afeb05299aab165f184Keun-young Parkpublic final class Car {
56ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
57f521fd7b917a63c240802c7f841fc04c315573d0Keun-young Park    /**
58f521fd7b917a63c240802c7f841fc04c315573d0Keun-young Park     * Represent the version of Car API.
59f521fd7b917a63c240802c7f841fc04c315573d0Keun-young Park     */
60f521fd7b917a63c240802c7f841fc04c315573d0Keun-young Park    public static final int VERSION = 1;
61f521fd7b917a63c240802c7f841fc04c315573d0Keun-young Park
62a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung    /** Service name for {@link CarSensorManager}, to be used in {@link #getCarManager(String)}. */
63ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public static final String SENSOR_SERVICE = "sensor";
64ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
65a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung    /** Service name for {@link CarInfoManager}, to be used in {@link #getCarManager(String)}. */
66a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung    public static final String INFO_SERVICE = "info";
67a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung
683ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    /** Service name for {@link CarAppFocusManager}. */
6946371473c416415fb6bcb8db85686669c3d65af6Vitalii Tomkiv    public static final String APP_FOCUS_SERVICE = "app_focus";
70a74b9caa2fb6435f1c01c5e8766b89235c4e3d5akeunyoung
717a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev    /** Service name for {@link CarPackageManager} */
7245fdcbaab5699d7d8153bfda058d0eea2049c8b8Keun-young Park    public static final String PACKAGE_SERVICE = "package";
7345fdcbaab5699d7d8153bfda058d0eea2049c8b8Keun-young Park
745672e85bdf82f6a2350afb942dfe17b7c699af87Keun-young Park    /** Service name for {@link CarAudioManager} */
755672e85bdf82f6a2350afb942dfe17b7c699af87Keun-young Park    public static final String AUDIO_SERVICE = "audio";
767a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev    /**
773388e7848f3a30029935463afafe9b8280939127Keun-young Park     * Service name for {@link CarNavigationStatusManager}
787a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev     * @hide
797a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev     */
807a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev    public static final String CAR_NAVIGATION_SERVICE = "car_navigation_service";
817a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev
82280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
83280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
84280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
85e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
8643c04a7c87404d078db60e09d2da0061d72357c2Steve Paik    public static final String CABIN_SERVICE = "cabin";
8743c04a7c87404d078db60e09d2da0061d72357c2Steve Paik
8843c04a7c87404d078db60e09d2da0061d72357c2Steve Paik    /**
8943c04a7c87404d078db60e09d2da0061d72357c2Steve Paik     * @hide
9043c04a7c87404d078db60e09d2da0061d72357c2Steve Paik     */
9143c04a7c87404d078db60e09d2da0061d72357c2Steve Paik    @SystemApi
92875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    public static final String CAMERA_SERVICE = "camera";
93875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik
94280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
95280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
96280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
97875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    @SystemApi
98e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String RADIO_SERVICE = "radio";
99ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
100280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
101280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
102280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
103e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
104e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String HVAC_SERVICE = "hvac";
105e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
106280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
107280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
108280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
1096e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    @SystemApi
1106e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    public static final String PROJECTION_SERVICE = "projection";
1116e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv
112e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /**
113634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev     * @hide
114634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev     */
115634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev    @SystemApi
116634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev    public static final String VENDOR_EXTENSION_SERVICE = "vendor_extension";
117634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev
118634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev    /**
119e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * Service for testing. This is system app only feature.
120e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}.
121e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * @hide
122e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     */
123e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
124e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String TEST_SERVICE = "car-service-test";
125ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
126ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /** Permission necessary to access car's mileage information. */
127e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
128e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
129ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /** Permission necessary to access car's fuel level. */
130e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
131e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
132ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /** Permission necessary to access car's speed. */
133e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
134e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
135ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /**
136c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen     * Permission necessary to change car audio volume through {@link CarAudioManager}.
137c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen     */
138c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen    public static final String PERMISSION_CAR_CONTROL_AUDIO_VOLUME =
139c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen            "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
140c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen
141c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen    /**
1423388e7848f3a30029935463afafe9b8280939127Keun-young Park     * Permission necessary to use {@link CarNavigationStatusManager}.
143ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev     * @hide
144ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev     */
145ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    public static final String PERMISSION_CAR_NAVIGATION_MANAGER =
146e31a8b24afe58bfc924fab7b66c9e48b9ef8e884Keun-young Park            "android.car.permission.CAR_NAVIGATION_MANAGER";
147ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev
148280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
149280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access car specific communication channel.
150280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
151280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
152e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
153ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public static final String PERMISSION_VENDOR_EXTENSION =
154e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            "android.car.permission.CAR_VENDOR_EXTENSION";
155e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
156280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
157280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
158280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
159e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
1604aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park    public static final String PERMISSION_CONTROL_APP_BLOCKING =
161e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            "android.car.permission.CONTROL_APP_BLOCKING";
162ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
163280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
16443c04a7c87404d078db60e09d2da0061d72357c2Steve Paik     * Permission necessary to access Car Cabin APIs.
16543c04a7c87404d078db60e09d2da0061d72357c2Steve Paik     * @hide
16643c04a7c87404d078db60e09d2da0061d72357c2Steve Paik     */
16743c04a7c87404d078db60e09d2da0061d72357c2Steve Paik    @SystemApi
16843c04a7c87404d078db60e09d2da0061d72357c2Steve Paik    public static final String PERMISSION_CAR_CABIN = "android.car.permission.CAR_CABIN";
16943c04a7c87404d078db60e09d2da0061d72357c2Steve Paik
17043c04a7c87404d078db60e09d2da0061d72357c2Steve Paik    /**
171280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access Car Camera APIs.
172280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
173280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
174875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    @SystemApi
175875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    public static final String PERMISSION_CAR_CAMERA = "android.car.permission.CAR_CAMERA";
176875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik
177280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
178280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access Car HVAC APIs.
179280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
180280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
181e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
182e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_CAR_HVAC = "android.car.permission.CAR_HVAC";
183ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
184280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
185280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access Car RADIO system APIs.
186280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
187280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
188e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
189e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_CAR_RADIO = "android.car.permission.CAR_RADIO";
190ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
191b13dbe470108846d1c04494c5c0d2bf3cd9b8054Jason Tholstrup
192280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
193b13dbe470108846d1c04494c5c0d2bf3cd9b8054Jason Tholstrup     * Permission necessary to access Car PROJECTION system APIs.
194280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
195280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
1966e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    @SystemApi
1976e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    public static final String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
1986e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv
199280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
200280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to mock vehicle hal for testing.
201280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
202280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
203e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
204e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_MOCK_VEHICLE_HAL =
205e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            "android.car.permission.CAR_MOCK_VEHICLE_HAL";
206e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
207e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /** Type of car connection: platform runs directly in car. */
208e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final int CONNECTION_TYPE_EMBEDDED = 5;
2091ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev    /**
2101ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     * Type of car connection: platform runs directly in car but with mocked vehicle hal.
2111ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     * This will only happen in testing environment.
2121ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     * @hide
2131ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     */
2141ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev    public static final int CONNECTION_TYPE_EMBEDDED_MOCKING = 6;
215e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
216e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup
217e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /** @hide */
2181ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev    @IntDef({CONNECTION_TYPE_EMBEDDED, CONNECTION_TYPE_EMBEDDED_MOCKING})
219e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @Retention(RetentionPolicy.SOURCE)
220e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public @interface ConnectionType {}
221ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
2223cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    /**
2233cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * CarXyzService throws IllegalStateException with this message is re-thrown as
2243cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * {@link CarNotConnectedException}.
2253cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     *
2263cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @hide
2273cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     */
2283cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public static final String CAR_NOT_CONNECTED_EXCEPTION_MSG = "CarNotConnected";
2293cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
230e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /** @hide */
231e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String CAR_SERVICE_INTERFACE_NAME = "android.car.ICar";
232e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
233e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private static final String CAR_SERVICE_PACKAGE = "com.android.car";
234e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
23544241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    private static final String CAR_SERVICE_CLASS = "com.android.car.CarService";
23644241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park
237e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private static final String CAR_TEST_MANAGER_CLASS = "android.car.CarTestManager";
238ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
23944241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    private static final long CAR_SERVICE_BIND_RETRY_INTERVAL_MS = 500;
24044241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    private static final long CAR_SERVICE_BIND_MAX_RETRY = 20;
24144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park
242ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final Context mContext;
243ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @GuardedBy("this")
244ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private ICar mService;
245ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private static final int STATE_DISCONNECTED = 0;
246ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private static final int STATE_CONNECTING = 1;
247ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private static final int STATE_CONNECTED = 2;
248ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @GuardedBy("this")
249ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private int mConnectionState;
25044241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    @GuardedBy("this")
25144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    private int mConnectionRetryCount;
25244241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park
25344241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    private final Runnable mConnectionRetryRunnable = new Runnable() {
25444241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        @Override
25544241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        public void run() {
25644241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            startCarService();
25744241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        }
25844241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    };
25944241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park
26044241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    private final Runnable mConnectionRetryFailedRunnable = new Runnable() {
26144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        @Override
26244241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        public void run() {
26344241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            mServiceConnectionListener.onServiceDisconnected(new ComponentName(CAR_SERVICE_PACKAGE,
26444241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park                    CAR_SERVICE_CLASS));
26544241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        }
26644241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park    };
267ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
268e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private final ServiceConnection mServiceConnectionListener =
269e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            new ServiceConnection () {
270ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        public void onServiceConnected(ComponentName name, IBinder service) {
2711ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung            synchronized (Car.this) {
272ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                mService = ICar.Stub.asInterface(service);
273ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                mConnectionState = STATE_CONNECTED;
274ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
275ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mServiceConnectionListenerClient.onServiceConnected(name, service);
276ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
277ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
278ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        public void onServiceDisconnected(ComponentName name) {
2791ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung            synchronized (Car.this) {
280ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                mService = null;
281ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                if (mConnectionState  == STATE_DISCONNECTED) {
282ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    return;
283ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                }
284cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung                mConnectionState = STATE_DISCONNECTED;
285ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
286e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            // unbind explicitly here.
287e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            disconnect();
288ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mServiceConnectionListenerClient.onServiceDisconnected(name);
289ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
290ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    };
291ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
292e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private final ServiceConnection mServiceConnectionListenerClient;
293ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final Object mCarManagerLock = new Object();
294ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @GuardedBy("mCarManagerLock")
295ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final HashMap<String, CarManagerBase> mServiceMap = new HashMap<>();
2966b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung
2976b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung    /** Handler for generic event dispatching. */
2986b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung    private final Handler mEventHandler;
2996b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung
3003ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    private final Handler mMainThreadEventHandler;
30144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park
3021ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung    /**
3038de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * A factory method that creates Car instance for all Car API access.
304ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param context
305e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * @param serviceConnectionListener listener for monitoring service connection.
3063ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup     * @param handler the handler on which the callback should execute, or null to execute on the
3073ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup     * service's main thread. Note: the service connection listener will be always on the main
3083ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup     * thread regardless of the handler given.
3098de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * @return Car instance if system is in car environment and returns {@code null} otherwise.
310ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
311e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static Car createCar(Context context, ServiceConnection serviceConnectionListener,
3123ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup            @Nullable Handler handler) {
313e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
314e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            Log.e(CarLibLog.TAG_CAR, "FEATURE_AUTOMOTIVE not declared while android.car is used");
315e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            return null;
316e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        }
3178de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        try {
3183ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup          return new Car(context, serviceConnectionListener, handler);
3198de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        } catch (IllegalArgumentException e) {
3208de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev          // Expected when car service loader is not available.
3218de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        }
3228de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        return null;
3238de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev    }
3248de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev
3258de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev    /**
3268de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * A factory method that creates Car instance for all Car API access using main thread {@code
3278de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * Looper}.
3288de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     *
3293ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup     * @see #createCar(Context, ServiceConnection, Handler)
3308de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     */
331e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static Car createCar(Context context, ServiceConnection serviceConnectionListener) {
3328de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev      return createCar(context, serviceConnectionListener, null);
3338de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev    }
3348de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev
335e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private Car(Context context, ServiceConnection serviceConnectionListener,
3363ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup            @Nullable Handler handler) {
337ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mContext = context;
3383ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        mEventHandler = determineEventHandler(handler);
339224220701b9c22ebcfc7dc532714839dca202bb3Yao Chen        mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
3403ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup
3413ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        mService = null;
342ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mServiceConnectionListenerClient = serviceConnectionListener;
343ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
344ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
3453ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup
346ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
3471ac59caa6b1bc760aef0adb3c675b49bfa53af9fJason Tholstrup     * Car constructor when ICar binder is already available.     *
348ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @hide
349ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
3503ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    public Car(Context context, ICar service, @Nullable Handler handler) {
351ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mContext = context;
3523ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        mEventHandler = determineEventHandler(handler);
353f4f07bf04563b9ad25ff9cdfc96f40790f155e41Keun-young Park        mMainThreadEventHandler = determineMainThreadEventHandler(mEventHandler);
3543ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup
355ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mService = service;
356ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mConnectionState = STATE_CONNECTED;
357ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mServiceConnectionListenerClient = null;
358ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
359ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
3603ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    private static Handler determineMainThreadEventHandler(Handler eventHandler) {
3613ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        Looper mainLooper = Looper.getMainLooper();
3623ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        return (eventHandler.getLooper() == mainLooper) ? eventHandler : new Handler(mainLooper);
3633ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    }
3643ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup
3653ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    private static Handler determineEventHandler(@Nullable Handler handler) {
3663ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        if (handler == null) {
367f4f07bf04563b9ad25ff9cdfc96f40790f155e41Keun-young Park            Looper looper = Looper.getMainLooper();
3683ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup            handler = new Handler(looper);
3693ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        }
3703ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup        return handler;
3713ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup    }
3723ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup
373ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
374ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Connect to car service. This can be called while it is disconnected.
375ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @throws IllegalStateException If connection is still on-going from previous
376ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     *         connect call or it is already connected
377ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
378ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public void connect() throws IllegalStateException {
379ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
380ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (mConnectionState != STATE_DISCONNECTED) {
381ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                throw new IllegalStateException("already connected or connecting");
382ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
383ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mConnectionState = STATE_CONNECTING;
384e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            startCarService();
385ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
386ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
387ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
388ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
389ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Disconnect from car service. This can be called while disconnected. Once disconnect is
390ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * called, all Car*Managers from this instance becomes invalid, and
391ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * {@link Car#getCarManager(String)} will return different instance if it is connected again.
392ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
393ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public void disconnect() {
394ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
395ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (mConnectionState == STATE_DISCONNECTED) {
396ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                return;
397ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
39844241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            mEventHandler.removeCallbacks(mConnectionRetryRunnable);
3993ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup            mMainThreadEventHandler.removeCallbacks(mConnectionRetryFailedRunnable);
40044241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            mConnectionRetryCount = 0;
401ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            tearDownCarManagers();
402ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mService = null;
403ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mConnectionState = STATE_DISCONNECTED;
404e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            mContext.unbindService(mServiceConnectionListener);
405ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
406ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
407ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
408ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
409ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Tells if it is connected to the service or not. This will return false if it is still
410ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * connecting.
411ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
412ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
413ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public boolean isConnected() {
414ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
415ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            return mService != null;
416ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
417ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
418ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
419ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
420ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Tells if this instance is already connecting to car service or not.
421ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
422ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
423ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public boolean isConnecting() {
424ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
425ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            return mConnectionState == STATE_CONNECTING;
426ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
427ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
428ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
429ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
430ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Get car specific service as in {@link Context#getSystemService(String)}. Returned
431ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * {@link Object} should be type-casted to the desired service.
432ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * For example, to get sensor service,
433ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * SensorManagerService sensorManagerService = car.getCarManager(Car.SENSOR_SERVICE);
434ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param serviceName Name of service that should be created like {@link #SENSOR_SERVICE}.
435ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return Matching service manager or null if there is no such service.
436d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * @throws CarNotConnectedException if the connection to the car service has been lost.
437ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
438235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv    public Object getCarManager(String serviceName) throws CarNotConnectedException {
4390477e29bb17ee8ec99acfa5fa966889cd45ebf34Pavel Maltsev        CarManagerBase manager;
4401ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung        ICar service = getICarOrThrow();
441ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (mCarManagerLock) {
442ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            manager = mServiceMap.get(serviceName);
443ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (manager == null) {
444ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                try {
4451ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung                    IBinder binder = service.getCarService(serviceName);
446ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    if (binder == null) {
447ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        Log.w(CarLibLog.TAG_CAR, "getCarManager could not get binder for service:" +
448ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                                serviceName);
449ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        return null;
450ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    }
451e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                    manager = createCarManager(serviceName, binder);
452ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    if (manager == null) {
453ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        Log.w(CarLibLog.TAG_CAR,
454ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                                "getCarManager could not create manager for service:" +
4550477e29bb17ee8ec99acfa5fa966889cd45ebf34Pavel Maltsev                                        serviceName);
456ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        return null;
457ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    }
458ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    mServiceMap.put(serviceName, manager);
459ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                } catch (RemoteException e) {
460e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                    handleRemoteException(e);
461ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                }
462ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
463ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
464ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return manager;
465ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
466ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
467ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
468ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Return the type of currently connected car.
469ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
470ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
471ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @ConnectionType
472e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public int getCarConnectionType() {
473e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        return CONNECTION_TYPE_EMBEDDED;
474ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
475ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
4763cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    /**
4773cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * IllegalStateException from XyzCarService with special message is re-thrown as a different
4783cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * exception. If the IllegalStateException is not understood then this message will throw the
4793cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * original exception.
4803cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     *
4813cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @param e exception from XyzCarService.
482d72b53500006e84b0c69e650878267c693c164a3Jason Tholstrup     * @throws CarNotConnectedException if the connection to the car service has been lost.
4833cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @hide
4843cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     */
4853cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public static void checkCarNotConnectedExceptionFromCarService(
4863cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            IllegalStateException e) throws CarNotConnectedException, IllegalStateException {
4873cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        String message = e.getMessage();
48877ac6cf7366599d48d242205bcf5a67bcc633980Keun-young Park        if (CAR_NOT_CONNECTED_EXCEPTION_MSG.equals(message)) {
4893cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            throw new CarNotConnectedException();
4903cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        } else {
4913cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            throw e;
4923cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
4933cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
4943cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
495150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park    /** @hide */
496150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park    public static void hideCarNotConnectedExceptionFromCarService(
497150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park            IllegalStateException e) throws IllegalStateException {
498150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park        String message = e.getMessage();
499150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park        if (CAR_NOT_CONNECTED_EXCEPTION_MSG.equals(message)) {
500150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park            return; //ignore
501150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park        } else {
502150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park            throw e;
503150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park        }
504150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park    }
505150d8de43e71a624106e90bcc04067414c42ef18Keun-young Park
506235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv    private CarManagerBase createCarManager(String serviceName, IBinder binder)
507235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv            throws CarNotConnectedException {
508e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        CarManagerBase manager = null;
509e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        switch (serviceName) {
510e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case AUDIO_SERVICE:
5116f3f402a7469e300fbfe65d950204fef995d4d8dVitalii Tomkiv                manager = new CarAudioManager(binder, mContext);
512e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
513e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case SENSOR_SERVICE:
5143ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarSensorManager(binder, mContext, mEventHandler);
515e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
516e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case INFO_SERVICE:
517e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarInfoManager(binder);
518e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
51946371473c416415fb6bcb8db85686669c3d65af6Vitalii Tomkiv            case APP_FOCUS_SERVICE:
5203ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarAppFocusManager(binder, mEventHandler);
521e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
522e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case PACKAGE_SERVICE:
523e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarPackageManager(binder, mContext);
524e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
525e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case CAR_NAVIGATION_SERVICE:
5263388e7848f3a30029935463afafe9b8280939127Keun-young Park                manager = new CarNavigationStatusManager(binder);
527e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
52843c04a7c87404d078db60e09d2da0061d72357c2Steve Paik            case CABIN_SERVICE:
5293ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarCabinManager(binder, mContext, mEventHandler);
53043c04a7c87404d078db60e09d2da0061d72357c2Steve Paik                break;
531875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik            case CAMERA_SERVICE:
532875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik                manager = new CarCameraManager(binder, mContext);
533875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik                break;
534e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case HVAC_SERVICE:
5353ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarHvacManager(binder, mContext, mEventHandler);
536e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
5376e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv            case PROJECTION_SERVICE:
5383ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarProjectionManager(binder, mEventHandler);
5396e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv                break;
540e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case RADIO_SERVICE:
5413ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarRadioManager(binder, mEventHandler);
542e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
543634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev            case VENDOR_EXTENSION_SERVICE:
5443ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                manager = new CarVendorExtensionManager(binder, mEventHandler);
545634e1ff49c62c32c8227ec5092743de3caca790cPavel Maltsev                break;
546e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case TEST_SERVICE:
547e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                /* CarTestManager exist in static library. So instead of constructing it here,
548e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                 * only pass binder wrapper so that CarTestManager can be constructed outside. */
549e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarTestManagerBinderWrapper(binder);
550e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
551e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        }
552e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        return manager;
553e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    }
554e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
555e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private void startCarService() {
556e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        Intent intent = new Intent();
557e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        intent.setPackage(CAR_SERVICE_PACKAGE);
558e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        intent.setAction(Car.CAR_SERVICE_INTERFACE_NAME);
55944241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        boolean bound = mContext.bindServiceAsUser(intent, mServiceConnectionListener,
56044241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park                Context.BIND_AUTO_CREATE, UserHandle.CURRENT_OR_SELF);
56144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        if (!bound) {
56244241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            mConnectionRetryCount++;
56344241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            if (mConnectionRetryCount > CAR_SERVICE_BIND_MAX_RETRY) {
56444241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park                Log.w(CarLibLog.TAG_CAR, "cannot bind to car service after max retry");
5653ee334d8c220f631d2ea7fa225af148f41b43354Jason Tholstrup                mMainThreadEventHandler.post(mConnectionRetryFailedRunnable);
56644241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            } else {
56744241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park                mEventHandler.postDelayed(mConnectionRetryRunnable,
56844241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park                        CAR_SERVICE_BIND_RETRY_INTERVAL_MS);
56944241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            }
57044241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        } else {
57144241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park            mConnectionRetryCount = 0;
57244241ffb0717f22650bbcef19c9b68c1f56cac10Keun-young Park        }
573e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    }
574e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
575ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private synchronized ICar getICarOrThrow() throws IllegalStateException {
576ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        if (mService == null) {
577ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            throw new IllegalStateException("not connected");
578ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
579ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return mService;
580ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
581ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
582ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private void handleRemoteException(RemoteException e) {
583ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        Log.w(CarLibLog.TAG_CAR, "RemoteException", e);
584ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        disconnect();
585ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
586ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
587ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private void tearDownCarManagers() {
588ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (mCarManagerLock) {
589ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            for (CarManagerBase manager: mServiceMap.values()) {
590ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                manager.onCarDisconnected();
591ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
592ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mServiceMap.clear();
593ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
594ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
595ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung}
596