blob: 6a478ed4c1bc7e5120d9f18f81bcd584ad3413ee [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;
Keun-young Park4aeb4bf2015-12-08 18:31:33 -080032import com.android.car.pm.CarPackageManagerService;
keunyoungca515072015-07-10 12:21:47 -070033import com.android.internal.annotations.GuardedBy;
34
keunyounga3b28d82015-08-25 13:05:15 -070035import java.io.PrintWriter;
keunyoung6b197692015-11-16 13:54:38 -080036import java.util.Collection;
keunyounga3b28d82015-08-25 13:05:15 -070037
keunyoungca515072015-07-10 12:21:47 -070038public class ICarImpl extends ICar.Stub {
39 private static final int VERSION = 1;
40
41 @GuardedBy("ICarImpl.class")
42 private static ICarImpl sInstance = null;
43
44 private final Context mContext;
keunyoungcc449f72015-08-12 10:46:27 -070045 private final VehicleHal mHal;
keunyoungca515072015-07-10 12:21:47 -070046
keunyoung4b0212c2015-10-29 17:11:57 -070047 private final CarPowerManagementService mCarPowerManagementService;
keunyoungca515072015-07-10 12:21:47 -070048 private final CarSensorService mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -070049 private final CarInfoService mCarInfoService;
keunyoungd32f4e62015-09-21 11:33:06 -070050 private final CarAudioService mCarAudioService;
Steve Paik66481982015-10-27 15:22:38 -070051 private final CarHvacService mCarHvacService;
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070052 private final CarRadioService mCarRadioService;
keunyounga74b9ca2015-10-21 13:33:58 -070053 private final AppContextService mAppContextService;
Keun-young Park45fdcba2015-12-08 11:38:58 -080054 private final CarPackageManagerService mCarPackageManagerService;
keunyounga74b9ca2015-10-21 13:33:58 -070055
keunyoung1ab8e182015-09-24 09:25:22 -070056 /** Test only service. Populate it only when necessary. */
57 @GuardedBy("this")
58 private CarTestService mCarTestService;
keunyounga3b28d82015-08-25 13:05:15 -070059 private final CarServiceBase[] mAllServices;
keunyoungca515072015-07-10 12:21:47 -070060
keunyoung6b197692015-11-16 13:54:38 -080061 /** Holds connection listener from client. Only necessary for mocking. */
62 private final BinderInterfaceContainer<ICarConnectionListener> mCarConnectionListeners =
63 new BinderInterfaceContainer<>(null);
64
keunyoungca515072015-07-10 12:21:47 -070065 public synchronized static ICarImpl getInstance(Context serviceContext) {
66 if (sInstance == null) {
67 sInstance = new ICarImpl(serviceContext);
68 sInstance.init();
69 }
70 return sInstance;
71 }
72
73 public synchronized static void releaseInstance() {
74 if (sInstance == null) {
75 return;
76 }
77 sInstance.release();
78 sInstance = null;
79 }
80
81 public ICarImpl(Context serviceContext) {
82 mContext = serviceContext;
keunyoungfe30ba02015-09-17 17:56:35 -070083 mHal = VehicleHal.getInstance();
keunyoung4b0212c2015-10-29 17:11:57 -070084 mCarPowerManagementService = new CarPowerManagementService(serviceContext);
keunyounga3b28d82015-08-25 13:05:15 -070085 mCarInfoService = new CarInfoService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070086 mAppContextService = new AppContextService(serviceContext);
keunyoungca515072015-07-10 12:21:47 -070087 mCarSensorService = new CarSensorService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070088 mCarAudioService = new CarAudioService(serviceContext, mAppContextService);
Steve Paik66481982015-10-27 15:22:38 -070089 mCarHvacService = new CarHvacService(serviceContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -070090 mCarRadioService = new CarRadioService(serviceContext);
Keun-young Park45fdcba2015-12-08 11:38:58 -080091 mCarPackageManagerService = new CarPackageManagerService(serviceContext);
keunyounga74b9ca2015-10-21 13:33:58 -070092
keunyounga3b28d82015-08-25 13:05:15 -070093 // Be careful with order. Service depending on other service should be inited later.
94 mAllServices = new CarServiceBase[] {
keunyoung4b0212c2015-10-29 17:11:57 -070095 mCarPowerManagementService,
Keun-young Park45fdcba2015-12-08 11:38:58 -080096 mCarPackageManagerService,
keunyounga3b28d82015-08-25 13:05:15 -070097 mCarInfoService,
keunyounga74b9ca2015-10-21 13:33:58 -070098 mAppContextService,
keunyoungd32f4e62015-09-21 11:33:06 -070099 mCarSensorService,
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700100 mCarAudioService,
Steve Paik66481982015-10-27 15:22:38 -0700101 mCarHvacService,
keunyounga74b9ca2015-10-21 13:33:58 -0700102 mCarRadioService,
103 };
keunyoungca515072015-07-10 12:21:47 -0700104 }
105
106 private void init() {
keunyounga3b28d82015-08-25 13:05:15 -0700107 for (CarServiceBase service: mAllServices) {
108 service.init();
109 }
keunyoungca515072015-07-10 12:21:47 -0700110 }
111
112 private void release() {
keunyounge4c90c42015-11-16 18:42:52 -0800113 mCarConnectionListeners.clear();
keunyounga3b28d82015-08-25 13:05:15 -0700114 // release done in opposite order from init
115 for (int i = mAllServices.length - 1; i >= 0; i--) {
116 mAllServices[i].release();
117 }
keunyoungcc449f72015-08-12 10:46:27 -0700118 VehicleHal.releaseInstance();
keunyoungca515072015-07-10 12:21:47 -0700119 }
120
keunyoung4b0212c2015-10-29 17:11:57 -0700121 /** Only for CarTestService */
122 void startMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700123 reinitServices();
124 }
125
keunyoung4b0212c2015-10-29 17:11:57 -0700126 /** Only for CarTestService */
127 void stopMocking() {
keunyoung1ab8e182015-09-24 09:25:22 -0700128 reinitServices();
129 }
130
keunyoung6b197692015-11-16 13:54:38 -0800131 /** Reset all services when starting / stopping vehicle hal mocking */
keunyoung1ab8e182015-09-24 09:25:22 -0700132 private void reinitServices() {
133 for (int i = mAllServices.length - 1; i >= 0; i--) {
134 mAllServices[i].release();
135 }
136 for (CarServiceBase service: mAllServices) {
137 service.init();
138 }
keunyoung6b197692015-11-16 13:54:38 -0800139 // send disconnect event and connect event to all clients.
140 Collection<BinderInterfaceContainer.BinderInterface<ICarConnectionListener>>
141 connectionListeners = mCarConnectionListeners.getInterfaces();
142 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
143 connectionListeners) {
144 try {
145 client.binderInterface.onDisconnected();
146 } catch (RemoteException e) {
147 //ignore
148 }
149 }
150 for (BinderInterfaceContainer.BinderInterface<ICarConnectionListener> client :
151 connectionListeners) {
152 try {
153 client.binderInterface.onConnected(Car.CONNECTION_TYPE_EMBEDDED);
154 } catch (RemoteException e) {
155 //ignore
156 }
157 }
keunyoung1ab8e182015-09-24 09:25:22 -0700158 }
159
keunyoungca515072015-07-10 12:21:47 -0700160 @Override
161 public int getVersion() {
162 return VERSION;
163 }
164
165 @Override
166 public IBinder getCarService(String serviceName) {
167 switch (serviceName) {
168 case Car.SENSOR_SERVICE:
169 return mCarSensorService;
keunyounga3b28d82015-08-25 13:05:15 -0700170 case Car.INFO_SERVICE:
171 return mCarInfoService;
Steve Paik66481982015-10-27 15:22:38 -0700172
keunyounge4c90c42015-11-16 18:42:52 -0800173 case Car.APP_CONTEXT_SERVICE:
174 return mAppContextService;
Steve Paik66481982015-10-27 15:22:38 -0700175
Keun-young Park45fdcba2015-12-08 11:38:58 -0800176 case Car.PACKAGE_SERVICE:
177 return mCarPackageManagerService;
178
Steve Paik66481982015-10-27 15:22:38 -0700179 case CarSystem.HVAC_SERVICE:
180 assertHvacPermission(mContext);
181 return mCarHvacService;
182
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700183 case CarSystem.RADIO_SERVICE:
keunyoung6b197692015-11-16 13:54:38 -0800184 assertRadioPermission(mContext);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700185 return mCarRadioService;
keunyoung1ab8e182015-09-24 09:25:22 -0700186 case CarSystemTest.TEST_SERVICE: {
187 assertVehicleHalMockPermission(mContext);
188 synchronized (this) {
189 if (mCarTestService == null) {
190 mCarTestService = new CarTestService(mContext, this);
191 }
192 return mCarTestService;
193 }
194 }
keunyoungca515072015-07-10 12:21:47 -0700195 default:
196 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName);
197 return null;
198 }
199 }
200
201 @Override
keunyoungca515072015-07-10 12:21:47 -0700202 public boolean isConnectedToCar() {
203 return true; // always connected in embedded
204 }
205
206 @Override
207 public int getCarConnectionType() {
208 return Car.CONNECTION_TYPE_EMBEDDED;
209 }
210
211 @Override
212 public void registerCarConnectionListener(int clientVersion, ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800213 mCarConnectionListeners.addBinder(clientVersion, listener);
214 try {
215 listener.onConnected(Car.CONNECTION_TYPE_EMBEDDED);
216 } catch (RemoteException e) {
217 //ignore
218 }
keunyoungca515072015-07-10 12:21:47 -0700219 }
220
221 @Override
222 public void unregisterCarConnectionListener(ICarConnectionListener listener) {
keunyoung6b197692015-11-16 13:54:38 -0800223 mCarConnectionListeners.removeBinder(listener);
keunyoungca515072015-07-10 12:21:47 -0700224 }
keunyoungcc449f72015-08-12 10:46:27 -0700225
keunyoung4b0212c2015-10-29 17:11:57 -0700226 /**
227 * Whether mocking underlying HAL or not.
228 * @return
229 */
230 public synchronized boolean isInMocking() {
231 if (mCarTestService == null) {
232 return false;
233 }
234 return mCarTestService.isInMocking();
235 }
236
keunyoung1ab8e182015-09-24 09:25:22 -0700237 public static void assertVehicleHalMockPermission(Context context) {
238 if (context.checkCallingOrSelfPermission(CarSystemTest.PERMISSION_MOCK_VEHICLE_HAL)
239 != PackageManager.PERMISSION_GRANTED) {
240 throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission");
241 }
242 }
243
Steve Paik66481982015-10-27 15:22:38 -0700244 public static void assertHvacPermission(Context context) {
245 if (context.checkCallingOrSelfPermission(CarSystem.PERMISSION_CAR_HVAC)
246 != PackageManager.PERMISSION_GRANTED) {
247 throw new SecurityException(
248 "requires " + CarSystem.PERMISSION_CAR_HVAC);
249 }
250 }
251
keunyoung6b197692015-11-16 13:54:38 -0800252 private static void assertRadioPermission(Context context) {
253 if (context.checkCallingOrSelfPermission(CarSystem.PERMISSION_CAR_RADIO)
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700254 != PackageManager.PERMISSION_GRANTED) {
255 throw new SecurityException(
Keun-young Parkaaeffaf2015-11-25 17:24:10 -0800256 "requires permission " + CarSystem.PERMISSION_CAR_RADIO);
Sanket Agarwal3cf096a2015-10-13 14:46:31 -0700257 }
258 }
259
keunyoungcc449f72015-08-12 10:46:27 -0700260 void dump(PrintWriter writer) {
keunyounga3b28d82015-08-25 13:05:15 -0700261 writer.println("*Dump all services*");
262 for (CarServiceBase service: mAllServices) {
263 service.dump(writer);
264 }
keunyoung1ab8e182015-09-24 09:25:22 -0700265 CarTestService testService = mCarTestService;
266 if (testService != null) {
267 testService.dump(writer);
268 }
keunyoungcc449f72015-08-12 10:46:27 -0700269 }
keunyoungca515072015-07-10 12:21:47 -0700270}