blob: 7f83db26a593fa7f69d27b64320797be92fad89a [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
19import android.content.Context;
keunyoung1ab8e182015-09-24 09:25:22 -070020import android.content.pm.PackageManager;
keunyoungca515072015-07-10 12:21:47 -070021import android.os.IBinder;
keunyoung6b197692015-11-16 13:54:38 -080022import android.os.RemoteException;
keunyoungca515072015-07-10 12:21:47 -070023import android.support.car.Car;
Pavel Maltsev75623ce2016-01-20 16:02:59 -080024import android.support.car.CarSystem;
25import android.support.car.CarSystemTest;
keunyoungca515072015-07-10 12:21:47 -070026import android.support.car.ICar;
27import android.support.car.ICarConnectionListener;
keunyoungca515072015-07-10 12:21:47 -070028import android.util.Log;
29
keunyoungcc449f72015-08-12 10:46:27 -070030import com.android.car.hal.VehicleHal;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080031import com.android.car.pm.CarPackageManagerService;
keunyoungca515072015-07-10 12:21:47 -070032import com.android.internal.annotations.GuardedBy;
33
keunyounga3b28d82015-08-25 13:05:15 -070034import java.io.PrintWriter;
keunyoung6b197692015-11-16 13:54:38 -080035import java.util.Collection;
keunyounga3b28d82015-08-25 13:05:15 -070036
keunyoungca515072015-07-10 12:21:47 -070037public class ICarImpl extends ICar.Stub {
38 private static final int VERSION = 1;
39
40 @GuardedBy("ICarImpl.class")
41 private static ICarImpl sInstance = null;
42
43 private final Context mContext;
keunyoungcc449f72015-08-12 10:46:27 -070044 private final VehicleHal mHal;
keunyoungca515072015-07-10 12:21:47 -070045
keunyoung4b0212c2015-10-29 17:11:57 -070046 private final CarPowerManagementService mCarPowerManagementService;
keunyoungca515072015-07-10 12:21:47 -070047 private final CarSensorService mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -070048 private final CarInfoService mCarInfoService;
keunyoungd32f4e62015-09-21 11:33:06 -070049 private final CarAudioService mCarAudioService;
Steve Paik66481982015-10-27 15:22:38 -070050 private final CarHvacService mCarHvacService;
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070051 private final CarRadioService mCarRadioService;
Joseph Pirozzo317343d2016-01-25 10:22:37 -080052 private final CarNightService mCarNightService;
keunyounga74b9ca2015-10-21 13:33:58 -070053 private final AppContextService mAppContextService;
Keun-young Park45fdcba2015-12-08 11:38:58 -080054 private final CarPackageManagerService mCarPackageManagerService;
Yao Chen3a7976d2016-01-20 17:27:08 -080055 private final GarageModeService mGarageModeService;
Pavel Maltsev7a948e52016-02-02 23:30:14 -080056 private final CarNavigationStatusService mCarNavigationStatusService;
keunyounga74b9ca2015-10-21 13:33:58 -070057
keunyoung1ab8e182015-09-24 09:25:22 -070058 /** Test only service. Populate it only when necessary. */
59 @GuardedBy("this")
60 private CarTestService mCarTestService;
keunyounga3b28d82015-08-25 13:05:15 -070061 private final CarServiceBase[] mAllServices;
keunyoungca515072015-07-10 12:21:47 -070062
keunyoung6b197692015-11-16 13:54:38 -080063 /** Holds connection listener from client. Only necessary for mocking. */
64 private final BinderInterfaceContainer<ICarConnectionListener> mCarConnectionListeners =
65 new BinderInterfaceContainer<>(null);
66
keunyoungca515072015-07-10 12:21:47 -070067 public synchronized static ICarImpl getInstance(Context serviceContext) {
68 if (sInstance == null) {
69 sInstance = new ICarImpl(serviceContext);
70 sInstance.init();
71 }
72 return sInstance;
73 }
74
75 public synchronized static void releaseInstance() {
76 if (sInstance == null) {
77 return;
78 }
79 sInstance.release();
80 sInstance = null;
81 }
82
83 public ICarImpl(Context serviceContext) {
84 mContext = serviceContext;
keunyoungfe30ba02015-09-17 17:56:35 -070085 mHal = VehicleHal.getInstance();
keunyoung4b0212c2015-10-29 17:11:57 -070086 mCarPowerManagementService = new CarPowerManagementService(serviceContext);
Yao Chen3a7976d2016-01-20 17:27:08 -080087 mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService);
keunyounga3b28d82015-08-25 13:05:15 -070088 mCarInfoService = new CarInfoService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070089 mAppContextService = new AppContextService(serviceContext);
keunyoungca515072015-07-10 12:21:47 -070090 mCarSensorService = new CarSensorService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070091 mCarAudioService = new CarAudioService(serviceContext, mAppContextService);
Steve Paik66481982015-10-27 15:22:38 -070092 mCarHvacService = new CarHvacService(serviceContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070093 mCarRadioService = new CarRadioService(serviceContext);
Joseph Pirozzo317343d2016-01-25 10:22:37 -080094 mCarNightService = new CarNightService(serviceContext);
Keun-young Park45fdcba2015-12-08 11:38:58 -080095 mCarPackageManagerService = new CarPackageManagerService(serviceContext);
Pavel Maltsev7a948e52016-02-02 23:30:14 -080096 mCarNavigationStatusService = new CarNavigationStatusService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070097
keunyounga3b28d82015-08-25 13:05:15 -070098 // Be careful with order. Service depending on other service should be inited later.
99 mAllServices = new CarServiceBase[] {
keunyoung4b0212c2015-10-29 17:11:57 -0700100 mCarPowerManagementService,
Yao Chen3a7976d2016-01-20 17:27:08 -0800101 mGarageModeService,
Keun-young Park45fdcba2015-12-08 11:38:58 -0800102 mCarPackageManagerService,
keunyounga3b28d82015-08-25 13:05:15 -0700103 mCarInfoService,
keunyounga74b9ca2015-10-21 13:33:58 -0700104 mAppContextService,
keunyoungd32f4e62015-09-21 11:33:06 -0700105 mCarSensorService,
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700106 mCarAudioService,
Steve Paik66481982015-10-27 15:22:38 -0700107 mCarHvacService,
keunyounga74b9ca2015-10-21 13:33:58 -0700108 mCarRadioService,
Joseph Pirozzo317343d2016-01-25 10:22:37 -0800109 mCarNightService,
Pavel Maltsev7a948e52016-02-02 23:30:14 -0800110 mCarNavigationStatusService,
keunyounga74b9ca2015-10-21 13:33:58 -0700111 };
keunyoungca515072015-07-10 12:21:47 -0700112 }
113
114 private void init() {
keunyounga3b28d82015-08-25 13:05:15 -0700115 for (CarServiceBase service: mAllServices) {
116 service.init();
117 }
keunyoungca515072015-07-10 12:21:47 -0700118 }
119
120 private void release() {
keunyounge4c90c42015-11-16 18:42:52 -0800121 mCarConnectionListeners.clear();
keunyounga3b28d82015-08-25 13:05:15 -0700122 // release done in opposite order from init
123 for (int i = mAllServices.length - 1; i >= 0; i--) {
124 mAllServices[i].release();
125 }
keunyoungcc449f72015-08-12 10:46:27 -0700126 VehicleHal.releaseInstance();
keunyoungca515072015-07-10 12:21:47 -0700127 }
128
keunyoung4b0212c2015-10-29 17:11:57 -0700129 /** Only for CarTestService */
130 void startMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700131 reinitServices();
132 }
133
keunyoung4b0212c2015-10-29 17:11:57 -0700134 /** Only for CarTestService */
135 void stopMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700136 reinitServices();
137 }
138
keunyoung6b197692015-11-16 13:54:38 -0800139 /** Reset all services when starting / stopping vehicle hal mocking */
keunyoung1ab8e182015-09-24 09:25:22 -0700140 private void reinitServices() {
141 for (int i = mAllServices.length - 1; i >= 0; i--) {
142 mAllServices[i].release();
143 }
144 for (CarServiceBase service: mAllServices) {
145 service.init();
146 }
keunyoung6b197692015-11-16 13:54:38 -0800147 // send disconnect event and connect event to all clients.
148 Collection<BinderInterfaceContainer.BinderInterface<ICarConnectionListener>>
149 connectionListeners = mCarConnectionListeners.getInterfaces();
150 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
151 connectionListeners) {
152 try {
153 client.binderInterface.onDisconnected();
154 } catch (RemoteException e) {
155 //ignore
156 }
157 }
158 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
159 connectionListeners) {
160 try {
161 client.binderInterface.onConnected(Car.CONNECTION_TYPE_EMBEDDED);
162 } catch (RemoteException e) {
163 //ignore
164 }
165 }
keunyoung1ab8e182015-09-24 09:25:22 -0700166 }
167
keunyoungca515072015-07-10 12:21:47 -0700168 @Override
169 public int getVersion() {
170 return VERSION;
171 }
172
173 @Override
174 public IBinder getCarService(String serviceName) {
175 switch (serviceName) {
Keun-young Park5672e852016-02-09 19:53:48 -0800176 case Car.AUDIO_SERVICE:
177 return mCarAudioService;
keunyoungca515072015-07-10 12:21:47 -0700178 case Car.SENSOR_SERVICE:
179 return mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -0700180 case Car.INFO_SERVICE:
181 return mCarInfoService;
keunyounge4c90c42015-11-16 18:42:52 -0800182 case Car.APP_CONTEXT_SERVICE:
183 return mAppContextService;
Keun-young Park45fdcba2015-12-08 11:38:58 -0800184 case Car.PACKAGE_SERVICE:
185 return mCarPackageManagerService;
Steve Paik66481982015-10-27 15:22:38 -0700186 case CarSystem.HVAC_SERVICE:
187 assertHvacPermission(mContext);
188 return mCarHvacService;
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700189 case CarSystem.RADIO_SERVICE:
keunyoung6b197692015-11-16 13:54:38 -0800190 assertRadioPermission(mContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700191 return mCarRadioService;
Pavel Maltsev7a948e52016-02-02 23:30:14 -0800192 case Car.CAR_NAVIGATION_SERVICE:
193 return mCarNavigationStatusService;
keunyoung1ab8e182015-09-24 09:25:22 -0700194 case CarSystemTest.TEST_SERVICE: {
195 assertVehicleHalMockPermission(mContext);
196 synchronized (this) {
197 if (mCarTestService == null) {
198 mCarTestService = new CarTestService(mContext, this);
199 }
200 return mCarTestService;
201 }
202 }
keunyoungca515072015-07-10 12:21:47 -0700203 default:
204 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
205 return null;
206 }
207 }
208
209 @Override
keunyoungca515072015-07-10 12:21:47 -0700210 public boolean isConnectedToCar() {
211 return true; // always connected in embedded
212 }
213
214 @Override
215 public int getCarConnectionType() {
216 return Car.CONNECTION_TYPE_EMBEDDED;
217 }
218
219 @Override
220 public void registerCarConnectionListener(int clientVersion, ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800221 mCarConnectionListeners.addBinder(clientVersion, listener);
222 try {
223 listener.onConnected(Car.CONNECTION_TYPE_EMBEDDED);
224 } catch (RemoteException e) {
225 //ignore
226 }
keunyoungca515072015-07-10 12:21:47 -0700227 }
228
229 @Override
230 public void unregisterCarConnectionListener(ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800231 mCarConnectionListeners.removeBinder(listener);
keunyoungca515072015-07-10 12:21:47 -0700232 }
keunyoungcc449f72015-08-12 10:46:27 -0700233
keunyoung4b0212c2015-10-29 17:11:57 -0700234 /**
235 * Whether mocking underlying HAL or not.
236 * @return
237 */
238 public synchronized boolean isInMocking() {
239 if (mCarTestService == null) {
240 return false;
241 }
242 return mCarTestService.isInMocking();
243 }
244
keunyoung1ab8e182015-09-24 09:25:22 -0700245 public static void assertVehicleHalMockPermission(Context context) {
246 if (context.checkCallingOrSelfPermission(CarSystemTest.PERMISSION_MOCK_VEHICLE_HAL)
247 != PackageManager.PERMISSION_GRANTED) {
248 throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission");
249 }
250 }
251
Steve Paik66481982015-10-27 15:22:38 -0700252 public static void assertHvacPermission(Context context) {
253 if (context.checkCallingOrSelfPermission(CarSystem.PERMISSION_CAR_HVAC)
254 != PackageManager.PERMISSION_GRANTED) {
255 throw new SecurityException(
256 "requires " + CarSystem.PERMISSION_CAR_HVAC);
257 }
258 }
259
keunyoung6b197692015-11-16 13:54:38 -0800260 private static void assertRadioPermission(Context context) {
261 if (context.checkCallingOrSelfPermission(CarSystem.PERMISSION_CAR_RADIO)
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700262 != PackageManager.PERMISSION_GRANTED) {
263 throw new SecurityException(
Keun-young Parkaaeffaf2015-11-25 17:24:10 -0800264 "requires permission " + CarSystem.PERMISSION_CAR_RADIO);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700265 }
266 }
267
keunyoungcc449f72015-08-12 10:46:27 -0700268 void dump(PrintWriter writer) {
keunyounga3b28d82015-08-25 13:05:15 -0700269 writer.println("*Dump all services*");
270 for (CarServiceBase service: mAllServices) {
271 service.dump(writer);
272 }
keunyoung1ab8e182015-09-24 09:25:22 -0700273 CarTestService testService = mCarTestService;
274 if (testService != null) {
275 testService.dump(writer);
276 }
keunyoungcc449f72015-08-12 10:46:27 -0700277 }
keunyoungca515072015-07-10 12:21:47 -0700278}