1 /* 2 * Copyright (C) 2014 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.tradefed.device; 17 18 import com.android.ddmlib.Log.LogLevel; 19 import com.android.tradefed.log.LogUtil.CLog; 20 import com.android.tradefed.util.CommandResult; 21 import com.android.tradefed.util.CommandStatus; 22 import com.android.tradefed.util.IRunUtil; 23 24 import java.util.HashSet; 25 import java.util.Set; 26 import java.util.regex.Matcher; 27 import java.util.regex.Pattern; 28 29 /** 30 * A helper class for fastboot operations. 31 */ 32 public class FastbootHelper { 33 34 /** max wait time in ms for fastboot devices command to complete */ 35 private static final long FASTBOOT_CMD_TIMEOUT = 1 * 60 * 1000; 36 37 private IRunUtil mRunUtil; 38 private String mFastbootPath = "fastboot"; 39 40 /** 41 * Constructor. 42 * 43 * @param runUtil a {@link IRunUtil}. 44 */ 45 public FastbootHelper(final IRunUtil runUtil, final String fastbootPath) { 46 if (runUtil == null) { 47 throw new IllegalArgumentException("runUtil cannot be null"); 48 } 49 if (fastbootPath == null || fastbootPath.isEmpty()) { 50 throw new IllegalArgumentException("fastboot cannot be null or empty"); 51 } 52 mRunUtil = runUtil; 53 mFastbootPath = fastbootPath; 54 } 55 56 /** 57 * Determine if fastboot is available for use. 58 */ 59 public boolean isFastbootAvailable() { 60 // Run "fastboot help" to check the existence and the version of fastboot 61 // (Old versions do not support "help" command). 62 CommandResult fastbootResult = mRunUtil.runTimedCmdSilently(5000, mFastbootPath, "help"); 63 if (fastbootResult.getStatus() == CommandStatus.SUCCESS) { 64 return true; 65 } 66 if (fastbootResult.getStderr() != null && 67 fastbootResult.getStderr().indexOf("usage: fastboot") >= 0) { 68 CLog.logAndDisplay(LogLevel.WARN, 69 "You are running an older version of fastboot, please update it."); 70 return true; 71 } 72 CLog.d("fastboot not available. stdout: %s, stderr: %s", 73 fastbootResult.getStdout(), fastbootResult.getStderr()); 74 return false; 75 } 76 77 78 /** 79 * Returns a set of device serials in fastboot mode or an empty set if no fastboot devices. 80 * 81 * @return a set of device serials. 82 */ 83 public Set<String> getDevices() { 84 CommandResult fastbootResult = mRunUtil.runTimedCmd(FASTBOOT_CMD_TIMEOUT, 85 mFastbootPath, "devices"); 86 if (fastbootResult.getStatus().equals(CommandStatus.SUCCESS)) { 87 CLog.v("fastboot devices returned\n %s", 88 fastbootResult.getStdout()); 89 return parseDevices(fastbootResult.getStdout()); 90 } else { 91 CLog.w("'fastboot devices' failed. Result: %s, stderr: %s", fastbootResult.getStatus(), 92 fastbootResult.getStderr()); 93 } 94 return new HashSet<String>(); 95 } 96 97 /** 98 * Parses the output of "fastboot devices" command. 99 * Exposed for unit testing. 100 * 101 * @param fastbootOutput the output of fastboot command. 102 * @return a set of device serials. 103 */ 104 Set<String> parseDevices(String fastbootOutput) { 105 Set<String> serials = new HashSet<String>(); 106 Pattern fastbootPattern = Pattern.compile("([\\w\\d-]+)\\s+fastboot\\s*"); 107 Matcher fastbootMatcher = fastbootPattern.matcher(fastbootOutput); 108 while (fastbootMatcher.find()) { 109 serials.add(fastbootMatcher.group(1)); 110 } 111 return serials; 112 } 113 114 /** 115 * Executes a fastboot command on a device and return the output. 116 * 117 * @param serial a device serial. 118 * @param command a fastboot command to run. 119 * @return the output of the fastboot command. null if the command failed. 120 */ 121 public String executeCommand(String serial, String command) { 122 final CommandResult fastbootResult = mRunUtil.runTimedCmd(FASTBOOT_CMD_TIMEOUT, 123 mFastbootPath, "-s", serial, command); 124 if (fastbootResult.getStatus() != CommandStatus.SUCCESS) { 125 CLog.w("'fastboot -s %s %s' failed. Result: %s, stderr: %s", serial, command, 126 fastbootResult.getStatus(), fastbootResult.getStderr()); 127 return null; 128 } 129 return fastbootResult.getStdout(); 130 } 131 } 132