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 package com.android.car; 17 18 import static android.content.pm.PackageManager.PERMISSION_DENIED; 19 20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; 21 22 import static com.google.common.truth.Truth.assertWithMessage; 23 24 import static org.junit.Assert.fail; 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.Mockito.doAnswer; 27 import static org.mockito.Mockito.mock; 28 29 import android.automotive.powerpolicy.internal.ICarPowerPolicyDelegate; 30 import android.car.Car; 31 import android.car.feature.Flags; 32 import android.car.test.CarTestManager; 33 import android.car.testapi.FakeRefactoredCarPowerPolicyDaemon; 34 import android.car.user.CarUserManager.UserLifecycleListener; 35 import android.content.ComponentName; 36 import android.content.Context; 37 import android.content.ContextWrapper; 38 import android.content.Intent; 39 import android.content.ServiceConnection; 40 import android.content.res.Resources; 41 import android.frameworks.automotive.powerpolicy.internal.ICarPowerPolicySystemNotification; 42 import android.hardware.automotive.vehicle.VehiclePropertyAccess; 43 import android.hardware.automotive.vehicle.VehiclePropertyChangeMode; 44 import android.os.Binder; 45 import android.os.Handler; 46 import android.os.IBinder; 47 import android.os.IInterface; 48 import android.os.Process; 49 import android.os.UserHandle; 50 import android.util.ArrayMap; 51 import android.util.ArraySet; 52 import android.util.Log; 53 import android.util.SparseArray; 54 55 import androidx.test.annotation.UiThreadTest; 56 import androidx.test.platform.app.InstrumentationRegistry; 57 58 import com.android.car.ICarImpl.Builder.CarRemoteAccessServiceConstructor; 59 import com.android.car.garagemode.GarageModeService; 60 import com.android.car.hal.test.AidlMockedVehicleHal; 61 import com.android.car.hal.test.AidlVehiclePropConfigBuilder; 62 import com.android.car.hal.test.HidlMockedVehicleHal; 63 import com.android.car.hal.test.HidlVehiclePropConfigBuilder; 64 import com.android.car.internal.ICarServiceHelper; 65 import com.android.car.internal.StaticBinderInterface; 66 import com.android.car.os.CarPerformanceService; 67 import com.android.car.power.CarPowerManagementService; 68 import com.android.car.systeminterface.ActivityManagerInterface; 69 import com.android.car.systeminterface.DisplayInterface; 70 import com.android.car.systeminterface.IOInterface; 71 import com.android.car.systeminterface.StorageMonitoringInterface; 72 import com.android.car.systeminterface.SystemInterface; 73 import com.android.car.systeminterface.SystemStateInterface; 74 import com.android.car.systeminterface.TimeInterface; 75 import com.android.car.systeminterface.WakeLockInterface; 76 import com.android.car.telemetry.CarTelemetryService; 77 import com.android.car.test.utils.TemporaryDirectory; 78 import com.android.car.user.CarUserService; 79 import com.android.car.watchdog.CarWatchdogService; 80 import com.android.internal.annotations.GuardedBy; 81 82 import org.junit.After; 83 import org.junit.Before; 84 import org.mockito.MockitoSession; 85 import org.mockito.quality.Strictness; 86 87 import java.io.File; 88 import java.io.IOException; 89 import java.time.Duration; 90 import java.util.ArrayList; 91 import java.util.HashMap; 92 import java.util.List; 93 import java.util.Map; 94 import java.util.Set; 95 96 /** 97 * Base class for testing with mocked vehicle HAL (=car). 98 * It is up to each app to start emulation by getHidlMockedVehicleHal().start() as there will be 99 * per test set up that should be done before starting. 100 */ 101 public class MockedCarTestBase { 102 protected static final long DEFAULT_WAIT_TIMEOUT_MS = 3000; 103 protected static final long SHORT_WAIT_TIMEOUT_MS = 500; 104 private static final int STATE_HANDLING_TIMEOUT = 5_000; 105 private static final int MAIN_LOOPER_TIMEOUT_MS = 1_000; 106 private static final String TAG = MockedCarTestBase.class.getSimpleName(); 107 private static final IBinder sCarServiceToken = new Binder(); 108 private static boolean sRealCarServiceReleased; 109 110 // Use the Mocked AIDL VHAL backend by default. 111 private boolean mUseAidlVhal = true; 112 113 private Car mCar; 114 private ICarImpl mCarImpl; 115 private HidlMockedVehicleHal mHidlMockedVehicleHal; 116 private AidlMockedVehicleHal mAidlMockedVehicleHal; 117 private SystemInterface mFakeSystemInterface; 118 private MockedCarTestContext mMockedCarTestContext; 119 private CarTelemetryService mCarTelemetryService; 120 private CarWatchdogService mCarWatchdogService = mock(CarWatchdogService.class); 121 private CarPerformanceService mCarPerformanceService; 122 private CarRemoteAccessServiceConstructor mCarRemoteAccessServiceConstructor; 123 private AppFocusService mAppFocusService; 124 125 private final CarUserService mCarUserService = mock(CarUserService.class); 126 private final MockIOInterface mMockIOInterface = new MockIOInterface(); 127 private final GarageModeService mGarageModeService = mock(GarageModeService.class); 128 // TODO(286303350): Replace mPowerPolicyDaemon with mRefactoredPowerPolicyDaemon 129 // once refactor complete 130 private final ICarPowerPolicySystemNotification.Stub mPowerPolicyDaemon = 131 mock(ICarPowerPolicySystemNotification.Stub.class); 132 private final ICarServiceHelper mICarServiceHelper = mock(ICarServiceHelper.class); 133 134 private final Object mLock = new Object(); 135 @GuardedBy("mLock") 136 private final SparseArray<HidlVehiclePropConfigBuilder> mHidlPropToConfigBuilder = 137 new SparseArray<>(); 138 @GuardedBy("mLock") 139 private final SparseArray<AidlVehiclePropConfigBuilder> mAidlPropToConfigBuilder = 140 new SparseArray<>(); 141 @GuardedBy("mLock") 142 private final Map<HidlVehiclePropConfigBuilder, HidlMockedVehicleHal.VehicleHalPropertyHandler> 143 mHidlHalConfig = new ArrayMap<>(); 144 @GuardedBy("mLock") 145 private final Map<AidlVehiclePropConfigBuilder, AidlMockedVehicleHal.VehicleHalPropertyHandler> 146 mAidlHalConfig = new ArrayMap<>(); 147 @GuardedBy("mLock") 148 private final List<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>(); 149 150 private ICarPowerPolicyDelegate mRefactoredPowerPolicyDaemon; 151 private MockitoSession mSession; 152 createHidlMockedVehicleHal()153 protected HidlMockedVehicleHal createHidlMockedVehicleHal() { 154 return new HidlMockedVehicleHal(); 155 } 156 createAidlMockedVehicleHal()157 protected AidlMockedVehicleHal createAidlMockedVehicleHal() { 158 return new AidlMockedVehicleHal(); 159 } 160 getHidlMockedVehicleHal()161 protected HidlMockedVehicleHal getHidlMockedVehicleHal() { 162 return mHidlMockedVehicleHal; 163 } 164 getAidlMockedVehicleHal()165 protected AidlMockedVehicleHal getAidlMockedVehicleHal() { 166 return mAidlMockedVehicleHal; 167 } 168 getFakeSystemInterface()169 protected SystemInterface getFakeSystemInterface() { 170 return mFakeSystemInterface; 171 } 172 getMockedPowerPolicyDaemon()173 protected android.os.IInterface getMockedPowerPolicyDaemon() { 174 if (Flags.carPowerPolicyRefactoring()) { 175 return mRefactoredPowerPolicyDaemon; 176 } else { 177 return mPowerPolicyDaemon; 178 } 179 } 180 configureMockedHal()181 protected void configureMockedHal() { 182 } 183 createCarTelemetryService()184 protected CarTelemetryService createCarTelemetryService() { 185 return mock(CarTelemetryService.class); 186 } 187 188 /** 189 * Use the Mocked HIDL Vehicle HAL as backend. If called, must be called in 190 * configureMockedHal(). 191 */ useHidlVhal()192 protected void useHidlVhal() { 193 mUseAidlVhal = false; 194 } 195 196 /** 197 * Use the Mocked AIDL Vehicle HAL as backend. If called, must be called in 198 * configureMockedHal(). 199 */ useAidlVhal()200 protected void useAidlVhal() { 201 mUseAidlVhal = true; 202 } 203 204 /** 205 * Set the CarWatchDogService to be used during the test. 206 */ setCarWatchDogService(CarWatchdogService service)207 protected void setCarWatchDogService(CarWatchdogService service) { 208 mCarWatchdogService = service; 209 } 210 211 /** 212 * Set the CarPerformanceService to be used during the test. 213 * 214 * Must be called during {@link configureMockedHal}. If not called, the real service would be 215 * used. 216 */ setCarPerformanceService(CarPerformanceService service)217 protected void setCarPerformanceService(CarPerformanceService service) { 218 mCarPerformanceService = service; 219 } 220 221 /** 222 * Set the consturctor to create a fake CarRemoteAccessService for the test. 223 * 224 * If not called, the real service would be used. 225 */ setCarRemoteAccessServiceConstructor( CarRemoteAccessServiceConstructor constructor)226 protected void setCarRemoteAccessServiceConstructor( 227 CarRemoteAccessServiceConstructor constructor) { 228 mCarRemoteAccessServiceConstructor = constructor; 229 } 230 231 /** 232 * Set the AppFocusService to be used during the test. 233 * 234 * If not called, the real service would be used. 235 */ setAppFocusService(AppFocusService service)236 protected void setAppFocusService(AppFocusService service) { 237 mAppFocusService = service; 238 } 239 240 /** 241 * Called after {@code ICarImpl} is created and before {@code ICarImpl.init()} is called. 242 * 243 * <p> Subclass that intend to apply spyOn() to the service under testing should override this. 244 * <pre class="prettyprint"> 245 * {@literal @}Override 246 * protected void spyOnBeforeCarImplInit() { 247 * mServiceUnderTest = CarLocalServices.getService(CarXXXService.class); 248 * ExtendedMockito.spyOn(mServiceUnderTest); 249 * } 250 * </pre> 251 */ spyOnBeforeCarImplInit(ICarImpl carImpl)252 protected void spyOnBeforeCarImplInit(ICarImpl carImpl) { 253 } 254 getSystemInterfaceBuilder()255 protected SystemInterface.Builder getSystemInterfaceBuilder() { 256 return SystemInterface.Builder.newSystemInterface() 257 .withSystemStateInterface(createMockSystemStateInterface()) 258 .withActivityManagerInterface(new MockActivityManagerInterface()) 259 .withDisplayInterface(new MockDisplayInterface()) 260 .withIOInterface(mMockIOInterface) 261 .withStorageMonitoringInterface(new MockStorageMonitoringInterface()) 262 .withTimeInterface(new MockTimeInterface()) 263 .withWakeLockInterface(new MockWakeLockInterface()); 264 } 265 createMockSystemStateInterface()266 protected SystemStateInterface createMockSystemStateInterface() { 267 return new MockSystemStateInterface(); 268 } 269 configureFakeSystemInterface()270 protected void configureFakeSystemInterface() {} 271 configureResourceOverrides(MockResources resources)272 protected void configureResourceOverrides(MockResources resources) { 273 resources.overrideResource(com.android.car.R.string.instrumentClusterRendererService, ""); 274 resources.overrideResource(com.android.car.R.bool.audioUseDynamicRouting, false); 275 resources.overrideResource(com.android.car.R.array.config_earlyStartupServices, 276 new String[0]); 277 resources.overrideResource(com.android.car.R.integer.maxGarageModeRunningDurationInSecs, 278 900); 279 } 280 getContext()281 protected Context getContext() { 282 synchronized (mLock) { 283 if (mMockedCarTestContext == null) { 284 mMockedCarTestContext = createMockedCarTestContext( 285 InstrumentationRegistry.getInstrumentation().getTargetContext()); 286 } 287 return mMockedCarTestContext; 288 } 289 } 290 createMockedCarTestContext(Context context)291 protected MockedCarTestContext createMockedCarTestContext(Context context) { 292 return new MockedCarTestContext(context); 293 } 294 getTestContext()295 protected Context getTestContext() { 296 return InstrumentationRegistry.getInstrumentation().getContext(); 297 } 298 getFlattenComponent(Class cls)299 protected String getFlattenComponent(Class cls) { 300 ComponentName cn = new ComponentName(getTestContext(), cls); 301 return cn.flattenToString(); 302 } 303 304 /** Child class should override this to configure mocking in different way */ createMockingSession()305 protected MockitoSession createMockingSession() { 306 return mockitoSession() 307 .initMocks(this) 308 .strictness(Strictness.LENIENT) 309 .startMocking(); 310 } 311 312 @Before 313 @UiThreadTest setUp()314 public void setUp() throws Exception { 315 Log.i(TAG, "setUp"); 316 317 mSession = createMockingSession(); 318 319 releaseRealCarService(getContext()); 320 321 // Create mock dependencies 322 mHidlMockedVehicleHal = createHidlMockedVehicleHal(); 323 mAidlMockedVehicleHal = createAidlMockedVehicleHal(); 324 configureMockedHal(); 325 326 mFakeSystemInterface = getSystemInterfaceBuilder().build(); 327 configureFakeSystemInterface(); 328 329 mMockedCarTestContext = (MockedCarTestContext) getContext(); 330 configureResourceOverrides((MockResources) mMockedCarTestContext.getResources()); 331 332 mCarTelemetryService = createCarTelemetryService(); 333 334 // Setup mocks 335 doAnswer((invocation) -> { 336 UserLifecycleListener listener = invocation.getArgument(/* index= */ 1); 337 synchronized (mLock) { 338 Log.d(TAG, "Adding UserLifecycleListener: " + listener); 339 mUserLifecycleListeners.add(listener); 340 } 341 return null; 342 }).when(mCarUserService).addUserLifecycleListener(any(), any()); 343 344 doAnswer((invocation) -> { 345 UserLifecycleListener listener = invocation.getArgument(/* index= */ 0); 346 synchronized (mLock) { 347 Log.d(TAG, "Removing UserLifecycleListener: " + listener); 348 mUserLifecycleListeners.remove(listener); 349 } 350 return null; 351 }).when(mCarUserService).removeUserLifecycleListener(any()); 352 353 // ICarImpl will register new CarLocalServices services. 354 // This prevents one test failure in tearDown from triggering assertion failure for single 355 // CarLocalServices service. 356 CarLocalServices.removeAllServices(); 357 358 // This should be done here as feature property is accessed inside the constructor. 359 initMockedHal(); 360 361 VehicleStub mockedVehicleStub; 362 if (!mUseAidlVhal) { 363 mockedVehicleStub = new HidlVehicleStub(mHidlMockedVehicleHal); 364 } else { 365 mockedVehicleStub = new AidlVehicleStub(mAidlMockedVehicleHal); 366 } 367 368 // Setup car 369 IInterface powerPolicyDaemon; 370 if (Flags.carPowerPolicyRefactoring()) { 371 mRefactoredPowerPolicyDaemon = new FakeRefactoredCarPowerPolicyDaemon( 372 /* fileKernelSilentMode= */ null, /* customComponents= */ null); 373 powerPolicyDaemon = mRefactoredPowerPolicyDaemon; 374 } else { 375 powerPolicyDaemon = mPowerPolicyDaemon; 376 } 377 ICarImpl carImpl = new ICarImpl.Builder() 378 .setServiceContext(mMockedCarTestContext) 379 .setVehicle(mockedVehicleStub) 380 .setVehicleInterfaceName("MockedCar") 381 .setSystemInterface(mFakeSystemInterface) 382 .setCarUserService(mCarUserService) 383 .setCarWatchdogService(mCarWatchdogService) 384 .setCarPerformanceService(mCarPerformanceService) 385 .setCarTelemetryService(mCarTelemetryService) 386 .setCarRemoteAccessServiceConstructor(mCarRemoteAccessServiceConstructor) 387 .setAppFocusService(mAppFocusService) 388 .setGarageModeService(mGarageModeService) 389 .setPowerPolicyDaemon(powerPolicyDaemon) 390 .setDoPriorityInitInConstruction(false) 391 .setTestStaticBinder(new StaticBinderInterface() { 392 @Override 393 public int getCallingUid() { 394 return Process.SYSTEM_UID; 395 } 396 397 @Override 398 public int getCallingPid() { 399 return 0; 400 } 401 }) 402 .build(); 403 404 carImpl.setSystemServerConnections(mICarServiceHelper, 405 new ICarImplTest.CarServiceConnectedCallback()); 406 spyOnBeforeCarImplInit(carImpl); 407 carImpl.init(); 408 mCarImpl = carImpl; 409 // Wait for CPMS to handle the first power state change request. 410 waitUntilPowerStateChangeHandled(); 411 mCar = new Car(mMockedCarTestContext, mCarImpl, /* handler= */ null); 412 } 413 414 @After tearDown()415 public void tearDown() throws Exception { 416 Log.i(TAG, "tearDown"); 417 418 // Wait for CPMS to finish event processing. 419 if (mCarImpl != null) { 420 waitUntilPowerStateChangeHandled(); 421 } 422 423 try { 424 if (mCar != null) { 425 mCar.disconnect(); 426 mCar = null; 427 } 428 if (mCarImpl != null) { 429 mCarImpl.release(); 430 mCarImpl = null; 431 } 432 CarServiceUtils.quitHandlerThreads(); 433 mMockIOInterface.tearDown(); 434 mHidlMockedVehicleHal = null; 435 mAidlMockedVehicleHal = null; 436 } finally { 437 // Wait for the main looper to handle the current queued tasks before finishing the 438 // mocking session since the task might use the mocked object. 439 assertWithMessage("main looper not idle in %sms", MAIN_LOOPER_TIMEOUT_MS) 440 .that(Handler.getMain().runWithScissors(() -> { 441 if (mSession != null) { 442 mSession.finishMocking(); 443 } 444 }, MAIN_LOOPER_TIMEOUT_MS)).isTrue(); 445 } 446 } 447 injectErrorEvent(int propId, int areaId, int errorCode)448 public void injectErrorEvent(int propId, int areaId, int errorCode) { 449 if (mUseAidlVhal) { 450 mAidlMockedVehicleHal.injectError(errorCode, propId, areaId); 451 } else { 452 mHidlMockedVehicleHal.injectError(errorCode, propId, areaId); 453 } 454 } 455 456 /** 457 * Creates new Car instance for testing. 458 */ createNewCar()459 public Car createNewCar() { 460 return new Car(mMockedCarTestContext, mCarImpl, /* handler= */ null); 461 } 462 getCarService(String service)463 protected IBinder getCarService(String service) { 464 return mCarImpl.getCarService(service); 465 } 466 initMockedHal()467 private void initMockedHal() throws Exception { 468 synchronized (mLock) { 469 for (Map.Entry<HidlVehiclePropConfigBuilder, 470 HidlMockedVehicleHal.VehicleHalPropertyHandler> entry : 471 mHidlHalConfig.entrySet()) { 472 mHidlMockedVehicleHal.addProperty(entry.getKey().build(), entry.getValue()); 473 } 474 for (Map.Entry<AidlVehiclePropConfigBuilder, 475 AidlMockedVehicleHal.VehicleHalPropertyHandler> 476 entry : mAidlHalConfig.entrySet()) { 477 mAidlMockedVehicleHal.addProperty(entry.getKey().build(), entry.getValue()); 478 } 479 mHidlHalConfig.clear(); 480 mAidlHalConfig.clear(); 481 } 482 } 483 addHidlProperty(int propertyId, HidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler)484 protected HidlVehiclePropConfigBuilder addHidlProperty(int propertyId, 485 HidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler) { 486 HidlVehiclePropConfigBuilder builder = HidlVehiclePropConfigBuilder.newBuilder(propertyId); 487 setHidlConfigBuilder(builder, propertyHandler); 488 return builder; 489 } 490 addHidlProperty(int propertyId)491 protected HidlVehiclePropConfigBuilder addHidlProperty(int propertyId) { 492 HidlVehiclePropConfigBuilder builder = HidlVehiclePropConfigBuilder.newBuilder(propertyId); 493 setHidlConfigBuilder(builder, new HidlMockedVehicleHal.DefaultPropertyHandler( 494 builder.build(), null)); 495 return builder; 496 } 497 addHidlProperty(int propertyId, android.hardware.automotive.vehicle.V2_0.VehiclePropValue value)498 protected HidlVehiclePropConfigBuilder addHidlProperty(int propertyId, 499 android.hardware.automotive.vehicle.V2_0.VehiclePropValue value) { 500 HidlVehiclePropConfigBuilder builder = HidlVehiclePropConfigBuilder.newBuilder(propertyId); 501 setHidlConfigBuilder(builder, new HidlMockedVehicleHal.DefaultPropertyHandler( 502 builder.build(), value)); 503 return builder; 504 } 505 addStaticHidlProperty(int propertyId, android.hardware.automotive.vehicle.V2_0.VehiclePropValue value)506 protected HidlVehiclePropConfigBuilder addStaticHidlProperty(int propertyId, 507 android.hardware.automotive.vehicle.V2_0.VehiclePropValue value) { 508 HidlVehiclePropConfigBuilder builder = HidlVehiclePropConfigBuilder.newBuilder(propertyId) 509 .setChangeMode(VehiclePropertyChangeMode.STATIC) 510 .setAccess(VehiclePropertyAccess.READ); 511 512 setHidlConfigBuilder(builder, new HidlMockedVehicleHal.StaticPropertyHandler(value)); 513 return builder; 514 } 515 addAidlProperty(int propertyId, AidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler)516 protected AidlVehiclePropConfigBuilder addAidlProperty(int propertyId, 517 AidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler) { 518 AidlVehiclePropConfigBuilder builder = AidlVehiclePropConfigBuilder.newBuilder(propertyId); 519 setAidlConfigBuilder(builder, propertyHandler); 520 return builder; 521 } 522 addAidlProperty(int propertyId)523 protected AidlVehiclePropConfigBuilder addAidlProperty(int propertyId) { 524 AidlVehiclePropConfigBuilder builder = AidlVehiclePropConfigBuilder.newBuilder(propertyId); 525 setAidlConfigBuilder(builder, new AidlMockedVehicleHal.DefaultPropertyHandler( 526 builder.build(), null)); 527 return builder; 528 } 529 addAidlProperty(int propertyId, android.hardware.automotive.vehicle.VehiclePropValue value)530 protected AidlVehiclePropConfigBuilder addAidlProperty(int propertyId, 531 android.hardware.automotive.vehicle.VehiclePropValue value) { 532 AidlVehiclePropConfigBuilder builder = AidlVehiclePropConfigBuilder.newBuilder(propertyId); 533 setAidlConfigBuilder(builder, new AidlMockedVehicleHal.DefaultPropertyHandler( 534 builder.build(), value)); 535 return builder; 536 } 537 addAidlStaticProperty(int propertyId, android.hardware.automotive.vehicle.VehiclePropValue value)538 protected AidlVehiclePropConfigBuilder addAidlStaticProperty(int propertyId, 539 android.hardware.automotive.vehicle.VehiclePropValue value) { 540 AidlVehiclePropConfigBuilder builder = AidlVehiclePropConfigBuilder.newBuilder(propertyId) 541 .setChangeMode(VehiclePropertyChangeMode.STATIC) 542 .setAccess(VehiclePropertyAccess.READ); 543 544 setAidlConfigBuilder(builder, new AidlMockedVehicleHal.StaticPropertyHandler( 545 value)); 546 return builder; 547 } 548 waitUntilPowerStateChangeHandled()549 private void waitUntilPowerStateChangeHandled() { 550 CarPowerManagementService cpms = 551 (CarPowerManagementService) getCarService(Car.POWER_SERVICE); 552 cpms.getHandler().runWithScissors(() -> {}, STATE_HANDLING_TIMEOUT); 553 } 554 555 @SuppressWarnings("CollectionIncompatibleType") // HidlVehiclePropConfigBuilder does not 556 // implement equals setHidlConfigBuilder(HidlVehiclePropConfigBuilder builder, HidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler)557 private void setHidlConfigBuilder(HidlVehiclePropConfigBuilder builder, 558 HidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler) { 559 int propId = builder.build().prop; 560 561 synchronized (mLock) { 562 // Override previous property config if exists. 563 HidlVehiclePropConfigBuilder prevBuilder = mHidlPropToConfigBuilder.get(propId); 564 if (prevBuilder != null) { 565 mHidlHalConfig.remove(prevBuilder); 566 } 567 mHidlPropToConfigBuilder.put(propId, builder); 568 mHidlHalConfig.put(builder, propertyHandler); 569 } 570 } 571 572 @SuppressWarnings("CollectionIncompatibleType") // AidlVehiclePropConfigBuilder does not 573 // implement equals setAidlConfigBuilder(AidlVehiclePropConfigBuilder builder, AidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler)574 private void setAidlConfigBuilder(AidlVehiclePropConfigBuilder builder, 575 AidlMockedVehicleHal.VehicleHalPropertyHandler propertyHandler) { 576 int propId = builder.build().prop; 577 578 synchronized (mLock) { 579 // Override previous property config if exists. 580 AidlVehiclePropConfigBuilder prevBuilder = mAidlPropToConfigBuilder.get(propId); 581 if (prevBuilder != null) { 582 mAidlHalConfig.remove(prevBuilder); 583 } 584 mAidlPropToConfigBuilder.put(propId, builder); 585 mAidlHalConfig.put(builder, propertyHandler); 586 } 587 } 588 getCar()589 protected android.car.Car getCar() { 590 return mCar; 591 } 592 593 /* 594 * In order to eliminate interfering with real car service we will disable it. It will be 595 * enabled back in CarTestService when sCarServiceToken will go away (tests finish). 596 */ releaseRealCarService(Context context)597 private static void releaseRealCarService(Context context) throws Exception { 598 if (sRealCarServiceReleased) { 599 return; // We just want to release it once. 600 } 601 sRealCarServiceReleased = true; // To make sure it was called once. 602 603 Object waitForConnection = new Object(); 604 Car car = android.car.Car.createCar(context, new ServiceConnection() { 605 @Override 606 public void onServiceConnected(ComponentName name, IBinder service) { 607 synchronized (waitForConnection) { 608 waitForConnection.notifyAll(); 609 } 610 } 611 612 @Override 613 public void onServiceDisconnected(ComponentName name) { } 614 }); 615 616 car.connect(); 617 synchronized (waitForConnection) { 618 if (!car.isConnected()) { 619 long nowMs = System.currentTimeMillis(); 620 long deadlineMs = nowMs + DEFAULT_WAIT_TIMEOUT_MS; 621 while (!car.isConnected() && nowMs < deadlineMs) { 622 waitForConnection.wait(deadlineMs - nowMs); 623 nowMs = System.currentTimeMillis(); 624 } 625 } 626 } 627 628 if (car.isConnected()) { 629 Log.i(TAG, "Connected to real car service"); 630 CarTestManager carTestManager = (CarTestManager) car.getCarManager(Car.TEST_SERVICE); 631 carTestManager.stopCarService(sCarServiceToken); 632 } 633 } 634 635 static final class MockActivityManagerInterface implements ActivityManagerInterface { 636 @Override sendBroadcastAsUser(Intent intent, UserHandle user)637 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 638 Log.d(TAG, "Broadcast intent: " + intent.getAction() + " as user: " + user); 639 } 640 } 641 642 static final class MockDisplayInterface implements DisplayInterface { 643 644 @Override init(CarPowerManagementService carPowerManagementService, CarUserService carUserService)645 public void init(CarPowerManagementService carPowerManagementService, 646 CarUserService carUserService) {} 647 648 @Override setDisplayBrightness(int brightness)649 public void setDisplayBrightness(int brightness) {} 650 651 @Override setDisplayBrightness(int displayId, int brightness)652 public void setDisplayBrightness(int displayId, int brightness) {} 653 654 @Override setDisplayState(int displayId, boolean on)655 public void setDisplayState(int displayId, boolean on) {} 656 657 @Override setAllDisplayState(boolean on)658 public void setAllDisplayState(boolean on) {} 659 660 @Override startDisplayStateMonitoring()661 public void startDisplayStateMonitoring() {} 662 663 @Override stopDisplayStateMonitoring()664 public void stopDisplayStateMonitoring() {} 665 666 @Override refreshDisplayBrightness()667 public void refreshDisplayBrightness() {} 668 669 @Override refreshDisplayBrightness(int displayid)670 public void refreshDisplayBrightness(int displayid) {} 671 672 @Override isAnyDisplayEnabled()673 public boolean isAnyDisplayEnabled() { 674 return true; 675 } 676 677 @Override isDisplayEnabled(int displayId)678 public boolean isDisplayEnabled(int displayId) { 679 return true; 680 } 681 } 682 683 static final class MockIOInterface implements IOInterface { 684 private TemporaryDirectory mFilesDir = null; 685 686 @Override getSystemCarDir()687 public File getSystemCarDir() { 688 if (mFilesDir == null) { 689 try { 690 mFilesDir = new TemporaryDirectory(TAG); 691 } catch (IOException e) { 692 Log.e(TAG, "failed to create temporary directory", e); 693 fail("failed to create temporary directory. exception was: " + e); 694 } 695 } 696 return mFilesDir.getDirectory(); 697 } 698 tearDown()699 public void tearDown() { 700 if (mFilesDir != null) { 701 try { 702 mFilesDir.close(); 703 } catch (Exception e) { 704 Log.w(TAG, "could not remove temporary directory", e); 705 } 706 } 707 } 708 } 709 710 /** 711 * Special version of {@link ContextWrapper} that overrides {@code getResources} by returning 712 * a {@link MockResources}, so tests are free to set resources. This class represents an 713 * alternative of using Mockito spy (see b/148240178). 714 * 715 * This class also overwrites {@code checkCallingOrSelfPermission} to allow setting caller's 716 * permissions. By default, caller is typically within the same process so permission will 717 * always be granted. Caller can use {@code setDeniedPermissions} to set permissions 718 * that should not be granted. 719 * 720 * Tests may specialize this class. If they decide so, then they are required to override 721 * {@link createMockedCarTestContext} to provide their own context. 722 */ 723 protected static class MockedCarTestContext extends ContextWrapper { 724 725 private final Resources mMockedResources; 726 private final Set<String> mDeniedPermissions = new ArraySet<>(); 727 MockedCarTestContext(Context base)728 protected MockedCarTestContext(Context base) { 729 super(base); 730 mMockedResources = new MockResources(base.getResources()); 731 } 732 733 /** 734 * Sets the permissions that should be denied. 735 */ setDeniedPermissions(String[] permissions)736 public void setDeniedPermissions(String[] permissions) { 737 for (String permission : permissions) { 738 mDeniedPermissions.add(permission); 739 } 740 } 741 742 @Override getResources()743 public Resources getResources() { 744 return mMockedResources; 745 } 746 747 @Override checkCallingOrSelfPermission(String permission)748 public int checkCallingOrSelfPermission(String permission) { 749 if (mDeniedPermissions.contains(permission)) { 750 return PERMISSION_DENIED; 751 } 752 return super.checkCallingOrSelfPermission(permission); 753 } 754 } 755 756 protected static final class MockResources extends Resources { 757 private final HashMap<Integer, Boolean> mBooleanOverrides = new HashMap<>(); 758 private final HashMap<Integer, Integer> mIntegerOverrides = new HashMap<>(); 759 private final HashMap<Integer, String> mStringOverrides = new HashMap<>(); 760 private final HashMap<Integer, String[]> mStringArrayOverrides = new HashMap<>(); 761 MockResources(Resources resources)762 MockResources(Resources resources) { 763 super(resources.getAssets(), 764 resources.getDisplayMetrics(), 765 resources.getConfiguration()); 766 } 767 768 @Override getBoolean(int id)769 public boolean getBoolean(int id) { 770 return mBooleanOverrides.getOrDefault(id, 771 super.getBoolean(id)); 772 } 773 774 @Override getInteger(int id)775 public int getInteger(int id) { 776 return mIntegerOverrides.getOrDefault(id, 777 super.getInteger(id)); 778 } 779 780 @Override getString(int id)781 public String getString(int id) { 782 return mStringOverrides.getOrDefault(id, 783 super.getString(id)); 784 } 785 786 @Override getStringArray(int id)787 public String[] getStringArray(int id) { 788 return mStringArrayOverrides.getOrDefault(id, 789 super.getStringArray(id)); 790 } 791 overrideResource(int id, boolean value)792 public MockResources overrideResource(int id, boolean value) { 793 mBooleanOverrides.put(id, value); 794 return this; 795 } 796 overrideResource(int id, int value)797 public MockResources overrideResource(int id, int value) { 798 mIntegerOverrides.put(id, value); 799 return this; 800 } 801 overrideResource(int id, String value)802 public MockResources overrideResource(int id, String value) { 803 mStringOverrides.put(id, value); 804 return this; 805 } 806 overrideResource(int id, String[] value)807 public MockResources overrideResource(int id, String[] value) { 808 mStringArrayOverrides.put(id, value); 809 return this; 810 } 811 } 812 813 static final class MockStorageMonitoringInterface implements StorageMonitoringInterface {} 814 815 static final class MockSystemStateInterface implements SystemStateInterface { 816 @Override shutdown()817 public void shutdown() {} 818 819 @Override enterDeepSleep()820 public boolean enterDeepSleep() { 821 return true; 822 } 823 824 @Override enterHibernation()825 public boolean enterHibernation() { 826 return true; 827 } 828 829 @Override scheduleActionForBootCompleted(Runnable action, Duration delay, Duration delayRange)830 public void scheduleActionForBootCompleted(Runnable action, Duration delay, 831 Duration delayRange) {} 832 } 833 834 static final class MockTimeInterface implements TimeInterface { 835 836 @Override scheduleAction(Runnable r, long delayMs)837 public void scheduleAction(Runnable r, long delayMs) {} 838 839 @Override cancelAllActions()840 public void cancelAllActions() {} 841 } 842 843 static final class MockWakeLockInterface implements WakeLockInterface { 844 845 @Override releaseAllWakeLocks(int displayId)846 public void releaseAllWakeLocks(int displayId) {} 847 848 @Override switchToPartialWakeLock(int displayId)849 public void switchToPartialWakeLock(int displayId) {} 850 851 @Override switchToFullWakeLock(int displayId)852 public void switchToFullWakeLock(int displayId) {} 853 } 854 } 855