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 17 package android.car.apitest; 18 19 import static com.android.compatibility.common.util.ShellUtils.runShellCommand; 20 import static com.android.compatibility.common.util.TestUtils.BooleanSupplierWithThrow; 21 22 import static com.google.common.truth.Truth.assertThat; 23 24 import static org.junit.Assert.fail; 25 26 import android.car.Car; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.ServiceConnection; 30 import android.os.IBinder; 31 import android.os.Looper; 32 import android.os.PowerManager; 33 import android.os.SystemClock; 34 import android.util.Log; 35 36 import androidx.test.platform.app.InstrumentationRegistry; 37 38 import org.junit.After; 39 import org.junit.Before; 40 41 import java.util.concurrent.Semaphore; 42 import java.util.concurrent.TimeUnit; 43 44 abstract class CarApiTestBase { 45 46 private static final String TAG = CarApiTestBase.class.getSimpleName(); 47 48 protected static final long DEFAULT_WAIT_TIMEOUT_MS = 1_000; 49 50 /** 51 * Constant used to wait blindly, when there is no condition that can be checked. 52 */ 53 private static final int SUSPEND_TIMEOUT_MS = 5_000; 54 /** 55 * How long to sleep (multiple times) while waiting for a condition. 56 */ 57 private static final int SMALL_NAP_MS = 100; 58 59 protected static final Context sContext = InstrumentationRegistry.getInstrumentation() 60 .getTargetContext(); 61 62 private Car mCar; 63 64 protected final DefaultServiceConnectionListener mConnectionListener = 65 new DefaultServiceConnectionListener(); 66 67 @Before connectToCar()68 public final void connectToCar() throws Exception { 69 mCar = Car.createCar(getContext(), mConnectionListener); 70 mCar.connect(); 71 mConnectionListener.waitForConnection(DEFAULT_WAIT_TIMEOUT_MS); 72 } 73 74 @After disconnectFromCar()75 public final void disconnectFromCar() throws Exception { 76 mCar.disconnect(); 77 } 78 getCar()79 protected Car getCar() { 80 return mCar; 81 } 82 getContext()83 protected final Context getContext() { 84 return sContext; 85 } 86 assertMainThread()87 protected static void assertMainThread() { 88 assertThat(Looper.getMainLooper().isCurrentThread()).isTrue(); 89 } 90 91 protected static final class DefaultServiceConnectionListener implements ServiceConnection { 92 private final Semaphore mConnectionWait = new Semaphore(0); 93 waitForConnection(long timeoutMs)94 public void waitForConnection(long timeoutMs) throws InterruptedException { 95 mConnectionWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS); 96 } 97 98 @Override onServiceConnected(ComponentName name, IBinder service)99 public void onServiceConnected(ComponentName name, IBinder service) { 100 assertMainThread(); 101 mConnectionWait.release(); 102 } 103 104 @Override onServiceDisconnected(ComponentName name)105 public void onServiceDisconnected(ComponentName name) { 106 assertMainThread(); 107 } 108 } 109 suspendToRamAndResume()110 protected static void suspendToRamAndResume() throws Exception { 111 Log.d(TAG, "Emulate suspend to RAM and resume"); 112 PowerManager powerManager = sContext.getSystemService(PowerManager.class); 113 runShellCommand("cmd car_service suspend"); 114 // Check for suspend success 115 waitUntil("Suspsend is not successful", 116 SUSPEND_TIMEOUT_MS, () -> !powerManager.isScreenOn()); 117 118 // Force turn off garage mode 119 runShellCommand("cmd car_service garage-mode off"); 120 runShellCommand("cmd car_service resume"); 121 } 122 waitUntil(String msg, long timeoutMs, BooleanSupplierWithThrow condition)123 protected static boolean waitUntil(String msg, long timeoutMs, 124 BooleanSupplierWithThrow condition) { 125 long deadline = SystemClock.elapsedRealtime() + timeoutMs; 126 do { 127 try { 128 if (condition.getAsBoolean()) { 129 return true; 130 } 131 } catch (Exception e) { 132 Log.e(TAG, "Exception in waitUntil: " + msg); 133 throw new RuntimeException(e); 134 } 135 SystemClock.sleep(SMALL_NAP_MS); 136 } while (SystemClock.elapsedRealtime() < deadline); 137 138 fail(msg + " after: " + timeoutMs + "ms"); 139 return false; 140 } 141 } 142