Home | History | Annotate | Download | only in targetprep
      1 /*
      2  * Copyright (C) 2012 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.BackgroundDeviceAction;
     23 import com.android.tradefed.device.CollectingOutputReceiver;
     24 import com.android.tradefed.device.DeviceNotAvailableException;
     25 import com.android.tradefed.device.ITestDevice;
     26 import com.android.tradefed.log.LogUtil.CLog;
     27 import com.android.tradefed.util.CommandResult;
     28 import com.android.tradefed.util.CommandStatus;
     29 import com.android.tradefed.util.RunUtil;
     30 
     31 import java.util.ArrayList;
     32 import java.util.HashMap;
     33 import java.util.List;
     34 import java.util.Map;
     35 import java.util.concurrent.TimeUnit;
     36 
     37 @OptionClass(alias = "run-command")
     38 public class RunCommandTargetPreparer extends BaseTargetPreparer implements ITargetCleaner {
     39 
     40     @Option(name = "run-command", description = "adb shell command to run")
     41     private List<String> mCommands = new ArrayList<String>();
     42 
     43     @Option(name = "run-bg-command", description = "Command to run repeatedly in the"
     44             + " device background. Can be repeated to run multiple commands"
     45             + " in the background.")
     46     private List<String> mBgCommands = new ArrayList<String>();
     47 
     48     @Option(name = "hide-bg-output", description = "if true, don't log background command output")
     49     private boolean mHideBgOutput = false;
     50 
     51     @Option(name = "teardown-command", description = "adb shell command to run at teardown time")
     52     private List<String> mTeardownCommands = new ArrayList<String>();
     53 
     54     @Option(name = "delay-after-commands",
     55             description = "Time to delay after running commands, in msecs")
     56     private long mDelayMsecs = 0;
     57 
     58     @Option(name = "run-command-timeout",
     59             description = "Timeout for execute shell command",
     60             isTimeVal = true)
     61     private long mRunCmdTimeout = 0;
     62 
     63     @Option(
     64         name = "use-shell-v2",
     65         description =
     66                 "Whether or not to use the shell v2 execution which provides status and output "
     67                         + "for the shell command."
     68     )
     69     private boolean mUseShellV2 = false;
     70 
     71     private Map<BackgroundDeviceAction, CollectingOutputReceiver> mBgDeviceActionsMap =
     72             new HashMap<>();
     73 
     74     /**
     75      * {@inheritDoc}
     76      */
     77     @Override
     78     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
     79             DeviceNotAvailableException {
     80         if (isDisabled()) return;
     81 
     82         for (String bgCmd : mBgCommands) {
     83             CollectingOutputReceiver receiver = new CollectingOutputReceiver();
     84             BackgroundDeviceAction mBgDeviceAction =
     85                     new BackgroundDeviceAction(bgCmd, bgCmd, device, receiver, 0);
     86             mBgDeviceAction.start();
     87             mBgDeviceActionsMap.put(mBgDeviceAction, receiver);
     88         }
     89 
     90         for (String cmd : mCommands) {
     91             CLog.d("About to run setup command on device %s: %s", device.getSerialNumber(), cmd);
     92             CommandResult result;
     93             if (!mUseShellV2) {
     94                 // Shell v1 without command status.
     95                 if (mRunCmdTimeout > 0) {
     96                     CollectingOutputReceiver receiver = new CollectingOutputReceiver();
     97                     device.executeShellCommand(
     98                             cmd, receiver, mRunCmdTimeout, TimeUnit.MILLISECONDS, 0);
     99                     CLog.v("cmd: '%s', returned:\n%s", cmd, receiver.getOutput());
    100                 } else {
    101                     String output = device.executeShellCommand(cmd);
    102                     CLog.v("cmd: '%s', returned:\n%s", cmd, output);
    103                 }
    104             } else {
    105                 // Shell v2 with command status checks
    106                 if (mRunCmdTimeout > 0) {
    107                     result =
    108                             device.executeShellV2Command(
    109                                     cmd, mRunCmdTimeout, TimeUnit.MILLISECONDS, 0);
    110                 } else {
    111                     result = device.executeShellV2Command(cmd);
    112                 }
    113                 // Ensure the command ran successfully.
    114                 if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
    115                     throw new TargetSetupError(
    116                             String.format(
    117                                     "Failed to run '%s' without error. stdout: '%s'\nstderr: '%s'",
    118                                     cmd, result.getStdout(), result.getStderr()),
    119                             device.getDeviceDescriptor());
    120                 }
    121                 CLog.v("cmd: '%s', returned:\n%s", cmd, result.getStdout());
    122             }
    123         }
    124 
    125         CLog.d("Sleeping %d msecs on device %s", mDelayMsecs, device.getSerialNumber());
    126         RunUtil.getDefault().sleep(mDelayMsecs);
    127     }
    128 
    129     /**
    130      * {@inheritDoc}
    131      */
    132     @Override
    133     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
    134             throws DeviceNotAvailableException {
    135         if (isDisabled()) return;
    136 
    137         for (Map.Entry<BackgroundDeviceAction, CollectingOutputReceiver> bgAction :
    138                 mBgDeviceActionsMap.entrySet()) {
    139             if (!mHideBgOutput) {
    140                 CLog.d("Background command output : %s", bgAction.getValue().getOutput());
    141             }
    142             bgAction.getKey().cancel();
    143         }
    144 
    145         for (String cmd : mTeardownCommands) {
    146             CLog.d("About to run tearDown command on device %s: %s", device.getSerialNumber(),
    147                     cmd);
    148             String output = device.executeShellCommand(cmd);
    149             CLog.v("tearDown cmd: '%s', returned:\n%s", cmd, output);
    150         }
    151 
    152     }
    153 }
    154 
    155