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