Home | History | Annotate | Download | only in car
      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;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.fail;
     20 
     21 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerBootupReason;
     22 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateConfigFlag;
     23 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReport;
     24 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReq;
     25 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateReqIndex;
     26 import android.hardware.automotive.vehicle.V2_0.VehicleApPowerStateShutdownParam;
     27 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
     28 import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
     29 import android.os.SystemClock;
     30 import android.support.test.annotation.UiThreadTest;
     31 import android.support.test.filters.MediumTest;
     32 import android.support.test.runner.AndroidJUnit4;
     33 
     34 import com.android.car.systeminterface.DisplayInterface;
     35 import com.android.car.systeminterface.SystemInterface;
     36 import com.android.car.vehiclehal.VehiclePropValueBuilder;
     37 import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
     38 
     39 import com.google.android.collect.Lists;
     40 
     41 import org.junit.Test;
     42 import org.junit.runner.RunWith;
     43 
     44 import java.util.ArrayList;
     45 import java.util.LinkedList;
     46 import java.util.concurrent.Semaphore;
     47 import java.util.concurrent.TimeUnit;
     48 
     49 @RunWith(AndroidJUnit4.class)
     50 @MediumTest
     51 public 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