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