blob: 37480bee48669fb5721800fec2acbf550b6bface [file] [log] [blame]
keunyoungca515072015-07-10 12:21:47 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.car;
18
Keun-young Parke54ac272016-02-16 19:02:18 -080019import android.car.Car;
20import android.car.ICar;
21import android.car.ICarConnectionListener;
keunyoungca515072015-07-10 12:21:47 -070022import android.content.Context;
keunyoung1ab8e182015-09-24 09:25:22 -070023import android.content.pm.PackageManager;
keunyoungca515072015-07-10 12:21:47 -070024import android.os.IBinder;
keunyoung6b197692015-11-16 13:54:38 -080025import android.os.RemoteException;
keunyoungca515072015-07-10 12:21:47 -070026import android.util.Log;
27
keunyoungcc449f72015-08-12 10:46:27 -070028import com.android.car.hal.VehicleHal;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080029import com.android.car.pm.CarPackageManagerService;
keunyoungca515072015-07-10 12:21:47 -070030import com.android.internal.annotations.GuardedBy;
31
keunyounga3b28d82015-08-25 13:05:15 -070032import java.io.PrintWriter;
keunyoung6b197692015-11-16 13:54:38 -080033import java.util.Collection;
keunyounga3b28d82015-08-25 13:05:15 -070034
keunyoungca515072015-07-10 12:21:47 -070035public class ICarImpl extends ICar.Stub {
keunyoungca515072015-07-10 12:21:47 -070036
Keun-young Parka28d7b22016-02-29 16:54:29 -080037 public static final String INTERNAL_INPUT_SERVICE = "internal_input";
38
39 // load jni for all services here
40 static {
41 System.loadLibrary("jni_car_service");
42 }
43
keunyoungca515072015-07-10 12:21:47 -070044 @GuardedBy("ICarImpl.class")
45 private static ICarImpl sInstance = null;
46
47 private final Context mContext;
keunyoungcc449f72015-08-12 10:46:27 -070048 private final VehicleHal mHal;
keunyoungca515072015-07-10 12:21:47 -070049
keunyoung4b0212c2015-10-29 17:11:57 -070050 private final CarPowerManagementService mCarPowerManagementService;
Keun-young Parka28d7b22016-02-29 16:54:29 -080051 private final CarPackageManagerService mCarPackageManagerService;
52 private final CarInputService mCarInputService;
keunyoungca515072015-07-10 12:21:47 -070053 private final CarSensorService mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -070054 private final CarInfoService mCarInfoService;
keunyoungd32f4e62015-09-21 11:33:06 -070055 private final CarAudioService mCarAudioService;
Steve Paik875616c2016-02-05 10:55:59 -080056 private final CarCameraService mCarCameraService;
Steve Paik66481982015-10-27 15:22:38 -070057 private final CarHvacService mCarHvacService;
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070058 private final CarRadioService mCarRadioService;
Joseph Pirozzo317343d2016-01-25 10:22:37 -080059 private final CarNightService mCarNightService;
keunyounga74b9ca2015-10-21 13:33:58 -070060 private final AppContextService mAppContextService;
Yao Chen3a7976d2016-01-20 17:27:08 -080061 private final GarageModeService mGarageModeService;
Keun-young Parke54ac272016-02-16 19:02:18 -080062 private final CarNavigationService mCarNavigationStatusService;
keunyounga74b9ca2015-10-21 13:33:58 -070063
keunyoung1ab8e182015-09-24 09:25:22 -070064 /** Test only service. Populate it only when necessary. */
65 @GuardedBy("this")
66 private CarTestService mCarTestService;
keunyounga3b28d82015-08-25 13:05:15 -070067 private final CarServiceBase[] mAllServices;
keunyoungca515072015-07-10 12:21:47 -070068
keunyoung6b197692015-11-16 13:54:38 -080069 /** Holds connection listener from client. Only necessary for mocking. */
70 private final BinderInterfaceContainer<ICarConnectionListener> mCarConnectionListeners =
71 new BinderInterfaceContainer<>(null);
72
keunyoungca515072015-07-10 12:21:47 -070073 public synchronized static ICarImpl getInstance(Context serviceContext) {
74 if (sInstance == null) {
75 sInstance = new ICarImpl(serviceContext);
76 sInstance.init();
77 }
78 return sInstance;
79 }
80
81 public synchronized static void releaseInstance() {
82 if (sInstance == null) {
83 return;
84 }
85 sInstance.release();
86 sInstance = null;
87 }
88
89 public ICarImpl(Context serviceContext) {
90 mContext = serviceContext;
keunyoungfe30ba02015-09-17 17:56:35 -070091 mHal = VehicleHal.getInstance();
keunyoung4b0212c2015-10-29 17:11:57 -070092 mCarPowerManagementService = new CarPowerManagementService(serviceContext);
Keun-young Parka28d7b22016-02-29 16:54:29 -080093 mCarPackageManagerService = new CarPackageManagerService(serviceContext);
94 mCarInputService = new CarInputService(serviceContext);
Yao Chen3a7976d2016-01-20 17:27:08 -080095 mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
keunyounga3b28d82015-08-25 13:05:15 -070096 mCarInfoService = new CarInfoService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070097 mAppContextService = new AppContextService(serviceContext);
keunyoungca515072015-07-10 12:21:47 -070098 mCarSensorService = new CarSensorService(serviceContext);
Keun-young Parka28d7b22016-02-29 16:54:29 -080099 mCarAudioService = new CarAudioService(serviceContext);
Steve Paik66481982015-10-27 15:22:38 -0700100 mCarHvacService = new CarHvacService(serviceContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700101 mCarRadioService = new CarRadioService(serviceContext);
Steve Paik875616c2016-02-05 10:55:59 -0800102 mCarCameraService = new CarCameraService(serviceContext);
Joseph Pirozzo317343d2016-01-25 10:22:37 -0800103 mCarNightService = new CarNightService(serviceContext);
Pavel Maltsevf78d8712016-02-25 16:07:46 -0800104 mCarNavigationStatusService = new CarNavigationService(serviceContext, mAppContextService);
keunyounga74b9ca2015-10-21 13:33:58 -0700105
keunyounga3b28d82015-08-25 13:05:15 -0700106 // Be careful with order. Service depending on other service should be inited later.
107 mAllServices = new CarServiceBase[] {
keunyoung4b0212c2015-10-29 17:11:57 -0700108 mCarPowerManagementService,
Keun-young Park45fdcba2015-12-08 11:38:58 -0800109 mCarPackageManagerService,
Keun-young Parka28d7b22016-02-29 16:54:29 -0800110 mCarInputService,
111 mGarageModeService,
keunyounga3b28d82015-08-25 13:05:15 -0700112 mCarInfoService,
keunyounga74b9ca2015-10-21 13:33:58 -0700113 mAppContextService,
keunyoungd32f4e62015-09-21 11:33:06 -0700114 mCarSensorService,
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700115 mCarAudioService,
Steve Paik66481982015-10-27 15:22:38 -0700116 mCarHvacService,
Steve Paik875616c2016-02-05 10:55:59 -0800117 mCarRadioService, mCarCameraService,
Joseph Pirozzo317343d2016-01-25 10:22:37 -0800118 mCarNightService,
Pavel Maltsev7a948e52016-02-02 23:30:14 -0800119 mCarNavigationStatusService,
keunyounga74b9ca2015-10-21 13:33:58 -0700120 };
keunyoungca515072015-07-10 12:21:47 -0700121 }
122
123 private void init() {
keunyounga3b28d82015-08-25 13:05:15 -0700124 for (CarServiceBase service: mAllServices) {
125 service.init();
126 }
keunyoungca515072015-07-10 12:21:47 -0700127 }
128
129 private void release() {
keunyounge4c90c42015-11-16 18:42:52 -0800130 mCarConnectionListeners.clear();
keunyounga3b28d82015-08-25 13:05:15 -0700131 // release done in opposite order from init
132 for (int i = mAllServices.length - 1; i >= 0; i--) {
133 mAllServices[i].release();
134 }
keunyoungcc449f72015-08-12 10:46:27 -0700135 VehicleHal.releaseInstance();
keunyoungca515072015-07-10 12:21:47 -0700136 }
137
keunyoung4b0212c2015-10-29 17:11:57 -0700138 /** Only for CarTestService */
139 void startMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700140 reinitServices();
141 }
142
keunyoung4b0212c2015-10-29 17:11:57 -0700143 /** Only for CarTestService */
144 void stopMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700145 reinitServices();
146 }
147
keunyoung6b197692015-11-16 13:54:38 -0800148 /** Reset all services when starting / stopping vehicle hal mocking */
keunyoung1ab8e182015-09-24 09:25:22 -0700149 private void reinitServices() {
150 for (int i = mAllServices.length - 1; i >= 0; i--) {
151 mAllServices[i].release();
152 }
153 for (CarServiceBase service: mAllServices) {
154 service.init();
155 }
keunyoung6b197692015-11-16 13:54:38 -0800156 // send disconnect event and connect event to all clients.
157 Collection<BinderInterfaceContainer.BinderInterface<ICarConnectionListener>>
158 connectionListeners = mCarConnectionListeners.getInterfaces();
159 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
160 connectionListeners) {
161 try {
162 client.binderInterface.onDisconnected();
163 } catch (RemoteException e) {
164 //ignore
165 }
166 }
167 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
168 connectionListeners) {
169 try {
Keun-young Parke54ac272016-02-16 19:02:18 -0800170 client.binderInterface.onConnected();
keunyoung6b197692015-11-16 13:54:38 -0800171 } catch (RemoteException e) {
172 //ignore
173 }
174 }
keunyoung1ab8e182015-09-24 09:25:22 -0700175 }
176
keunyoungca515072015-07-10 12:21:47 -0700177 @Override
keunyoungca515072015-07-10 12:21:47 -0700178 public IBinder getCarService(String serviceName) {
179 switch (serviceName) {
Keun-young Park5672e852016-02-09 19:53:48 -0800180 case Car.AUDIO_SERVICE:
181 return mCarAudioService;
keunyoungca515072015-07-10 12:21:47 -0700182 case Car.SENSOR_SERVICE:
183 return mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -0700184 case Car.INFO_SERVICE:
185 return mCarInfoService;
keunyounge4c90c42015-11-16 18:42:52 -0800186 case Car.APP_CONTEXT_SERVICE:
187 return mAppContextService;
Keun-young Park45fdcba2015-12-08 11:38:58 -0800188 case Car.PACKAGE_SERVICE:
189 return mCarPackageManagerService;
Steve Paik875616c2016-02-05 10:55:59 -0800190 case Car.CAMERA_SERVICE:
191 assertCameraPermission(mContext);
192 return mCarCameraService;
Keun-young Parke54ac272016-02-16 19:02:18 -0800193 case Car.HVAC_SERVICE:
Steve Paik66481982015-10-27 15:22:38 -0700194 assertHvacPermission(mContext);
195 return mCarHvacService;
Keun-young Parke54ac272016-02-16 19:02:18 -0800196 case Car.RADIO_SERVICE:
keunyoung6b197692015-11-16 13:54:38 -0800197 assertRadioPermission(mContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700198 return mCarRadioService;
Pavel Maltsev7a948e52016-02-02 23:30:14 -0800199 case Car.CAR_NAVIGATION_SERVICE:
200 return mCarNavigationStatusService;
Keun-young Parke54ac272016-02-16 19:02:18 -0800201 case Car.TEST_SERVICE: {
keunyoung1ab8e182015-09-24 09:25:22 -0700202 assertVehicleHalMockPermission(mContext);
203 synchronized (this) {
204 if (mCarTestService == null) {
205 mCarTestService = new CarTestService(mContext, this);
206 }
207 return mCarTestService;
208 }
209 }
keunyoungca515072015-07-10 12:21:47 -0700210 default:
211 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
212 return null;
213 }
214 }
215
Keun-young Parka28d7b22016-02-29 16:54:29 -0800216 public CarServiceBase getCarInternalService(String serviceName) {
217 switch (serviceName) {
218 case INTERNAL_INPUT_SERVICE:
219 return mCarInputService;
220 default:
221 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" +
222 serviceName);
223 return null;
224 }
225 }
226
keunyoungca515072015-07-10 12:21:47 -0700227 @Override
keunyoungca515072015-07-10 12:21:47 -0700228 public boolean isConnectedToCar() {
229 return true; // always connected in embedded
230 }
231
232 @Override
Keun-young Parke54ac272016-02-16 19:02:18 -0800233 public void registerCarConnectionListener(ICarConnectionListener listener) {
234 mCarConnectionListeners.addBinder(listener);
keunyoung6b197692015-11-16 13:54:38 -0800235 try {
Keun-young Parke54ac272016-02-16 19:02:18 -0800236 listener.onConnected();
keunyoung6b197692015-11-16 13:54:38 -0800237 } catch (RemoteException e) {
238 //ignore
239 }
keunyoungca515072015-07-10 12:21:47 -0700240 }
241
242 @Override
243 public void unregisterCarConnectionListener(ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800244 mCarConnectionListeners.removeBinder(listener);
keunyoungca515072015-07-10 12:21:47 -0700245 }
keunyoungcc449f72015-08-12 10:46:27 -0700246
keunyoung4b0212c2015-10-29 17:11:57 -0700247 /**
248 * Whether mocking underlying HAL or not.
249 * @return
250 */
251 public synchronized boolean isInMocking() {
252 if (mCarTestService == null) {
253 return false;
254 }
255 return mCarTestService.isInMocking();
256 }
257
keunyoung1ab8e182015-09-24 09:25:22 -0700258 public static void assertVehicleHalMockPermission(Context context) {
Keun-young Parke54ac272016-02-16 19:02:18 -0800259 if (context.checkCallingOrSelfPermission(Car.PERMISSION_MOCK_VEHICLE_HAL)
keunyoung1ab8e182015-09-24 09:25:22 -0700260 != PackageManager.PERMISSION_GRANTED) {
261 throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission");
262 }
263 }
264
Steve Paik875616c2016-02-05 10:55:59 -0800265 public static void assertCameraPermission(Context context) {
266 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_CAMERA)
267 != PackageManager.PERMISSION_GRANTED) {
268 throw new SecurityException(
269 "requires " + Car.PERMISSION_CAR_CAMERA);
270 }
271 }
272
Steve Paik66481982015-10-27 15:22:38 -0700273 public static void assertHvacPermission(Context context) {
Keun-young Parke54ac272016-02-16 19:02:18 -0800274 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_HVAC)
Steve Paik66481982015-10-27 15:22:38 -0700275 != PackageManager.PERMISSION_GRANTED) {
276 throw new SecurityException(
Keun-young Parke54ac272016-02-16 19:02:18 -0800277 "requires " + Car.PERMISSION_CAR_HVAC);
Steve Paik66481982015-10-27 15:22:38 -0700278 }
279 }
280
keunyoung6b197692015-11-16 13:54:38 -0800281 private static void assertRadioPermission(Context context) {
Keun-young Parke54ac272016-02-16 19:02:18 -0800282 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_RADIO)
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700283 != PackageManager.PERMISSION_GRANTED) {
284 throw new SecurityException(
Keun-young Parke54ac272016-02-16 19:02:18 -0800285 "requires permission " + Car.PERMISSION_CAR_RADIO);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700286 }
287 }
288
keunyoungcc449f72015-08-12 10:46:27 -0700289 void dump(PrintWriter writer) {
keunyounga3b28d82015-08-25 13:05:15 -0700290 writer.println("*Dump all services*");
291 for (CarServiceBase service: mAllServices) {
292 service.dump(writer);
293 }
keunyoung1ab8e182015-09-24 09:25:22 -0700294 CarTestService testService = mCarTestService;
295 if (testService != null) {
296 testService.dump(writer);
297 }
keunyoungcc449f72015-08-12 10:46:27 -0700298 }
keunyoungca515072015-07-10 12:21:47 -0700299}