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