Car.java revision c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193f
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;
246e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.camera.CarCameraManager;
256e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.hvac.CarHvacManager;
266e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.hardware.radio.CarRadioManager;
276e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.media.CarAudioManager;
286e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.navigation.CarNavigationManager;
296e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkivimport android.car.test.CarTestManagerBinderWrapper;
30ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.ComponentName;
31ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.Context;
32e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.content.Intent;
33e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.content.ServiceConnection;
34ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.content.pm.PackageManager;
356b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoungimport android.os.Handler;
36ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.IBinder;
37ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.Looper;
38ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.os.RemoteException;
39ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport android.util.Log;
40ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
41e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport com.android.internal.annotations.GuardedBy;
42e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
43ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.lang.annotation.Retention;
44ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.lang.annotation.RetentionPolicy;
45ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungimport java.util.HashMap;
466b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung
47ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung/**
48e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup *   Top level car API for embedded Android Auto deployments.
49e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup *   This API works only for devices with {@link PackageManager#FEATURE_AUTOMOTIVE}
50e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup *   Calling this API on a device with no such feature will lead to an exception.
51ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung */
52ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoungpublic class Car {
53ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
54a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung    /** Service name for {@link CarSensorManager}, to be used in {@link #getCarManager(String)}. */
55ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public static final String SENSOR_SERVICE = "sensor";
56ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
57a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung    /** Service name for {@link CarInfoManager}, to be used in {@link #getCarManager(String)}. */
58a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung    public static final String INFO_SERVICE = "info";
59a3b28d81e0c8df531ac704f9e649e38ea90483d2keunyoung
6045fdcbaab5699d7d8153bfda058d0eea2049c8b8Keun-young Park    /** Service name for {@link CarAppContextManager}. */
61a74b9caa2fb6435f1c01c5e8766b89235c4e3d5akeunyoung    public static final String APP_CONTEXT_SERVICE = "app_context";
62a74b9caa2fb6435f1c01c5e8766b89235c4e3d5akeunyoung
637a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev    /** Service name for {@link CarPackageManager} */
6445fdcbaab5699d7d8153bfda058d0eea2049c8b8Keun-young Park    public static final String PACKAGE_SERVICE = "package";
6545fdcbaab5699d7d8153bfda058d0eea2049c8b8Keun-young Park
665672e85bdf82f6a2350afb942dfe17b7c699af87Keun-young Park    /** Service name for {@link CarAudioManager} */
675672e85bdf82f6a2350afb942dfe17b7c699af87Keun-young Park    public static final String AUDIO_SERVICE = "audio";
687a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev    /**
69e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * Service name for {@link CarNavigationManager}
707a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev     * @hide
717a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev     */
727a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev    public static final String CAR_NAVIGATION_SERVICE = "car_navigation_service";
737a948e54331cccf96f178ab426cb7810472c2dc8Pavel Maltsev
74280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
75280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
76280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
77e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
78875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    public static final String CAMERA_SERVICE = "camera";
79875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik
80280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
81280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
82280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
83875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    @SystemApi
84e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String RADIO_SERVICE = "radio";
85ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
86280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
87280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
88280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
89e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
90e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String HVAC_SERVICE = "hvac";
91e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
92280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
93280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
94280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
956e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    @SystemApi
966e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    public static final String PROJECTION_SERVICE = "projection";
976e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv
98e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /**
99e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * Service for testing. This is system app only feature.
100e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * Service name for {@link CarTestManager}, to be used in {@link #getCarManager(String)}.
101e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * @hide
102e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     */
103e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
104e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String TEST_SERVICE = "car-service-test";
105ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
106ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /** Permission necessary to access car's mileage information. */
107e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_MILEAGE = "android.car.permission.CAR_MILEAGE";
108e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
109ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /** Permission necessary to access car's fuel level. */
110e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_FUEL = "android.car.permission.CAR_FUEL";
111e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
112ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /** Permission necessary to access car's speed. */
113e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_SPEED = "android.car.permission.CAR_SPEED";
114e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
115ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    /**
116c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen     * Permission necessary to change car audio volume through {@link CarAudioManager}.
117c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen     */
118c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen    public static final String PERMISSION_CAR_CONTROL_AUDIO_VOLUME =
119c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen            "android.car.permission.CAR_CONTROL_AUDIO_VOLUME";
120c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen
121c4d442f4a0d3acf90b1c7a1dd7c222a8f32a193fYao Chen    /**
122ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev     * Permission necessary to use {@link CarNavigationManager}.
123ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev     * @hide
124ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev     */
125ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev    public static final String PERMISSION_CAR_NAVIGATION_MANAGER =
126e31a8b24afe58bfc924fab7b66c9e48b9ef8e884Keun-young Park            "android.car.permission.CAR_NAVIGATION_MANAGER";
127ce4ffd95d6883b28756e5b02ae45a06013bd6c38Pavel Maltsev
128280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
129280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access car specific communication channel.
130280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
131280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
132e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
133ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public static final String PERMISSION_VENDOR_EXTENSION =
134e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            "android.car.permission.CAR_VENDOR_EXTENSION";
135e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
136280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
137280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
138280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
139e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
1404aeb4bf0c56588be65264c324bbaaa545ad6714cKeun-young Park    public static final String PERMISSION_CONTROL_APP_BLOCKING =
141e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            "android.car.permission.CONTROL_APP_BLOCKING";
142ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
143280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
144280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access Car Camera APIs.
145280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
146280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
147875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    @SystemApi
148875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik    public static final String PERMISSION_CAR_CAMERA = "android.car.permission.CAR_CAMERA";
149875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik
150280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
151280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access Car HVAC APIs.
152280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
153280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
154e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
155e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_CAR_HVAC = "android.car.permission.CAR_HVAC";
156ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
157280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
158280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to access Car RADIO system APIs.
159280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
160280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
161e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
162e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_CAR_RADIO = "android.car.permission.CAR_RADIO";
163ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
164b13dbe470108846d1c04494c5c0d2bf3cd9b8054Jason Tholstrup
165280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
166b13dbe470108846d1c04494c5c0d2bf3cd9b8054Jason Tholstrup     * Permission necessary to access Car PROJECTION system APIs.
167280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
168280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
1696e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    @SystemApi
1706e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv    public static final String PERMISSION_CAR_PROJECTION = "android.car.permission.CAR_PROJECTION";
1716e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv
172280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv    /**
173280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * Permission necessary to mock vehicle hal for testing.
174280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     * @hide
175280b5721254e5ac974404e02e7589f17f560d1f9Vitalii Tomkiv     */
176e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @SystemApi
177e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String PERMISSION_MOCK_VEHICLE_HAL =
178e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            "android.car.permission.CAR_MOCK_VEHICLE_HAL";
179e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
180e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /** Type of car connection: platform runs directly in car. */
181e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final int CONNECTION_TYPE_EMBEDDED = 5;
1821ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev    /**
1831ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     * Type of car connection: platform runs directly in car but with mocked vehicle hal.
1841ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     * This will only happen in testing environment.
1851ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     * @hide
1861ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev     */
1871ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev    public static final int CONNECTION_TYPE_EMBEDDED_MOCKING = 6;
188e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
189e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup
190e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /** @hide */
1911ecdd6ca75fdf8ff62105630664de5125e29676bPavel Maltsev    @IntDef({CONNECTION_TYPE_EMBEDDED, CONNECTION_TYPE_EMBEDDED_MOCKING})
192e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    @Retention(RetentionPolicy.SOURCE)
193e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public @interface ConnectionType {}
194ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
1953cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    /**
1963cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * CarXyzService throws IllegalStateException with this message is re-thrown as
1973cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * {@link CarNotConnectedException}.
1983cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     *
1993cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @hide
2003cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     */
2013cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public static final String CAR_NOT_CONNECTED_EXCEPTION_MSG = "CarNotConnected";
2023cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
203e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    /** @hide */
204e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static final String CAR_SERVICE_INTERFACE_NAME = "android.car.ICar";
205e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
206e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private static final String CAR_SERVICE_PACKAGE = "com.android.car";
207e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
208e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private static final String CAR_TEST_MANAGER_CLASS = "android.car.CarTestManager";
209ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
210ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final Context mContext;
211ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final Looper mLooper;
212ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @GuardedBy("this")
213ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private ICar mService;
214ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private static final int STATE_DISCONNECTED = 0;
215ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private static final int STATE_CONNECTING = 1;
216ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private static final int STATE_CONNECTED = 2;
217ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @GuardedBy("this")
218ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private int mConnectionState;
219ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
220e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private final ServiceConnection mServiceConnectionListener =
221e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            new ServiceConnection () {
222ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        public void onServiceConnected(ComponentName name, IBinder service) {
2231ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung            synchronized (Car.this) {
224ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                mService = ICar.Stub.asInterface(service);
225ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                mConnectionState = STATE_CONNECTED;
226ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
227ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mServiceConnectionListenerClient.onServiceConnected(name, service);
228ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
229ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
230ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        public void onServiceDisconnected(ComponentName name) {
2311ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung            synchronized (Car.this) {
232ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                mService = null;
233ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                if (mConnectionState  == STATE_DISCONNECTED) {
234ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    return;
235ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                }
236cc449f7941456a0133ff8a4b2e49737f0936c1d0keunyoung                mConnectionState = STATE_DISCONNECTED;
237ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
238e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            // unbind explicitly here.
239e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            disconnect();
240ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mServiceConnectionListenerClient.onServiceDisconnected(name);
241ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
242ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    };
243ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
244e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private final ServiceConnection mServiceConnectionListenerClient;
245ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final Object mCarManagerLock = new Object();
246ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @GuardedBy("mCarManagerLock")
247ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private final HashMap<String, CarManagerBase> mServiceMap = new HashMap<>();
2486b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung
2496b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung    /** Handler for generic event dispatching. */
2506b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung    private final Handler mEventHandler;
2516b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung
2521ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung    /**
2538de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * A factory method that creates Car instance for all Car API access.
254ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param context
255e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park     * @param serviceConnectionListener listener for monitoring service connection.
256ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param looper Looper to dispatch all listeners. If null, it will use main thread. Note that
257ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     *        service connection listener will be always in main thread regardless of this Looper.
2588de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * @return Car instance if system is in car environment and returns {@code null} otherwise.
259ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
260e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static Car createCar(Context context, ServiceConnection serviceConnectionListener,
2618de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev            @Nullable Looper looper) {
262e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
263e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            Log.e(CarLibLog.TAG_CAR, "FEATURE_AUTOMOTIVE not declared while android.car is used");
264e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            return null;
265e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        }
2668de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        try {
2678de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev          return new Car(context, serviceConnectionListener, looper);
2688de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        } catch (IllegalArgumentException e) {
2698de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev          // Expected when car service loader is not available.
2708de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        }
2718de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev        return null;
2728de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev    }
2738de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev
2748de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev    /**
2758de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * A factory method that creates Car instance for all Car API access using main thread {@code
2768de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     * Looper}.
2778de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     *
278e4c731ea3ed22615783efb02818b0b3d184bba33Jason Tholstrup     * @see #createCar(Context, ServiceConnection, Looper)
2798de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev     */
280e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public static Car createCar(Context context, ServiceConnection serviceConnectionListener) {
2818de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev      return createCar(context, serviceConnectionListener, null);
2828de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev    }
2838de993354f1a8c30880b535cf8b80fee10c4e882Pavel Maltsev
284e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private Car(Context context, ServiceConnection serviceConnectionListener,
285ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            @Nullable Looper looper) {
286ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mContext = context;
287ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mServiceConnectionListenerClient = serviceConnectionListener;
288ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        if (looper == null) {
289ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mLooper = Looper.getMainLooper();
290ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        } else {
291ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mLooper = looper;
292ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
2936b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung        mEventHandler = new Handler(mLooper);
294ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
295ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
296ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
297ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Car constructor when ICar binder is already available.
298ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param context
299ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param service
300ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param looper
301ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     *
302ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @hide
303ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
304ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public Car(Context context, ICar service, @Nullable Looper looper) {
305ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mContext = context;
306ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        if (looper == null) {
307ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mLooper = Looper.getMainLooper();
308ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        } else {
309ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mLooper = looper;
310ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
3116b19769ee8cfbe0960d05ecfc01f73d08040784fkeunyoung        mEventHandler = new Handler(mLooper);
312ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mService = service;
313ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mConnectionState = STATE_CONNECTED;
314ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        mServiceConnectionListenerClient = null;
315ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
316ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
317ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
318ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Connect to car service. This can be called while it is disconnected.
319ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @throws IllegalStateException If connection is still on-going from previous
320ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     *         connect call or it is already connected
321ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
322ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public void connect() throws IllegalStateException {
323ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
324ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (mConnectionState != STATE_DISCONNECTED) {
325ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                throw new IllegalStateException("already connected or connecting");
326ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
327ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mConnectionState = STATE_CONNECTING;
328e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            startCarService();
329ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
330ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
331ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
332ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
333ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Disconnect from car service. This can be called while disconnected. Once disconnect is
334ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * called, all Car*Managers from this instance becomes invalid, and
335ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * {@link Car#getCarManager(String)} will return different instance if it is connected again.
336ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
337ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public void disconnect() {
338ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
339ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (mConnectionState == STATE_DISCONNECTED) {
340ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                return;
341ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
342ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            tearDownCarManagers();
343ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mService = null;
344ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mConnectionState = STATE_DISCONNECTED;
345e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            mContext.unbindService(mServiceConnectionListener);
346ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
347ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
348ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
349ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
350ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Tells if it is connected to the service or not. This will return false if it is still
351ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * connecting.
352ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
353ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
354ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public boolean isConnected() {
355ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
356ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            return mService != null;
357ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
358ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
359ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
360ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
361ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Tells if this instance is already connecting to car service or not.
362ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
363ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
364ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    public boolean isConnecting() {
365ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (this) {
366ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            return mConnectionState == STATE_CONNECTING;
367ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
368ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
369ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
370ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
371ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Get car specific service as in {@link Context#getSystemService(String)}. Returned
372ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * {@link Object} should be type-casted to the desired service.
373ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * For example, to get sensor service,
374ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * SensorManagerService sensorManagerService = car.getCarManager(Car.SENSOR_SERVICE);
375ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @param serviceName Name of service that should be created like {@link #SENSOR_SERVICE}.
376ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return Matching service manager or null if there is no such service.
377235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv     * @throws CarNotConnectedException
378ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
379235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv    public Object getCarManager(String serviceName) throws CarNotConnectedException {
380ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        CarManagerBase manager = null;
3811ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung        ICar service = getICarOrThrow();
382ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (mCarManagerLock) {
383ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            manager = mServiceMap.get(serviceName);
384ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            if (manager == null) {
385ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                try {
3861ab8e18e01d8063821bee0bf641a365224c7e1eekeunyoung                    IBinder binder = service.getCarService(serviceName);
387ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    if (binder == null) {
388ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        Log.w(CarLibLog.TAG_CAR, "getCarManager could not get binder for service:" +
389ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                                serviceName);
390ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        return null;
391ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    }
392e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                    manager = createCarManager(serviceName, binder);
393ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    if (manager == null) {
394ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        Log.w(CarLibLog.TAG_CAR,
395ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                                "getCarManager could not create manager for service:" +
396ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                                serviceName);
397ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                        return null;
398ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    }
399ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                    mServiceMap.put(serviceName, manager);
400ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                } catch (RemoteException e) {
401e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                    handleRemoteException(e);
402ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                }
403ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
404ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
405ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return manager;
406ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
407ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
408ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    /**
409ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * Return the type of currently connected car.
410ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     * @return
411ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung     */
412ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    @ConnectionType
413e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    public int getCarConnectionType() {
414e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        return CONNECTION_TYPE_EMBEDDED;
415ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
416ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
4173cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    /**
4183cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * IllegalStateException from XyzCarService with special message is re-thrown as a different
4193cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * exception. If the IllegalStateException is not understood then this message will throw the
4203cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * original exception.
4213cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     *
4223cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @param e exception from XyzCarService.
4233cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @throws CarNotConnectedException
4243cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     * @hide
4253cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal     */
4263cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public static void checkCarNotConnectedExceptionFromCarService(
4273cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            IllegalStateException e) throws CarNotConnectedException, IllegalStateException {
4283cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        String message = e.getMessage();
4293cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (message.equals(CAR_NOT_CONNECTED_EXCEPTION_MSG)) {
4303cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            throw new CarNotConnectedException();
4313cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        } else {
4323cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            throw e;
4333cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
4343cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
4353cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
436235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv    private CarManagerBase createCarManager(String serviceName, IBinder binder)
437235f8acd3cf83079ecd0f3e1b8368b0c9886de82Vitalii Tomkiv            throws CarNotConnectedException {
438e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        CarManagerBase manager = null;
439e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        switch (serviceName) {
440e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case AUDIO_SERVICE:
4416f3f402a7469e300fbfe65d950204fef995d4d8dVitalii Tomkiv                manager = new CarAudioManager(binder, mContext);
442e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
443e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case SENSOR_SERVICE:
444e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarSensorManager(binder, mContext, mLooper);
445e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
446e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case INFO_SERVICE:
447e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarInfoManager(binder);
448e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
449e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case APP_CONTEXT_SERVICE:
450e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarAppContextManager(binder, mLooper);
451e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
452e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case PACKAGE_SERVICE:
453e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarPackageManager(binder, mContext);
454e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
455e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case CAR_NAVIGATION_SERVICE:
456e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarNavigationManager(binder, mLooper);
457e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
458875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik            case CAMERA_SERVICE:
459875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik                manager = new CarCameraManager(binder, mContext);
460875616c52be0a5a4d3aa348e9dcfd90e54789912Steve Paik                break;
461e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case HVAC_SERVICE:
462e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarHvacManager(binder, mContext, mLooper);
463e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
4646e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv            case PROJECTION_SERVICE:
4656e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv                manager = new CarProjectionManager(binder, mLooper);
4666e5ee61be4c24ae4d647d687901b7c9670c25899Vitalii Tomkiv                break;
467e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case RADIO_SERVICE:
468e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarRadioManager(binder, mLooper);
469e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
470e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park            case TEST_SERVICE:
471e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                /* CarTestManager exist in static library. So instead of constructing it here,
472e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                 * only pass binder wrapper so that CarTestManager can be constructed outside. */
473e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                manager = new CarTestManagerBinderWrapper(binder);
474e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park                break;
475e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        }
476e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        return manager;
477e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    }
478e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
479e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    private void startCarService() {
480e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        Intent intent = new Intent();
481e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        intent.setPackage(CAR_SERVICE_PACKAGE);
482e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        intent.setAction(Car.CAR_SERVICE_INTERFACE_NAME);
483e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        mContext.startService(intent);
484e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park        mContext.bindService(intent, mServiceConnectionListener, 0);
485e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park    }
486e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Park
487ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private synchronized ICar getICarOrThrow() throws IllegalStateException {
488ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        if (mService == null) {
489ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            throw new IllegalStateException("not connected");
490ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
491ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        return mService;
492ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
493ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
494ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private void handleRemoteException(RemoteException e) {
495ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        Log.w(CarLibLog.TAG_CAR, "RemoteException", e);
496ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        disconnect();
497ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
498ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung
499ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    private void tearDownCarManagers() {
500ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        synchronized (mCarManagerLock) {
501ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            for (CarManagerBase manager: mServiceMap.values()) {
502ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung                manager.onCarDisconnected();
503ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            }
504ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung            mServiceMap.clear();
505ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung        }
506ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung    }
507ca515079e9fc0c35b1498830f67378e9ccf949e5keunyoung}
508