Home | History | Annotate | Download | only in test
      1 /*
      2  * Copyright (C) 2016 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 com.android.car.test;
     18 
     19 import android.test.AndroidTestCase;
     20 import android.util.Log;
     21 
     22 import com.android.car.CarPowerManagementService;
     23 import com.android.car.CarPowerManagementService.PowerEventProcessingHandler;
     24 import com.android.car.CarPowerManagementService.PowerServiceEventListener;
     25 import com.android.car.hal.PowerHalService;
     26 import com.android.car.hal.PowerHalService.PowerState;
     27 
     28 import java.util.concurrent.Semaphore;
     29 import java.util.concurrent.TimeUnit;
     30 
     31 public class CarPowerManagementServiceTest extends AndroidTestCase {
     32     private static final String TAG = CarPowerManagementServiceTest.class.getSimpleName();
     33     private static final long WAIT_TIMEOUT_MS = 2000;
     34     private static final long WAIT_TIMEOUT_LONG_MS = 5000;
     35     private MockedPowerHalService mPowerHal;
     36     private SystemIntefaceImpl mSystemInterface;
     37     private CarPowerManagementService mService;
     38     private final PowerEventListener mPowerEventListener = new PowerEventListener();
     39     private PowerEventProcessingHandlerImpl mPowerEventProcessingHandler;
     40 
     41     @Override
     42     protected void setUp() throws Exception {
     43         super.setUp();
     44         mPowerHal = new MockedPowerHalService(true /*isPowerStateSupported*/,
     45                 true /*isDeepSleepAllowed*/, true /*isTimedWakeupAllowed*/);
     46         mSystemInterface = new SystemIntefaceImpl();
     47     }
     48 
     49     @Override
     50     protected void tearDown() throws Exception {
     51         super.tearDown();
     52         if (mService != null) {
     53             mService.release();
     54         }
     55     }
     56 
     57     public void testBootComplete() throws Exception {
     58         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
     59         mService.init();
     60         mService.registerPowerEventListener(mPowerEventListener);
     61         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, 0);
     62         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
     63         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
     64         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
     65     }
     66 
     67     public void testDisplayOff() throws Exception {
     68         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
     69         mService.init();
     70         mService.registerPowerEventListener(mPowerEventListener);
     71         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, 0);
     72         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
     73         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
     74         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
     75         // it will call display on for initial state
     76         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
     77         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0));
     78         assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
     79     }
     80 
     81     public void testDisplayOn() throws Exception {
     82         // start with display off
     83         mSystemInterface.setDisplayState(false);
     84         mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
     85         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
     86         mService.init();
     87         mService.registerPowerEventListener(mPowerEventListener);
     88         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, 0);
     89         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
     90         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
     91         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
     92 
     93         // display should be turned on as it started with off state.
     94         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
     95     }
     96 
     97     public void testShutdown() throws Exception {
     98         final int wakeupTime = 100;
     99         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
    100         mService.init();
    101         mService.registerPowerEventListener(mPowerEventListener);
    102         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, wakeupTime);
    103         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
    104         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
    105         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
    106         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    107 
    108         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
    109                 PowerHalService.FLAG_SHUTDOWN_IMMEDIATELY));
    110         assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
    111         assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    112         mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
    113         mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
    114     }
    115 
    116     public void testShutdownWithProcessing() throws Exception {
    117         final long processingTimeMs = 3000;
    118         final int wakeupTime = 100;
    119         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
    120         mService.init();
    121         mService.registerPowerEventListener(mPowerEventListener);
    122         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
    123                 wakeupTime);
    124         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
    125         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
    126         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
    127         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    128 
    129         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE, 0));
    130         mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
    131         assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_SHUTDOWN_START,
    132                 WAIT_TIMEOUT_LONG_MS, wakeupTime);
    133         assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    134         mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
    135         mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
    136     }
    137 
    138     public void testSleepEntryAndWakeup() throws Exception {
    139         final int wakeupTime = 100;
    140         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
    141         mService.init();
    142         mService.registerPowerEventListener(mPowerEventListener);
    143         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(0, wakeupTime);
    144         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
    145         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
    146         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
    147         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    148 
    149         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
    150                 PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
    151         assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    152         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_ENTRY, 0);
    153         mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
    154         int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
    155         assertEquals(wakeupTime, wakeupTimeReceived);
    156         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
    157         mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
    158 
    159     }
    160 
    161     public void testSleepEntryAndPowerOnWithProcessing() throws Exception {
    162         final long processingTimeMs = 3000;
    163         final int wakeupTime = 100;
    164         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
    165         mService.init();
    166         mService.registerPowerEventListener(mPowerEventListener);
    167         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
    168                 wakeupTime);
    169         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
    170         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
    171         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
    172         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    173 
    174         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
    175                 PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
    176         mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
    177         assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    178         assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
    179                 WAIT_TIMEOUT_LONG_MS, 0);
    180         mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
    181         // set power on here without notification. PowerManager should check the state after sleep
    182         // exit
    183         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0), false);
    184         int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
    185         assertEquals(wakeupTime, wakeupTimeReceived);
    186         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
    187         mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
    188         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
    189     }
    190 
    191     public void testSleepEntryAndWakeUpForProcessing() throws Exception {
    192         final long processingTimeMs = 3000;
    193         final int wakeupTime = 100;
    194         mService = new CarPowerManagementService(getContext(), mPowerHal, mSystemInterface);
    195         mService.init();
    196         mService.registerPowerEventListener(mPowerEventListener);
    197         mPowerEventProcessingHandler = new PowerEventProcessingHandlerImpl(processingTimeMs,
    198                 wakeupTime);
    199         mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
    200         assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
    201         mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
    202         assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    203 
    204         mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
    205                 PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
    206         mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
    207         assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
    208         assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
    209                 WAIT_TIMEOUT_LONG_MS, 0);
    210         mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
    211         mSystemInterface.setWakeupCausedByTimer(true);
    212         int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
    213         assertEquals(wakeupTime, wakeupTimeReceived);
    214         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
    215         mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
    216         // second processing after wakeup
    217         assertFalse(mSystemInterface.getDisplayState());
    218         mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
    219         assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
    220                 WAIT_TIMEOUT_LONG_MS, 0);
    221         mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
    222         // PM will shutdown system as it was not woken-up due to timer and it is not power on.
    223         mSystemInterface.setWakeupCausedByTimer(false);
    224         wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
    225         assertEquals(wakeupTime, wakeupTimeReceived);
    226         assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
    227         assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
    228         mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
    229         mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
    230         assertFalse(mSystemInterface.getDisplayState());
    231     }
    232 
    233     private void assertStateReceived(int expectedState, int expectedParam) throws Exception {
    234         int[] state = mPowerHal.waitForSend(WAIT_TIMEOUT_MS);
    235         assertEquals(expectedState, state[0]);
    236         assertEquals(expectedParam, state[1]);
    237     }
    238 
    239     private void assertStateReceivedForShutdownOrSleepWithPostpone(int lastState, long timeoutMs,
    240             int expectedParamForShutdown) throws Exception {
    241         while (true) {
    242             int[] state = mPowerHal.waitForSend(timeoutMs);
    243             if (state[0] == PowerHalService.SET_SHUTDOWN_POSTPONE) {
    244                 continue;
    245             }
    246             if (state[0] == lastState) {
    247                 assertEquals(expectedParamForShutdown, state[1]);
    248                 return;
    249             }
    250         }
    251     }
    252 
    253     private static void waitForSemaphore(Semaphore semaphore, long timeoutMs)
    254             throws InterruptedException {
    255         if (!semaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) {
    256             throw new IllegalStateException("timeout");
    257         }
    258     }
    259 
    260     private class SystemIntefaceImpl implements CarPowerManagementService.SystemInteface {
    261 
    262         private boolean mDisplayOn = true;
    263         private final Semaphore mDisplayStateWait = new Semaphore(0);
    264         private final Semaphore mShutdownWait = new Semaphore(0);
    265         private final Semaphore mSleepWait = new Semaphore(0);
    266         private final Semaphore mSleepExitWait = new Semaphore(0);
    267         private int mWakeupTime;
    268         private boolean mWakeupCausedByTimer = false;
    269 
    270         @Override
    271         public synchronized void setDisplayState(boolean on) {
    272             Log.i(TAG, "SystemIntefaceImpl.setDisplayState " + on);
    273             mDisplayOn = on;
    274             mDisplayStateWait.release();
    275         }
    276 
    277         public synchronized boolean getDisplayState() {
    278             return mDisplayOn;
    279         }
    280 
    281         public boolean waitForDisplayStateChange(long timeoutMs) throws Exception {
    282             waitForSemaphore(mDisplayStateWait, timeoutMs);
    283             return mDisplayOn;
    284         }
    285 
    286         @Override
    287         public void releaseAllWakeLocks() {
    288         }
    289 
    290         @Override
    291         public void shutdown() {
    292             mShutdownWait.release();
    293         }
    294 
    295         public void waitForShutdown(long timeoutMs) throws Exception {
    296             waitForSemaphore(mShutdownWait, timeoutMs);
    297         }
    298 
    299         @Override
    300         public void enterDeepSleep(int wakeupTimeSec) {
    301             mWakeupTime = wakeupTimeSec;
    302             mSleepWait.release();
    303             try {
    304                 mSleepExitWait.acquire();
    305             } catch (InterruptedException e) {
    306             }
    307         }
    308 
    309         @Override
    310         public boolean isSystemSupportingDeepSleep() {
    311             return true;
    312         }
    313 
    314         public int waitForSleepEntryAndWakeup(long timeoutMs) throws Exception {
    315             waitForSemaphore(mSleepWait, timeoutMs);
    316             mSleepExitWait.release();
    317             return mWakeupTime;
    318         }
    319 
    320         @Override
    321         public void switchToPartialWakeLock() {
    322         }
    323 
    324         @Override
    325         public void switchToFullWakeLock() {
    326         }
    327 
    328         @Override
    329         public void startDisplayStateMonitoring(CarPowerManagementService service) {
    330         }
    331 
    332         @Override
    333         public void stopDisplayStateMonitoring() {
    334         }
    335 
    336         @Override
    337         public synchronized boolean isWakeupCausedByTimer() {
    338             Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
    339             return mWakeupCausedByTimer;
    340         }
    341 
    342         public synchronized void setWakeupCausedByTimer(boolean set) {
    343             mWakeupCausedByTimer = set;
    344         }
    345     }
    346 
    347     private class PowerEventListener implements PowerServiceEventListener {
    348         private final Semaphore mShutdownWait = new Semaphore(0);
    349         private final Semaphore mSleepEntryWait = new Semaphore(0);
    350         private final Semaphore mSleepExitWait = new Semaphore(0);
    351 
    352         @Override
    353         public void onShutdown() {
    354             mShutdownWait.release();
    355         }
    356 
    357         public void waitForShutdown(long timeoutMs) throws Exception {
    358             waitForSemaphore(mShutdownWait, timeoutMs);
    359         }
    360 
    361         @Override
    362         public void onSleepEntry() {
    363             mSleepEntryWait.release();
    364         }
    365 
    366         public void waitForSleepEntry(long timeoutMs) throws Exception {
    367             waitForSemaphore(mSleepEntryWait, timeoutMs);
    368         }
    369 
    370         @Override
    371         public void onSleepExit() {
    372             mSleepExitWait.release();
    373         }
    374 
    375         public void waitForSleepExit(long timeoutMs) throws Exception {
    376             waitForSemaphore(mSleepExitWait, timeoutMs);
    377         }
    378     }
    379 
    380     private class PowerEventProcessingHandlerImpl implements PowerEventProcessingHandler {
    381         private final long mProcessingTime;
    382         private final int mWakeupTime;
    383         private final Semaphore mPrepareShutdownWait = new Semaphore(0);
    384         private final Semaphore mOnPowerOnWait = new Semaphore(0);
    385         private boolean mShuttingDown;
    386         private boolean mDisplayOn;
    387 
    388         private PowerEventProcessingHandlerImpl(long processingTime, int wakeupTime) {
    389             mProcessingTime = processingTime;
    390             mWakeupTime = wakeupTime;
    391         }
    392 
    393         @Override
    394         public long onPrepareShutdown(boolean shuttingDown) {
    395             mShuttingDown = shuttingDown;
    396             mPrepareShutdownWait.release();
    397             return mProcessingTime;
    398         }
    399         public boolean waitForPrepareShutdown(long timeoutMs) throws Exception {
    400             waitForSemaphore(mPrepareShutdownWait, timeoutMs);
    401             return mShuttingDown;
    402         }
    403 
    404         @Override
    405         public void onPowerOn(boolean displayOn) {
    406             mDisplayOn = displayOn;
    407             mOnPowerOnWait.release();
    408         }
    409 
    410         public boolean waitForPowerOn(long timeoutMs) throws Exception {
    411             waitForSemaphore(mOnPowerOnWait, timeoutMs);
    412             return mDisplayOn;
    413         }
    414 
    415         @Override
    416         public int getWakeupTime() {
    417             return mWakeupTime;
    418         }
    419     }
    420 }
    421