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