• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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