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