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; 17 18import static org.junit.Assert.assertEquals; 19import static org.junit.Assert.fail; 20 21import android.hardware.automotive.vehicle.V2_0.VehicleApPowerBootupReason; 22import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateConfigFlag; 23import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReport; 24import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq; 25import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReqIndex; 26import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam; 27import android.hardware.automotive.vehicle.V2_0.VehiclePropValue; 28import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 29import android.os.SystemClock; 30import android.support.test.annotation.UiThreadTest; 31import android.support.test.filters.MediumTest; 32import android.support.test.runner.AndroidJUnit4; 33 34import com.android.car.systeminterface.DisplayInterface; 35import com.android.car.systeminterface.SystemInterface; 36import com.android.car.vehiclehal.VehiclePropValueBuilder; 37import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler; 38 39import com.google.android.collect.Lists; 40 41import org.junit.Test; 42import org.junit.runner.RunWith; 43 44import java.util.ArrayList; 45import java.util.LinkedList; 46import java.util.concurrent.Semaphore; 47import java.util.concurrent.TimeUnit; 48 49@RunWith(AndroidJUnit4.class) 50@MediumTest 51public class CarPowerManagementTest extends MockedCarTestBase { 52 53 private final PowerStatePropertyHandler mPowerStateHandler = new PowerStatePropertyHandler(); 54 private final MockDisplayInterface mMockDisplayInterface = new MockDisplayInterface(); 55 56 @Override 57 protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() { 58 SystemInterface.Builder builder = super.getSystemInterfaceBuilder(); 59 return builder.withDisplayInterface(mMockDisplayInterface); 60 } 61 62 private void setupPowerPropertyAndStart(boolean allowSleep) throws Exception { 63 addProperty(VehicleProperty.AP_POWER_STATE_REQ, mPowerStateHandler) 64 .setConfigArray(Lists.newArrayList( 65 allowSleep ? VehicleApPowerStateConfigFlag.ENABLE_DEEP_SLEEP_FLAG : 0)); 66 addProperty(VehicleProperty.AP_POWER_STATE_REPORT, mPowerStateHandler); 67 68 addStaticProperty(VehicleProperty.AP_POWER_BOOTUP_REASON, 69 VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_BOOTUP_REASON) 70 .addIntValue(VehicleApPowerBootupReason.USER_POWER_ON) 71 .build()); 72 73 reinitializeMockedHal(); 74 } 75 76 @Test 77 @UiThreadTest 78 public void testImmediateShutdown() throws Exception { 79 setupPowerPropertyAndStart(true); 80 assertBootComplete(); 81 mPowerStateHandler.sendPowerState( 82 VehicleApPowerStateReq.SHUTDOWN_PREPARE, 83 VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY); 84 mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS, 85 VehicleApPowerStateReport.SHUTDOWN_START); 86 mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.ON_FULL, 0); 87 } 88 89 @Test 90 @UiThreadTest 91 public void testDisplayOnOff() throws Exception { 92 setupPowerPropertyAndStart(true); 93 assertBootComplete(); 94 for (int i = 0; i < 2; i++) { 95 mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.ON_DISP_OFF, 0); 96 mMockDisplayInterface.waitForDisplayState(false); 97 mPowerStateHandler.sendPowerState(VehicleApPowerStateReq.ON_FULL, 0); 98 mMockDisplayInterface.waitForDisplayState(true); 99 } 100 } 101 102 /* TODO make deep sleep work to test this 103 @Test public void testSleepEntry() throws Exception { 104 assertBootComplete(); 105 mPowerStateHandler.sendPowerState( 106 VehicleApPowerState.SHUTDOWN_PREPARE, 107 VehicleApPowerStateShutdownParam.CAN_SLEEP); 108 assertResponse(VehicleApPowerSetState.DEEP_SLEEP_ENTRY, 0); 109 assertResponse(VehicleApPowerSetState.DEEP_SLEEP_EXIT, 0); 110 mPowerStateHandler.sendPowerState( 111 VehicleApPowerState.ON_FULL, 112 0); 113 }*/ 114 115 private void assertResponse(int expectedResponseState, int expectedResponseParam) 116 throws Exception { 117 LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll( 118 DEFAULT_WAIT_TIMEOUT_MS, expectedResponseState); 119 int[] last = setEvents.getLast(); 120 assertEquals(expectedResponseState, last[0]); 121 assertEquals(expectedResponseParam, last[1]); 122 } 123 124 private void assertBootComplete() throws Exception { 125 mPowerStateHandler.waitForSubscription(DEFAULT_WAIT_TIMEOUT_MS); 126 LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll( 127 DEFAULT_WAIT_TIMEOUT_MS, VehicleApPowerStateReport.BOOT_COMPLETE); 128 int[] first = setEvents.getFirst(); 129 assertEquals(VehicleApPowerStateReport.BOOT_COMPLETE, first[0]); 130 assertEquals(0, first[1]); 131 } 132 133 private final class MockDisplayInterface implements DisplayInterface { 134 private boolean mDisplayOn = true; 135 private final Semaphore mDisplayStateWait = new Semaphore(0); 136 137 @Override 138 public void setDisplayBrightness(int brightness) {} 139 140 @Override 141 public synchronized void setDisplayState(boolean on) { 142 mDisplayOn = on; 143 mDisplayStateWait.release(); 144 } 145 146 boolean waitForDisplayState(boolean expectedState) 147 throws Exception { 148 if (expectedState == mDisplayOn) { 149 return true; 150 } 151 mDisplayStateWait.tryAcquire(MockedCarTestBase.SHORT_WAIT_TIMEOUT_MS, 152 TimeUnit.MILLISECONDS); 153 return expectedState == mDisplayOn; 154 } 155 156 @Override 157 public void startDisplayStateMonitoring(CarPowerManagementService service) {} 158 159 @Override 160 public void stopDisplayStateMonitoring() {} 161 } 162 163 private class PowerStatePropertyHandler implements VehicleHalPropertyHandler { 164 165 private int mPowerState = VehicleApPowerStateReq.ON_FULL; 166 private int mPowerParam = 0; 167 168 private final Semaphore mSubscriptionWaitSemaphore = new Semaphore(0); 169 private final Semaphore mSetWaitSemaphore = new Semaphore(0); 170 private LinkedList<int[]> mSetStates = new LinkedList<>(); 171 172 @Override 173 public void onPropertySet(VehiclePropValue value) { 174 ArrayList<Integer> v = value.value.int32Values; 175 synchronized (this) { 176 mSetStates.add(new int[] { 177 v.get(VehicleApPowerStateReqIndex.STATE), 178 v.get(VehicleApPowerStateReqIndex.ADDITIONAL) 179 }); 180 } 181 mSetWaitSemaphore.release(); 182 } 183 184 @Override 185 public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) { 186 return VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ) 187 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 188 .addIntValue(mPowerState, mPowerParam) 189 .build(); 190 } 191 192 @Override 193 public void onPropertySubscribe(int property, float sampleRate) { 194 mSubscriptionWaitSemaphore.release(); 195 } 196 197 @Override 198 public void onPropertyUnsubscribe(int property) { 199 //ignore 200 } 201 202 private synchronized void setCurrentState(int state, int param) { 203 mPowerState = state; 204 mPowerParam = param; 205 } 206 207 private void waitForSubscription(long timeoutMs) throws Exception { 208 if (!mSubscriptionWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 209 fail("waitForSubscription timeout"); 210 } 211 } 212 213 private LinkedList<int[]> waitForStateSetAndGetAll(long timeoutMs, int expectedSet) 214 throws Exception { 215 while (true) { 216 if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 217 fail("waitForStateSetAndGetAll timeout"); 218 } 219 synchronized (this) { 220 boolean found = false; 221 for (int[] state : mSetStates) { 222 if (state[0] == expectedSet) { 223 found = true; 224 } 225 } 226 if (found) { 227 LinkedList<int[]> res = mSetStates; 228 mSetStates = new LinkedList<>(); 229 return res; 230 } 231 } 232 } 233 } 234 235 private void sendPowerState(int state, int param) { 236 getMockedVehicleHal().injectEvent( 237 VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE_REQ) 238 .setTimestamp(SystemClock.elapsedRealtimeNanos()) 239 .addIntValue(state, param) 240 .build()); 241 } 242 } 243} 244