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