• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(name = "throw-if-cmd-fail", description = "Whether or not to throw if a command fails")
64     private boolean mThrowIfFailed = false;
65 
66     private Map<BackgroundDeviceAction, CollectingOutputReceiver> mBgDeviceActionsMap =
67             new HashMap<>();
68 
69     /**
70      * {@inheritDoc}
71      */
72     @Override
setUp(ITestDevice device, IBuildInfo buildInfo)73     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError,
74             DeviceNotAvailableException {
75         if (isDisabled()) return;
76 
77         for (String bgCmd : mBgCommands) {
78             CollectingOutputReceiver receiver = new CollectingOutputReceiver();
79             BackgroundDeviceAction mBgDeviceAction =
80                     new BackgroundDeviceAction(bgCmd, bgCmd, device, receiver, 0);
81             mBgDeviceAction.start();
82             mBgDeviceActionsMap.put(mBgDeviceAction, receiver);
83         }
84 
85         for (String cmd : mCommands) {
86             CommandResult result;
87             // Shell v2 with command status checks
88             if (mRunCmdTimeout > 0) {
89                 result =
90                         device.executeShellV2Command(cmd, mRunCmdTimeout, TimeUnit.MILLISECONDS, 0);
91             } else {
92                 result = device.executeShellV2Command(cmd);
93             }
94             // Ensure the command ran successfully.
95             if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
96                 if (mThrowIfFailed) {
97                     throw new TargetSetupError(
98                             String.format(
99                                     "Failed to run '%s' without error. stdout: '%s'\nstderr: '%s'",
100                                     cmd, result.getStdout(), result.getStderr()),
101                             device.getDeviceDescriptor());
102                 } else {
103                     CLog.d(
104                             "cmd: '%s' failed, returned:\nstdout:%s\nstderr:%s",
105                             cmd, result.getStdout(), result.getStderr());
106                 }
107             }
108         }
109 
110         if (mDelayMsecs > 0) {
111             CLog.d("Sleeping %d msecs on device %s", mDelayMsecs, device.getSerialNumber());
112             RunUtil.getDefault().sleep(mDelayMsecs);
113         }
114     }
115 
116     /**
117      * {@inheritDoc}
118      */
119     @Override
tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)120     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
121             throws DeviceNotAvailableException {
122         if (isDisabled()) return;
123 
124         for (Map.Entry<BackgroundDeviceAction, CollectingOutputReceiver> bgAction :
125                 mBgDeviceActionsMap.entrySet()) {
126             if (!mHideBgOutput) {
127                 CLog.d("Background command output : %s", bgAction.getValue().getOutput());
128             }
129             bgAction.getKey().cancel();
130         }
131         if (e instanceof DeviceNotAvailableException) {
132             CLog.e("Skipping command teardown since exception was DeviceNotAvailable");
133             return;
134         }
135         for (String cmd : mTeardownCommands) {
136             CommandResult result = device.executeShellV2Command(cmd);
137             if (!CommandStatus.SUCCESS.equals(result.getStatus())) {
138                 CLog.d(
139                         "tearDown cmd: '%s' failed, returned:\nstdout:%s\nstderr:%s",
140                         cmd, result.getStdout(), result.getStderr());
141             }
142         }
143     }
144 }
145 
146