1 /* 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 17 package com.android.car; 18 19 import android.car.Car; 20 import android.car.ICar; 21 import android.content.Context; 22 import android.content.pm.PackageManager; 23 import android.os.IBinder; 24 import android.util.Log; 25 26 import com.android.car.cluster.CarNavigationService; 27 import com.android.car.cluster.InstrumentClusterService; 28 import com.android.car.hal.VehicleHal; 29 import com.android.car.pm.CarPackageManagerService; 30 import com.android.internal.annotations.GuardedBy; 31 32 import java.io.PrintWriter; 33 34 public class ICarImpl extends ICar.Stub { 35 36 public static final String INTERNAL_INPUT_SERVICE = "internal_input"; 37 38 // load jni for all services here 39 static { 40 System.loadLibrary("jni_car_service"); 41 } 42 43 @GuardedBy("ICarImpl.class") 44 private static ICarImpl sInstance = null; 45 46 private final Context mContext; 47 private final VehicleHal mHal; 48 49 private final CarPowerManagementService mCarPowerManagementService; 50 private final CarPackageManagerService mCarPackageManagerService; 51 private final CarInputService mCarInputService; 52 private final CarSensorService mCarSensorService; 53 private final CarInfoService mCarInfoService; 54 private final CarAudioService mCarAudioService; 55 private final CarProjectionService mCarProjectionService; 56 private final CarCameraService mCarCameraService; 57 private final CarHvacService mCarHvacService; 58 private final CarRadioService mCarRadioService; 59 private final CarNightService mCarNightService; 60 private final AppContextService mAppContextService; 61 private final GarageModeService mGarageModeService; 62 private final CarNavigationService mCarNavigationService; 63 private final InstrumentClusterService mInstrumentClusterService; 64 65 /** Test only service. Populate it only when necessary. */ 66 @GuardedBy("this") 67 private CarTestService mCarTestService; 68 private final CarServiceBase[] mAllServices; 69 getInstance(Context serviceContext)70 public synchronized static ICarImpl getInstance(Context serviceContext) { 71 if (sInstance == null) { 72 sInstance = new ICarImpl(serviceContext); 73 sInstance.init(); 74 } 75 return sInstance; 76 } 77 releaseInstance()78 public synchronized static void releaseInstance() { 79 if (sInstance == null) { 80 return; 81 } 82 sInstance.release(); 83 sInstance = null; 84 } 85 ICarImpl(Context serviceContext)86 public ICarImpl(Context serviceContext) { 87 mContext = serviceContext; 88 mHal = VehicleHal.getInstance(); 89 mCarPowerManagementService = new CarPowerManagementService(serviceContext); 90 mCarInputService = new CarInputService(serviceContext); 91 mCarProjectionService = new CarProjectionService(serviceContext, mCarInputService); 92 mGarageModeService = new GarageModeService(mContext, mCarPowerManagementService); 93 mCarInfoService = new CarInfoService(serviceContext); 94 mAppContextService = new AppContextService(serviceContext); 95 mCarSensorService = new CarSensorService(serviceContext); 96 mCarAudioService = new CarAudioService(serviceContext); 97 mCarHvacService = new CarHvacService(serviceContext); 98 mCarRadioService = new CarRadioService(serviceContext); 99 mCarCameraService = new CarCameraService(serviceContext); 100 mCarNightService = new CarNightService(serviceContext); 101 mCarPackageManagerService = new CarPackageManagerService(serviceContext); 102 mInstrumentClusterService = new InstrumentClusterService(serviceContext); 103 mCarNavigationService = new CarNavigationService( 104 serviceContext, mAppContextService, mInstrumentClusterService); 105 106 // Be careful with order. Service depending on other service should be inited later. 107 mAllServices = new CarServiceBase[] { 108 mCarPowerManagementService, 109 mCarPackageManagerService, 110 mCarInputService, 111 mGarageModeService, 112 mCarInfoService, 113 mAppContextService, 114 mCarSensorService, 115 mCarAudioService, 116 mCarHvacService, 117 mCarRadioService, 118 mCarCameraService, 119 mCarNightService, 120 mInstrumentClusterService, 121 mCarProjectionService, 122 mCarNavigationService, 123 }; 124 } 125 init()126 private void init() { 127 for (CarServiceBase service: mAllServices) { 128 service.init(); 129 } 130 } 131 release()132 private void release() { 133 // release done in opposite order from init 134 for (int i = mAllServices.length - 1; i >= 0; i--) { 135 mAllServices[i].release(); 136 } 137 VehicleHal.releaseInstance(); 138 } 139 140 /** Only for CarTestService */ startMocking()141 void startMocking() { 142 reinitServices(); 143 } 144 145 /** Only for CarTestService */ stopMocking()146 void stopMocking() { 147 reinitServices(); 148 } 149 150 /** Reset all services when starting / stopping vehicle hal mocking */ reinitServices()151 private void reinitServices() { 152 for (int i = mAllServices.length - 1; i >= 0; i--) { 153 mAllServices[i].release(); 154 } 155 for (CarServiceBase service: mAllServices) { 156 service.init(); 157 } 158 } 159 160 @Override getCarService(String serviceName)161 public IBinder getCarService(String serviceName) { 162 switch (serviceName) { 163 case Car.AUDIO_SERVICE: 164 return mCarAudioService; 165 case Car.SENSOR_SERVICE: 166 return mCarSensorService; 167 case Car.INFO_SERVICE: 168 return mCarInfoService; 169 case Car.APP_CONTEXT_SERVICE: 170 return mAppContextService; 171 case Car.PACKAGE_SERVICE: 172 return mCarPackageManagerService; 173 case Car.CAMERA_SERVICE: 174 assertCameraPermission(mContext); 175 return mCarCameraService; 176 case Car.HVAC_SERVICE: 177 assertHvacPermission(mContext); 178 return mCarHvacService; 179 case Car.RADIO_SERVICE: 180 assertRadioPermission(mContext); 181 return mCarRadioService; 182 case Car.CAR_NAVIGATION_SERVICE: 183 assertNavigationManagerPermission(mContext); 184 return mCarNavigationService; 185 case Car.PROJECTION_SERVICE: 186 assertProjectionPermission(mContext); 187 return mCarProjectionService; 188 case Car.TEST_SERVICE: { 189 assertVehicleHalMockPermission(mContext); 190 synchronized (this) { 191 if (mCarTestService == null) { 192 mCarTestService = new CarTestService(mContext, this); 193 } 194 return mCarTestService; 195 } 196 } 197 default: 198 Log.w(CarLog.TAG_SERVICE, "getCarService for unknown service:" + serviceName); 199 return null; 200 } 201 } 202 203 @Override getCarConnectionType()204 public int getCarConnectionType() { 205 if (!isInMocking()) { 206 return Car.CONNECTION_TYPE_EMBEDDED; 207 } else { 208 return Car.CONNECTION_TYPE_EMBEDDED_MOCKING; 209 } 210 } 211 getCarInternalService(String serviceName)212 public CarServiceBase getCarInternalService(String serviceName) { 213 switch (serviceName) { 214 case INTERNAL_INPUT_SERVICE: 215 return mCarInputService; 216 default: 217 Log.w(CarLog.TAG_SERVICE, "getCarInternalService for unknown service:" + 218 serviceName); 219 return null; 220 } 221 } 222 223 /** 224 * Whether mocking underlying HAL or not. 225 * @return 226 */ isInMocking()227 public synchronized boolean isInMocking() { 228 if (mCarTestService == null) { 229 return false; 230 } 231 return mCarTestService.isInMocking(); 232 } 233 assertVehicleHalMockPermission(Context context)234 public static void assertVehicleHalMockPermission(Context context) { 235 if (context.checkCallingOrSelfPermission(Car.PERMISSION_MOCK_VEHICLE_HAL) 236 != PackageManager.PERMISSION_GRANTED) { 237 throw new SecurityException("requires CAR_MOCK_VEHICLE_HAL permission"); 238 } 239 } 240 assertCameraPermission(Context context)241 public static void assertCameraPermission(Context context) { 242 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_CAMERA) 243 != PackageManager.PERMISSION_GRANTED) { 244 throw new SecurityException( 245 "requires " + Car.PERMISSION_CAR_CAMERA); 246 } 247 } 248 assertNavigationManagerPermission(Context context)249 public static void assertNavigationManagerPermission(Context context) { 250 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_NAVIGATION_MANAGER) 251 != PackageManager.PERMISSION_GRANTED) { 252 throw new SecurityException( 253 "requires " + Car.PERMISSION_CAR_NAVIGATION_MANAGER); 254 } 255 } 256 assertHvacPermission(Context context)257 public static void assertHvacPermission(Context context) { 258 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_HVAC) 259 != PackageManager.PERMISSION_GRANTED) { 260 throw new SecurityException( 261 "requires " + Car.PERMISSION_CAR_HVAC); 262 } 263 } 264 assertRadioPermission(Context context)265 private static void assertRadioPermission(Context context) { 266 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_RADIO) 267 != PackageManager.PERMISSION_GRANTED) { 268 throw new SecurityException( 269 "requires permission " + Car.PERMISSION_CAR_RADIO); 270 } 271 } 272 assertProjectionPermission(Context context)273 public static void assertProjectionPermission(Context context) { 274 if (context.checkCallingOrSelfPermission(Car.PERMISSION_CAR_PROJECTION) 275 != PackageManager.PERMISSION_GRANTED) { 276 throw new SecurityException( 277 "requires " + Car.PERMISSION_CAR_PROJECTION); 278 } 279 } 280 dump(PrintWriter writer)281 void dump(PrintWriter writer) { 282 writer.println("*Dump all services*"); 283 for (CarServiceBase service: mAllServices) { 284 service.dump(writer); 285 } 286 CarTestService testService = mCarTestService; 287 if (testService != null) { 288 testService.dump(writer); 289 } 290 } 291 } 292