blob: abea6f76b54b8bea6686270f7d5bbee446fdb0f7 [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;
20import android.content.Intent;
keunyoung1ab8e182015-09-24 09:25:22 -070021import android.content.pm.PackageManager;
keunyoungca515072015-07-10 12:21:47 -070022import android.os.IBinder;
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070023import android.os.Process;
keunyoung6b197692015-11-16 13:54:38 -080024import android.os.RemoteException;
keunyoungca515072015-07-10 12:21:47 -070025import android.support.car.Car;
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
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070030import com.android.car.CarSystem;
keunyoungcc449f72015-08-12 10:46:27 -070031import com.android.car.hal.VehicleHal;
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;
keunyounga74b9ca2015-10-21 13:33:58 -070052 private final AppContextService mAppContextService;
Keun-young Park45fdcba2015-12-08 11:38:58 -080053 private final CarPackageManagerService mCarPackageManagerService;
keunyounga74b9ca2015-10-21 13:33:58 -070054
keunyoung1ab8e182015-09-24 09:25:22 -070055 /** Test only service. Populate it only when necessary. */
56 @GuardedBy("this")
57 private CarTestService mCarTestService;
keunyounga3b28d82015-08-25 13:05:15 -070058 private final CarServiceBase[] mAllServices;
keunyoungca515072015-07-10 12:21:47 -070059
keunyoung6b197692015-11-16 13:54:38 -080060 /** Holds connection listener from client. Only necessary for mocking. */
61 private final BinderInterfaceContainer<ICarConnectionListener> mCarConnectionListeners =
62 new BinderInterfaceContainer<>(null);
63
keunyoungca515072015-07-10 12:21:47 -070064 public synchronized static ICarImpl getInstance(Context serviceContext) {
65 if (sInstance == null) {
66 sInstance = new ICarImpl(serviceContext);
67 sInstance.init();
68 }
69 return sInstance;
70 }
71
72 public synchronized static void releaseInstance() {
73 if (sInstance == null) {
74 return;
75 }
76 sInstance.release();
77 sInstance = null;
78 }
79
80 public ICarImpl(Context serviceContext) {
81 mContext = serviceContext;
keunyoungfe30ba02015-09-17 17:56:35 -070082 mHal = VehicleHal.getInstance();
keunyoung4b0212c2015-10-29 17:11:57 -070083 mCarPowerManagementService = new CarPowerManagementService(serviceContext);
keunyounga3b28d82015-08-25 13:05:15 -070084 mCarInfoService = new CarInfoService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070085 mAppContextService = new AppContextService(serviceContext);
keunyoungca515072015-07-10 12:21:47 -070086 mCarSensorService = new CarSensorService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070087 mCarAudioService = new CarAudioService(serviceContext, mAppContextService);
Steve Paik66481982015-10-27 15:22:38 -070088 mCarHvacService = new CarHvacService(serviceContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070089 mCarRadioService = new CarRadioService(serviceContext);
Keun-young Park45fdcba2015-12-08 11:38:58 -080090 mCarPackageManagerService = new CarPackageManagerService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070091
keunyounga3b28d82015-08-25 13:05:15 -070092 // Be careful with order. Service depending on other service should be inited later.
93 mAllServices = new CarServiceBase[] {
keunyoung4b0212c2015-10-29 17:11:57 -070094 mCarPowerManagementService,
Keun-young Park45fdcba2015-12-08 11:38:58 -080095 mCarPackageManagerService,
keunyounga3b28d82015-08-25 13:05:15 -070096 mCarInfoService,
keunyounga74b9ca2015-10-21 13:33:58 -070097 mAppContextService,
keunyoungd32f4e62015-09-21 11:33:06 -070098 mCarSensorService,
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070099 mCarAudioService,
Steve Paik66481982015-10-27 15:22:38 -0700100 mCarHvacService,
keunyounga74b9ca2015-10-21 13:33:58 -0700101 mCarRadioService,
102 };
keunyoungca515072015-07-10 12:21:47 -0700103 }
104
105 private void init() {
keunyounga3b28d82015-08-25 13:05:15 -0700106 for (CarServiceBase service: mAllServices) {
107 service.init();
108 }
keunyoungca515072015-07-10 12:21:47 -0700109 }
110
111 private void release() {
keunyounge4c90c42015-11-16 18:42:52 -0800112 mCarConnectionListeners.clear();
keunyounga3b28d82015-08-25 13:05:15 -0700113 // release done in opposite order from init
114 for (int i = mAllServices.length - 1; i >= 0; i--) {
115 mAllServices[i].release();
116 }
keunyoungcc449f72015-08-12 10:46:27 -0700117 VehicleHal.releaseInstance();
keunyoungca515072015-07-10 12:21:47 -0700118 }
119
keunyoung4b0212c2015-10-29 17:11:57 -0700120 /** Only for CarTestService */
121 void startMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700122 reinitServices();
123 }
124
keunyoung4b0212c2015-10-29 17:11:57 -0700125 /** Only for CarTestService */
126 void stopMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700127 reinitServices();
128 }
129
keunyoung6b197692015-11-16 13:54:38 -0800130 /** Reset all services when starting / stopping vehicle hal mocking */
keunyoung1ab8e182015-09-24 09:25:22 -0700131 private void reinitServices() {
132 for (int i = mAllServices.length - 1; i >= 0; i--) {
133 mAllServices[i].release();
134 }
135 for (CarServiceBase service: mAllServices) {
136 service.init();
137 }
keunyoung6b197692015-11-16 13:54:38 -0800138 // send disconnect event and connect event to all clients.
139 Collection<BinderInterfaceContainer.BinderInterface<ICarConnectionListener>>
140 connectionListeners = mCarConnectionListeners.getInterfaces();
141 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
142 connectionListeners) {
143 try {
144 client.binderInterface.onDisconnected();
145 } catch (RemoteException e) {
146 //ignore
147 }
148 }
149 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
150 connectionListeners) {
151 try {
152 client.binderInterface.onConnected(Car.CONNECTION_TYPE_EMBEDDED);
153 } catch (RemoteException e) {
154 //ignore
155 }
156 }
keunyoung1ab8e182015-09-24 09:25:22 -0700157 }
158
keunyoungca515072015-07-10 12:21:47 -0700159 @Override
160 public int getVersion() {
161 return VERSION;
162 }
163
164 @Override
165 public IBinder getCarService(String serviceName) {
166 switch (serviceName) {
167 case Car.SENSOR_SERVICE:
168 return mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -0700169 case Car.INFO_SERVICE:
170 return mCarInfoService;
Steve Paik66481982015-10-27 15:22:38 -0700171
keunyounge4c90c42015-11-16 18:42:52 -0800172 case Car.APP_CONTEXT_SERVICE:
173 return mAppContextService;
Steve Paik66481982015-10-27 15:22:38 -0700174
Keun-young Park45fdcba2015-12-08 11:38:58 -0800175 case Car.PACKAGE_SERVICE:
176 return mCarPackageManagerService;
177
Steve Paik66481982015-10-27 15:22:38 -0700178 case CarSystem.HVAC_SERVICE:
179 assertHvacPermission(mContext);
180 return mCarHvacService;
181
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700182 case CarSystem.RADIO_SERVICE:
keunyoung6b197692015-11-16 13:54:38 -0800183 assertRadioPermission(mContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700184 return mCarRadioService;
keunyoung1ab8e182015-09-24 09:25:22 -0700185 case CarSystemTest.TEST_SERVICE: {
186 assertVehicleHalMockPermission(mContext);
187 synchronized (this) {
188 if (mCarTestService == null) {
189 mCarTestService = new CarTestService(mContext, this);
190 }
191 return mCarTestService;
192 }
193 }
keunyoungca515072015-07-10 12:21:47 -0700194 default:
195 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
196 return null;
197 }
198 }
199
200 @Override
keunyoungca515072015-07-10 12:21:47 -0700201 public boolean isConnectedToCar() {
202 return true; // always connected in embedded
203 }
204
205 @Override
206 public int getCarConnectionType() {
207 return Car.CONNECTION_TYPE_EMBEDDED;
208 }
209
210 @Override
211 public void registerCarConnectionListener(int clientVersion, ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800212 mCarConnectionListeners.addBinder(clientVersion, listener);
213 try {
214 listener.onConnected(Car.CONNECTION_TYPE_EMBEDDED);
215 } catch (RemoteException e) {
216 //ignore
217 }
keunyoungca515072015-07-10 12:21:47 -0700218 }
219
220 @Override
221 public void unregisterCarConnectionListener(ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800222 mCarConnectionListeners.removeBinder(listener);
keunyoungca515072015-07-10 12:21:47 -0700223 }
keunyoungcc449f72015-08-12 10:46:27 -0700224
keunyoung4b0212c2015-10-29 17:11:57 -0700225 /**
226 * Whether mocking underlying HAL or not.
227 * @return
228 */
229 public synchronized boolean isInMocking() {
230 if (mCarTestService == null) {
231 return false;
232 }
233 return mCarTestService.isInMocking();
234 }
235
keunyoung1ab8e182015-09-24 09:25:22 -0700236 public static void assertVehicleHalMockPermission(Context context) {
237 if (context.checkCallingOrSelfPermission(CarSystemTest.PERMISSION_MOCK_VEHICLE_HAL)
238 != PackageManager.PERMISSION_GRANTED) {
239 throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission");
240 }
241 }
242
Steve Paik66481982015-10-27 15:22:38 -0700243 public static void assertHvacPermission(Context context) {
244 if (context.checkCallingOrSelfPermission(CarSystem.PERMISSION_CAR_HVAC)
245 != PackageManager.PERMISSION_GRANTED) {
246 throw new SecurityException(
247 "requires " + CarSystem.PERMISSION_CAR_HVAC);
248 }
249 }
250
keunyoung6b197692015-11-16 13:54:38 -0800251 private static void assertRadioPermission(Context context) {
252 if (context.checkCallingOrSelfPermission(CarSystem.PERMISSION_CAR_RADIO)
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700253 != PackageManager.PERMISSION_GRANTED) {
254 throw new SecurityException(
Keun-young Parkaaeffaf2015-11-25 17:24:10 -0800255 "requires permission " + CarSystem.PERMISSION_CAR_RADIO);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700256 }
257 }
258
keunyoungcc449f72015-08-12 10:46:27 -0700259 void dump(PrintWriter writer) {
keunyounga3b28d82015-08-25 13:05:15 -0700260 writer.println("*Dump all services*");
261 for (CarServiceBase service: mAllServices) {
262 service.dump(writer);
263 }
keunyoung1ab8e182015-09-24 09:25:22 -0700264 CarTestService testService = mCarTestService;
265 if (testService != null) {
266 testService.dump(writer);
267 }
keunyoungcc449f72015-08-12 10:46:27 -0700268 }
keunyoungca515072015-07-10 12:21:47 -0700269}