blob: 17d7cac737818219a88dbd88939a897487f6a59a [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerBootupReason;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerSetState;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerState;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateConfigFlag;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateIndex;
import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.SystemClock;
import android.support.test.annotation.UiThreadTest;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
import com.google.android.collect.Lists;
import com.android.car.systeminterface.DisplayInterface;
import com.android.car.systeminterface.SystemInterface;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class CarPowerManagementTest extends MockedCarTestBase {
private final PowerStatePropertyHandler mPowerStateHandler = new PowerStatePropertyHandler();
private final MockDisplayInterface mMockDisplayInterface = new MockDisplayInterface();
@Override
protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
return builder.withDisplayInterface(mMockDisplayInterface);
}
private void setupPowerPropertyAndStart(boolean allowSleep) throws Exception {
addProperty(VehicleProperty.AP_POWER_STATE, mPowerStateHandler)
.setConfigArray(Lists.newArrayList(
allowSleep ? VehicleApPowerStateConfigFlag.ENABLE_DEEP_SLEEP_FLAG : 0));
addStaticProperty(VehicleProperty.AP_POWER_BOOTUP_REASON,
VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_BOOTUP_REASON)
.addIntValue(VehicleApPowerBootupReason.USER_POWER_ON)
.build());
reinitializeMockedHal();
}
@Test
@UiThreadTest
public void testImmediateShutdown() throws Exception {
setupPowerPropertyAndStart(true);
assertBootComplete();
mPowerStateHandler.sendPowerState(
VehicleApPowerState.SHUTDOWN_PREPARE,
VehicleApPowerStateShutdownParam.SHUTDOWN_IMMEDIATELY);
mPowerStateHandler.waitForStateSetAndGetAll(DEFAULT_WAIT_TIMEOUT_MS,
VehicleApPowerSetState.SHUTDOWN_START);
mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_FULL, 0);
}
@Test
@UiThreadTest
public void testDisplayOnOff() throws Exception {
setupPowerPropertyAndStart(true);
assertBootComplete();
for (int i = 0; i < 2; i++) {
mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_DISP_OFF, 0);
mMockDisplayInterface.waitForDisplayState(false);
mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_FULL, 0);
mMockDisplayInterface.waitForDisplayState(true);
}
}
/* TODO make deep sleep work to test this
@Test public void testSleepEntry() throws Exception {
assertBootComplete();
mPowerStateHandler.sendPowerState(
VehicleApPowerState.SHUTDOWN_PREPARE,
VehicleApPowerStateShutdownParam.CAN_SLEEP);
assertResponse(VehicleApPowerSetState.DEEP_SLEEP_ENTRY, 0);
assertResponse(VehicleApPowerSetState.DEEP_SLEEP_EXIT, 0);
mPowerStateHandler.sendPowerState(
VehicleApPowerState.ON_FULL,
0);
}*/
private void assertResponse(int expectedResponseState, int expectedResponseParam)
throws Exception {
LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll(
DEFAULT_WAIT_TIMEOUT_MS, expectedResponseState);
int[] last = setEvents.getLast();
assertEquals(expectedResponseState, last[0]);
assertEquals(expectedResponseParam, last[1]);
}
private void assertBootComplete() throws Exception {
mPowerStateHandler.waitForSubscription(DEFAULT_WAIT_TIMEOUT_MS);
LinkedList<int[]> setEvents = mPowerStateHandler.waitForStateSetAndGetAll(
DEFAULT_WAIT_TIMEOUT_MS, VehicleApPowerSetState.BOOT_COMPLETE);
int[] first = setEvents.getFirst();
assertEquals(VehicleApPowerSetState.BOOT_COMPLETE, first[0]);
assertEquals(0, first[1]);
}
private final class MockDisplayInterface implements DisplayInterface {
private boolean mDisplayOn = true;
private final Semaphore mDisplayStateWait = new Semaphore(0);
@Override
public synchronized void setDisplayState(boolean on) {
mDisplayOn = on;
mDisplayStateWait.release();
}
boolean waitForDisplayState(boolean expectedState)
throws Exception {
if (expectedState == mDisplayOn) {
return true;
}
mDisplayStateWait.tryAcquire(MockedCarTestBase.SHORT_WAIT_TIMEOUT_MS,
TimeUnit.MILLISECONDS);
return expectedState == mDisplayOn;
}
@Override
public void startDisplayStateMonitoring(CarPowerManagementService service) {}
@Override
public void stopDisplayStateMonitoring() {}
}
private class PowerStatePropertyHandler implements VehicleHalPropertyHandler {
private int mPowerState = VehicleApPowerState.ON_FULL;
private int mPowerParam = 0;
private final Semaphore mSubscriptionWaitSemaphore = new Semaphore(0);
private final Semaphore mSetWaitSemaphore = new Semaphore(0);
private LinkedList<int[]> mSetStates = new LinkedList<>();
@Override
public void onPropertySet(VehiclePropValue value) {
ArrayList<Integer> v = value.value.int32Values;
synchronized (this) {
mSetStates.add(new int[] {
v.get(VehicleApPowerStateIndex.STATE),
v.get(VehicleApPowerStateIndex.ADDITIONAL)
});
}
mSetWaitSemaphore.release();
}
@Override
public synchronized VehiclePropValue onPropertyGet(VehiclePropValue value) {
return VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addIntValue(mPowerState, mPowerParam)
.build();
}
@Override
public void onPropertySubscribe(int property, float sampleRate) {
mSubscriptionWaitSemaphore.release();
}
@Override
public void onPropertyUnsubscribe(int property) {
//ignore
}
private synchronized void setCurrentState(int state, int param) {
mPowerState = state;
mPowerParam = param;
}
private void waitForSubscription(long timeoutMs) throws Exception {
if (!mSubscriptionWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
fail("waitForSubscription timeout");
}
}
private LinkedList<int[]> waitForStateSetAndGetAll(long timeoutMs, int expectedSet)
throws Exception {
while (true) {
if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
fail("waitForStateSetAndGetAll timeout");
}
synchronized (this) {
boolean found = false;
for (int[] state : mSetStates) {
if (state[0] == expectedSet) {
found = true;
}
}
if (found) {
LinkedList<int[]> res = mSetStates;
mSetStates = new LinkedList<>();
return res;
}
}
}
}
private void sendPowerState(int state, int param) {
getMockedVehicleHal().injectEvent(
VehiclePropValueBuilder.newBuilder(VehicleProperty.AP_POWER_STATE)
.setTimestamp(SystemClock.elapsedRealtimeNanos())
.addIntValue(state, param)
.build());
}
}
}