Home | History | Annotate | Download | only in test
      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.test;
     17 
     18 import android.car.test.CarTestManager;
     19 import android.car.test.CarTestManagerBinderWrapper;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.ServiceConnection;
     23 import android.content.pm.PackageManager.NameNotFoundException;
     24 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
     25 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyAccess;
     26 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyChangeMode;
     27 import android.os.Binder;
     28 import android.os.Handler;
     29 import android.os.IBinder;
     30 import android.os.Looper;
     31 import android.test.AndroidTestCase;
     32 import android.util.Log;
     33 
     34 import com.android.car.CarPowerManagementService;
     35 import com.android.car.ICarImpl;
     36 import com.android.car.SystemInterface;
     37 import com.android.car.vehiclehal.test.MockedVehicleHal;
     38 import com.android.car.vehiclehal.test.MockedVehicleHal.DefaultPropertyHandler;
     39 import com.android.car.vehiclehal.test.MockedVehicleHal.StaticPropertyHandler;
     40 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
     41 import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
     42 
     43 import java.util.Arrays;
     44 import java.util.HashMap;
     45 import java.util.Map;
     46 import java.util.concurrent.Semaphore;
     47 import java.util.concurrent.TimeUnit;
     48 
     49 /**
     50  * Base class for testing with mocked vehicle HAL (=car).
     51  * It is up to each app to start emulation by getMockedVehicleHal().start() as there will be
     52  * per test set up that should be done before starting.
     53  */
     54 public class MockedCarTestBase extends AndroidTestCase {
     55     private static final String TAG = MockedCarTestBase.class.getSimpleName();
     56     static final long DEFAULT_WAIT_TIMEOUT_MS = 3000;
     57     static final long SHORT_WAIT_TIMEOUT_MS = 500;
     58 
     59     private android.car.Car mCar;
     60     private ICarImpl mCarImpl;
     61     private MockedVehicleHal mMockedVehicleHal;
     62     private FakeSystemInterface mFakeSystemInterface;
     63 
     64     private final Semaphore mWaitForMain = new Semaphore(0);
     65     private final Handler mMainHandler = new Handler(Looper.getMainLooper());
     66 
     67     private static final IBinder mCarServiceToken = new Binder();
     68     private static boolean mRealCarServiceReleased = false;
     69 
     70     protected synchronized MockedVehicleHal createMockedVehicleHal() {
     71         return new MockedVehicleHal();
     72     }
     73 
     74     protected synchronized MockedVehicleHal getMockedVehicleHal() {
     75         return mMockedVehicleHal;
     76     }
     77 
     78     protected synchronized void configureMockedHal() {
     79     }
     80 
     81     @Override
     82     protected synchronized void setUp() throws Exception {
     83         super.setUp();
     84 
     85         releaseRealCarService(getContext());
     86 
     87         mMockedVehicleHal = createMockedVehicleHal();
     88         configureMockedHal();
     89 
     90         mFakeSystemInterface = new FakeSystemInterface();
     91         Context context = getCarServiceContext();
     92         mCarImpl = new ICarImpl(context, mMockedVehicleHal, mFakeSystemInterface,
     93                 null /* error notifier */);
     94 
     95         initMockedHal(false /* no need to release */);
     96 
     97         mCar = new android.car.Car(context, mCarImpl, null /* handler */);
     98     }
     99 
    100     @Override
    101     protected synchronized void tearDown() throws Exception {
    102         super.tearDown();
    103 
    104         mCar.disconnect();
    105         mCarImpl.release();
    106     }
    107 
    108     protected Context getCarServiceContext() throws NameNotFoundException {
    109         return getContext()
    110                 .createPackageContext("com.android.car", Context.CONTEXT_IGNORE_SECURITY);
    111     }
    112 
    113     protected synchronized void reinitializeMockedHal() {
    114         initMockedHal(true /* release */);
    115     }
    116 
    117     private synchronized void initMockedHal(boolean release) {
    118         if (release) {
    119             mCarImpl.release();
    120         }
    121 
    122         for (Map.Entry<VehiclePropConfigBuilder, VehicleHalPropertyHandler> entry
    123                 : mHalConfig.entrySet()) {
    124             mMockedVehicleHal.addProperty(entry.getKey().build(), entry.getValue());
    125         }
    126         mHalConfig.clear();
    127         mCarImpl.init();
    128     }
    129 
    130     private final Map<VehiclePropConfigBuilder, VehicleHalPropertyHandler> mHalConfig =
    131             new HashMap<>();
    132 
    133     protected synchronized VehiclePropConfigBuilder addProperty(int propertyId,
    134             VehicleHalPropertyHandler propertyHandler) {
    135         VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
    136         mHalConfig.put(builder, propertyHandler);
    137         return builder;
    138     }
    139 
    140     protected synchronized VehiclePropConfigBuilder addProperty(int propertyId) {
    141         VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
    142         mHalConfig.put(builder, new DefaultPropertyHandler(builder.build(), null));
    143         return builder;
    144     }
    145 
    146     protected synchronized VehiclePropConfigBuilder addProperty(int propertyId,
    147             VehiclePropValue value) {
    148         VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId);
    149         mHalConfig.put(builder, new DefaultPropertyHandler(builder.build(), value));
    150         return builder;
    151     }
    152 
    153     protected synchronized VehiclePropConfigBuilder addStaticProperty(int propertyId,
    154             VehiclePropValue value) {
    155         VehiclePropConfigBuilder builder = VehiclePropConfigBuilder.newBuilder(propertyId)
    156                 .setChangeMode(VehiclePropertyChangeMode.STATIC)
    157                 .setAccess(VehiclePropertyAccess.READ);
    158 
    159         mHalConfig.put(builder, new StaticPropertyHandler(value));
    160         return builder;
    161     }
    162 
    163     protected synchronized android.car.Car getCar() {
    164         return mCar;
    165     }
    166 
    167     protected void runOnMain(final Runnable r) {
    168         mMainHandler.post(r);
    169     }
    170 
    171     protected void runOnMainSync(final Runnable r) throws Exception {
    172         mMainHandler.post(new Runnable() {
    173             @Override
    174             public void run() {
    175                 r.run();
    176                 mWaitForMain.release();
    177             }
    178         });
    179         mWaitForMain.acquire();
    180     }
    181 
    182     protected boolean waitForFakeDisplayState(boolean expectedState) throws Exception {
    183         return mFakeSystemInterface.waitForDisplayState(expectedState, SHORT_WAIT_TIMEOUT_MS);
    184     }
    185 
    186     public static <T> void assertArrayEquals(T[] expected, T[] actual) {
    187         if (!Arrays.equals(expected, actual)) {
    188             fail("expected:<" + Arrays.toString(expected) +
    189                     "> but was:<" + Arrays.toString(actual) + ">");
    190         }
    191     }
    192 
    193     public static void assertArrayEquals(int[] expected, int[] actual) {
    194         if (!Arrays.equals(expected, actual)) {
    195             fail("expected:<" + Arrays.toString(expected) +
    196                     "> but was:<" + Arrays.toString(actual) + ">");
    197         }
    198     }
    199 
    200     /*
    201      * In order to eliminate interfering with real car service we will disable it. It will be
    202      * enabled back in CarTestService when mCarServiceToken will go away (tests finish).
    203      */
    204     private synchronized static void releaseRealCarService(Context context) throws Exception {
    205         if (mRealCarServiceReleased) {
    206             return;  // We just want to release it once.
    207         }
    208 
    209         mRealCarServiceReleased = true;  // To make sure it was called once.
    210 
    211         Object waitForConnection = new Object();
    212         android.car.Car car = android.car.Car.createCar(context, new ServiceConnection() {
    213             @Override
    214             public void onServiceConnected(ComponentName name, IBinder service) {
    215                 synchronized (waitForConnection) {
    216                     waitForConnection.notify();
    217                 }
    218             }
    219 
    220             @Override
    221             public void onServiceDisconnected(ComponentName name) { }
    222         });
    223 
    224         car.connect();
    225         synchronized (waitForConnection) {
    226             if (!car.isConnected()) {
    227                 waitForConnection.wait(DEFAULT_WAIT_TIMEOUT_MS);
    228             }
    229         }
    230 
    231         if (car.isConnected()) {
    232             Log.i(TAG, "Connected to real car service");
    233             CarTestManagerBinderWrapper binderWrapper =
    234                     (CarTestManagerBinderWrapper) car.getCarManager(android.car.Car.TEST_SERVICE);
    235             assertNotNull(binderWrapper);
    236 
    237             CarTestManager mgr = new CarTestManager(binderWrapper.binder);
    238             mgr.stopCarService(mCarServiceToken);
    239         }
    240     }
    241 
    242     private static class FakeSystemInterface extends SystemInterface {
    243 
    244         private boolean mDisplayOn = true;
    245         private final Semaphore mDisplayStateWait = new Semaphore(0);
    246 
    247         @Override
    248         public synchronized void setDisplayState(boolean on) {
    249             mDisplayOn = on;
    250             mDisplayStateWait.release();
    251         }
    252 
    253         boolean waitForDisplayState(boolean expectedState, long timeoutMs)
    254                 throws Exception {
    255             if (expectedState == mDisplayOn) {
    256                 return true;
    257             }
    258             mDisplayStateWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
    259             return expectedState == mDisplayOn;
    260         }
    261 
    262         @Override
    263         public void releaseAllWakeLocks() {
    264         }
    265 
    266         @Override
    267         public void shutdown() { }
    268 
    269         @Override
    270         public void enterDeepSleep(int wakeupTimeSec) { }
    271 
    272         @Override
    273         public boolean isSystemSupportingDeepSleep() {
    274             return false;
    275         }
    276 
    277         @Override
    278         public void switchToPartialWakeLock() {
    279         }
    280 
    281         @Override
    282         public void switchToFullWakeLock() {
    283         }
    284 
    285         @Override
    286         public void startDisplayStateMonitoring(CarPowerManagementService service) {
    287         }
    288 
    289         @Override
    290         public void stopDisplayStateMonitoring() {
    291         }
    292 
    293         @Override
    294         public boolean isWakeupCausedByTimer() { return false; }
    295     }
    296 }
    297