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