Home | History | Annotate | Download | only in targetprep
      1 /*
      2  * Copyright (C) 2013 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.tradefed.targetprep;
     18 
     19 import com.android.tradefed.build.IBuildInfo;
     20 import com.android.tradefed.config.Option;
     21 import com.android.tradefed.config.OptionClass;
     22 import com.android.tradefed.device.DeviceNotAvailableException;
     23 import com.android.tradefed.device.DeviceUnresponsiveException;
     24 import com.android.tradefed.device.ITestDevice;
     25 import com.android.tradefed.device.TestDeviceState;
     26 import com.android.tradefed.log.LogUtil.CLog;
     27 import com.android.tradefed.util.RunUtil;
     28 
     29 /** Performs reboot or format as cleanup action after test, and optionally turns screen off */
     30 @OptionClass(alias = "device-cleaner")
     31 public class DeviceCleaner extends BaseTargetPreparer implements ITargetCleaner {
     32 
     33     public static enum CleanupAction {
     34         /** no cleanup action */
     35         NONE,
     36         /** reboot the device as post test cleanup */
     37         REBOOT,
     38         /** format userdata and cache partitions as post test cleanup */
     39         FORMAT,
     40     }
     41 
     42     public static enum PostCleanupAction {
     43         /** no post cleanup action */
     44         NONE,
     45         /** turns screen off after the cleanup action */
     46         SCREEN_OFF,
     47         /** turns off screen and stops runtime after the cleanup action */
     48         SCREEN_OFF_AND_STOP,
     49     }
     50 
     51     private static final int MAX_SCREEN_OFF_RETRY = 5;
     52     private static final int SCREEN_OFF_RETRY_DELAY_MS = 2 * 1000;
     53 
     54     @Option(name = "cleanup-action",
     55             description = "Type of action to perform as a post test cleanup; options are: "
     56             + "NONE, REBOOT or FORMAT; defaults to NONE")
     57     private CleanupAction mCleanupAction = CleanupAction.NONE;
     58 
     59     /**
     60      * @deprecated use --post-cleanup SCREEN_OFF option instead.
     61      */
     62     @Deprecated
     63     @Option(name = "screen-off", description = "After cleanup action, "
     64             + "if screen should be turned off; defaults to false; "
     65             + "[deprecated] use --post-cleanup SCREEN_OFF instead")
     66     private boolean mScreenOff = false;
     67 
     68     @Option(name = "post-cleanup",
     69             description = "Type of action to perform after the cleanup action;"
     70             + "this will override the deprecated screen-off action if specified")
     71     private PostCleanupAction mPostCleanupAction = PostCleanupAction.NONE;
     72 
     73     @Override
     74     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
     75             BuildError, DeviceNotAvailableException {
     76         // no op since this is a target cleaner
     77     }
     78 
     79     @Override
     80     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
     81             throws DeviceNotAvailableException {
     82         if (e instanceof DeviceFailedToBootError) {
     83             CLog.w("boot failure: attempting to stop runtime instead of cleanup");
     84             try {
     85                 device.executeShellCommand("stop");
     86             } catch (DeviceUnresponsiveException due) {
     87                 CLog.w("boot failure: ignored DeviceUnresponsiveException during forced cleanup");
     88             }
     89         } else {
     90             clean(device);
     91         }
     92     }
     93 
     94     /**
     95      * Execute cleanup action followed by post cleanup action
     96      */
     97     protected void clean(ITestDevice device) throws DeviceNotAvailableException {
     98         if (TestDeviceState.ONLINE.equals(device.getDeviceState())) {
     99             switch (mCleanupAction) {
    100                 case NONE:
    101                     // do nothing here
    102                     break;
    103                 case REBOOT:
    104                     device.reboot();
    105                     break;
    106                 case FORMAT:
    107                     device.rebootIntoBootloader();
    108                     device.executeLongFastbootCommand("-w");
    109                     device.executeFastbootCommand("reboot");
    110                     device.waitForDeviceAvailable();
    111                     break;
    112             }
    113             if (mScreenOff && mPostCleanupAction == PostCleanupAction.NONE) {
    114                 mPostCleanupAction = PostCleanupAction.SCREEN_OFF;
    115             }
    116             // perform post cleanup action
    117             switch (mPostCleanupAction) {
    118                 case NONE:
    119                     // do nothing here
    120                     break;
    121                 case SCREEN_OFF:
    122                     turnScreenOff(device);
    123                     break;
    124                 case SCREEN_OFF_AND_STOP:
    125                     turnScreenOff(device);
    126                     device.executeShellCommand("stop");
    127                     break;
    128             }
    129         }
    130     }
    131 
    132     private void turnScreenOff(ITestDevice device) throws DeviceNotAvailableException {
    133         String output = device.executeShellCommand("dumpsys power");
    134         int retries = 1;
    135         // screen on semantics have changed in newest API platform, checking for both signatures
    136         // to detect screen on state
    137         while (output.contains("mScreenOn=true") || output.contains("mInteractive=true")) {
    138             // KEYCODE_POWER = 26
    139             device.executeShellCommand("input keyevent 26");
    140             // due to framework initialization, device may not actually turn off screen
    141             // after boot, recheck screen status with linear backoff
    142             RunUtil.getDefault().sleep(SCREEN_OFF_RETRY_DELAY_MS * retries);
    143             output = device.executeShellCommand("dumpsys power");
    144             retries++;
    145             if (retries > MAX_SCREEN_OFF_RETRY) {
    146                 CLog.w(String.format("screen still on after %d retries", retries));
    147                 break;
    148             }
    149         }
    150     }
    151 }
    152