1*90c8c64dSAndroid Build Coastguard Worker#!/usr/bin/env python2.7 2*90c8c64dSAndroid Build Coastguard Worker 3*90c8c64dSAndroid Build Coastguard Workerimport argparse 4*90c8c64dSAndroid Build Coastguard Workerimport datetime 5*90c8c64dSAndroid Build Coastguard Workerimport os 6*90c8c64dSAndroid Build Coastguard Workerimport re 7*90c8c64dSAndroid Build Coastguard Workerimport subprocess 8*90c8c64dSAndroid Build Coastguard Workerimport sys 9*90c8c64dSAndroid Build Coastguard Workerimport threading 10*90c8c64dSAndroid Build Coastguard Workerimport time 11*90c8c64dSAndroid Build Coastguard Worker 12*90c8c64dSAndroid Build Coastguard WorkerQUIET = False 13*90c8c64dSAndroid Build Coastguard Worker 14*90c8c64dSAndroid Build Coastguard Worker# ANSI escape sequences 15*90c8c64dSAndroid Build Coastguard Workerif sys.stdout.isatty(): 16*90c8c64dSAndroid Build Coastguard Worker BOLD = "\033[1m" 17*90c8c64dSAndroid Build Coastguard Worker RED = "\033[91m" + BOLD 18*90c8c64dSAndroid Build Coastguard Worker GREEN = "\033[92m" + BOLD 19*90c8c64dSAndroid Build Coastguard Worker YELLOW = "\033[93m" + BOLD 20*90c8c64dSAndroid Build Coastguard Worker UNDERLINE = "\033[4m" 21*90c8c64dSAndroid Build Coastguard Worker ENDCOLOR = "\033[0m" 22*90c8c64dSAndroid Build Coastguard Worker CLEARLINE = "\033[K" 23*90c8c64dSAndroid Build Coastguard Worker STDOUT_IS_TTY = True 24*90c8c64dSAndroid Build Coastguard Workerelse: 25*90c8c64dSAndroid Build Coastguard Worker BOLD = "" 26*90c8c64dSAndroid Build Coastguard Worker RED = "" 27*90c8c64dSAndroid Build Coastguard Worker GREEN = "" 28*90c8c64dSAndroid Build Coastguard Worker YELLOW = "" 29*90c8c64dSAndroid Build Coastguard Worker UNDERLINE = "" 30*90c8c64dSAndroid Build Coastguard Worker ENDCOLOR = "" 31*90c8c64dSAndroid Build Coastguard Worker CLEARLINE = "" 32*90c8c64dSAndroid Build Coastguard Worker STDOUT_IS_TTY = False 33*90c8c64dSAndroid Build Coastguard Worker 34*90c8c64dSAndroid Build Coastguard Workerdef PrintStatus(s): 35*90c8c64dSAndroid Build Coastguard Worker """Prints a bold underlined status message""" 36*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write("\n") 37*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(BOLD) 38*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(UNDERLINE) 39*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(s) 40*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(ENDCOLOR) 41*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write("\n") 42*90c8c64dSAndroid Build Coastguard Worker 43*90c8c64dSAndroid Build Coastguard Worker 44*90c8c64dSAndroid Build Coastguard Workerdef PrintCommand(cmd, env=None): 45*90c8c64dSAndroid Build Coastguard Worker """Prints a bold line of a shell command that is being run""" 46*90c8c64dSAndroid Build Coastguard Worker if not QUIET: 47*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(BOLD) 48*90c8c64dSAndroid Build Coastguard Worker if env: 49*90c8c64dSAndroid Build Coastguard Worker for k,v in env.iteritems(): 50*90c8c64dSAndroid Build Coastguard Worker if " " in v and "\"" not in v: 51*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write("%s=\"%s\" " % (k, v.replace("\"", "\\\""))) 52*90c8c64dSAndroid Build Coastguard Worker else: 53*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write("%s=%s " % (k, v)) 54*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(" ".join(cmd)) 55*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write(ENDCOLOR) 56*90c8c64dSAndroid Build Coastguard Worker sys.stdout.write("\n") 57*90c8c64dSAndroid Build Coastguard Worker 58*90c8c64dSAndroid Build Coastguard Worker 59*90c8c64dSAndroid Build Coastguard Workerclass ExecutionException(Exception): 60*90c8c64dSAndroid Build Coastguard Worker """Thrown to cleanly abort operation.""" 61*90c8c64dSAndroid Build Coastguard Worker def __init__(self,*args,**kwargs): 62*90c8c64dSAndroid Build Coastguard Worker Exception.__init__(self,*args,**kwargs) 63*90c8c64dSAndroid Build Coastguard Worker 64*90c8c64dSAndroid Build Coastguard Worker 65*90c8c64dSAndroid Build Coastguard Workerclass Adb(object): 66*90c8c64dSAndroid Build Coastguard Worker """Encapsulates adb functionality.""" 67*90c8c64dSAndroid Build Coastguard Worker 68*90c8c64dSAndroid Build Coastguard Worker def __init__(self): 69*90c8c64dSAndroid Build Coastguard Worker """Initialize adb.""" 70*90c8c64dSAndroid Build Coastguard Worker self._command = ["adb"] 71*90c8c64dSAndroid Build Coastguard Worker 72*90c8c64dSAndroid Build Coastguard Worker 73*90c8c64dSAndroid Build Coastguard Worker def Exec(self, cmd, stdout=None, stderr=None): 74*90c8c64dSAndroid Build Coastguard Worker """Runs an adb command, and prints that command to stdout. 75*90c8c64dSAndroid Build Coastguard Worker 76*90c8c64dSAndroid Build Coastguard Worker Raises: 77*90c8c64dSAndroid Build Coastguard Worker ExecutionException: if the adb command returned an error. 78*90c8c64dSAndroid Build Coastguard Worker 79*90c8c64dSAndroid Build Coastguard Worker Example: 80*90c8c64dSAndroid Build Coastguard Worker adb.Exec("shell", "ls") will run "adb shell ls" 81*90c8c64dSAndroid Build Coastguard Worker """ 82*90c8c64dSAndroid Build Coastguard Worker cmd = self._command + cmd 83*90c8c64dSAndroid Build Coastguard Worker PrintCommand(cmd) 84*90c8c64dSAndroid Build Coastguard Worker result = subprocess.call(cmd, stdout=stdout, stderr=stderr) 85*90c8c64dSAndroid Build Coastguard Worker if result: 86*90c8c64dSAndroid Build Coastguard Worker raise ExecutionException("adb: %s returned %s" % (cmd, result)) 87*90c8c64dSAndroid Build Coastguard Worker 88*90c8c64dSAndroid Build Coastguard Worker 89*90c8c64dSAndroid Build Coastguard Worker def WaitForDevice(self): 90*90c8c64dSAndroid Build Coastguard Worker """Waits for the android device to be available on usb with adbd running.""" 91*90c8c64dSAndroid Build Coastguard Worker self.Exec(["wait-for-device"]) 92*90c8c64dSAndroid Build Coastguard Worker 93*90c8c64dSAndroid Build Coastguard Worker 94*90c8c64dSAndroid Build Coastguard Worker def Run(self, cmd, stdout=None, stderr=None): 95*90c8c64dSAndroid Build Coastguard Worker """Waits for the device, and then runs a command. 96*90c8c64dSAndroid Build Coastguard Worker 97*90c8c64dSAndroid Build Coastguard Worker Raises: 98*90c8c64dSAndroid Build Coastguard Worker ExecutionException: if the adb command returned an error. 99*90c8c64dSAndroid Build Coastguard Worker 100*90c8c64dSAndroid Build Coastguard Worker Example: 101*90c8c64dSAndroid Build Coastguard Worker adb.Run("shell", "ls") will run "adb shell ls" 102*90c8c64dSAndroid Build Coastguard Worker """ 103*90c8c64dSAndroid Build Coastguard Worker self.WaitForDevice() 104*90c8c64dSAndroid Build Coastguard Worker self.Exec(cmd, stdout=stdout, stderr=stderr) 105*90c8c64dSAndroid Build Coastguard Worker 106*90c8c64dSAndroid Build Coastguard Worker 107*90c8c64dSAndroid Build Coastguard Worker def Get(self, cmd): 108*90c8c64dSAndroid Build Coastguard Worker """Waits for the device, and then runs a command, returning the output. 109*90c8c64dSAndroid Build Coastguard Worker 110*90c8c64dSAndroid Build Coastguard Worker Raises: 111*90c8c64dSAndroid Build Coastguard Worker ExecutionException: if the adb command returned an error. 112*90c8c64dSAndroid Build Coastguard Worker 113*90c8c64dSAndroid Build Coastguard Worker Example: 114*90c8c64dSAndroid Build Coastguard Worker adb.Get(["shell", "ls"]) will run "adb shell ls" 115*90c8c64dSAndroid Build Coastguard Worker """ 116*90c8c64dSAndroid Build Coastguard Worker self.WaitForDevice() 117*90c8c64dSAndroid Build Coastguard Worker cmd = self._command + cmd 118*90c8c64dSAndroid Build Coastguard Worker PrintCommand(cmd) 119*90c8c64dSAndroid Build Coastguard Worker try: 120*90c8c64dSAndroid Build Coastguard Worker text = subprocess.check_output(cmd) 121*90c8c64dSAndroid Build Coastguard Worker return text.strip() 122*90c8c64dSAndroid Build Coastguard Worker except subprocess.CalledProcessError as ex: 123*90c8c64dSAndroid Build Coastguard Worker raise ExecutionException("adb: %s returned %s" % (cmd, ex.returncode)) 124*90c8c64dSAndroid Build Coastguard Worker 125*90c8c64dSAndroid Build Coastguard Worker 126*90c8c64dSAndroid Build Coastguard Worker def Shell(self, cmd, stdout=None, stderr=None): 127*90c8c64dSAndroid Build Coastguard Worker """Runs an adb shell command 128*90c8c64dSAndroid Build Coastguard Worker Args: 129*90c8c64dSAndroid Build Coastguard Worker cmd: The command to run. 130*90c8c64dSAndroid Build Coastguard Worker 131*90c8c64dSAndroid Build Coastguard Worker Raises: 132*90c8c64dSAndroid Build Coastguard Worker ExecutionException: if the adb command returned an error. 133*90c8c64dSAndroid Build Coastguard Worker 134*90c8c64dSAndroid Build Coastguard Worker Example: 135*90c8c64dSAndroid Build Coastguard Worker adb.Shell(["ls"]) will run "adb shell ls" 136*90c8c64dSAndroid Build Coastguard Worker """ 137*90c8c64dSAndroid Build Coastguard Worker cmd = ["shell"] + cmd 138*90c8c64dSAndroid Build Coastguard Worker self.Run(cmd, stdout=stdout, stderr=stderr) 139*90c8c64dSAndroid Build Coastguard Worker 140*90c8c64dSAndroid Build Coastguard Worker 141*90c8c64dSAndroid Build Coastguard Worker def GetProp(self, name): 142*90c8c64dSAndroid Build Coastguard Worker """Gets a system property from the device.""" 143*90c8c64dSAndroid Build Coastguard Worker return self.Get(["shell", "getprop", name]) 144*90c8c64dSAndroid Build Coastguard Worker 145*90c8c64dSAndroid Build Coastguard Worker 146*90c8c64dSAndroid Build Coastguard Worker def Reboot(self): 147*90c8c64dSAndroid Build Coastguard Worker """Reboots the device, and waits for boot to complete.""" 148*90c8c64dSAndroid Build Coastguard Worker # Reboot 149*90c8c64dSAndroid Build Coastguard Worker self.Run(["reboot"]) 150*90c8c64dSAndroid Build Coastguard Worker # Wait until it comes back on adb 151*90c8c64dSAndroid Build Coastguard Worker self.WaitForDevice() 152*90c8c64dSAndroid Build Coastguard Worker # Poll until the system says it's booted 153*90c8c64dSAndroid Build Coastguard Worker while self.GetProp("sys.boot_completed") != "1": 154*90c8c64dSAndroid Build Coastguard Worker time.sleep(2) 155*90c8c64dSAndroid Build Coastguard Worker # Dismiss the keyguard 156*90c8c64dSAndroid Build Coastguard Worker self.Shell(["wm", "dismiss-keyguard"]); 157*90c8c64dSAndroid Build Coastguard Worker 158*90c8c64dSAndroid Build Coastguard Worker def GetBatteryProperties(self): 159*90c8c64dSAndroid Build Coastguard Worker """A dict of the properties from adb shell dumpsys battery""" 160*90c8c64dSAndroid Build Coastguard Worker def ConvertVal(s): 161*90c8c64dSAndroid Build Coastguard Worker if s == "true": 162*90c8c64dSAndroid Build Coastguard Worker return True 163*90c8c64dSAndroid Build Coastguard Worker elif s == "false": 164*90c8c64dSAndroid Build Coastguard Worker return False 165*90c8c64dSAndroid Build Coastguard Worker else: 166*90c8c64dSAndroid Build Coastguard Worker try: 167*90c8c64dSAndroid Build Coastguard Worker return int(s) 168*90c8c64dSAndroid Build Coastguard Worker except ValueError: 169*90c8c64dSAndroid Build Coastguard Worker return s 170*90c8c64dSAndroid Build Coastguard Worker text = self.Get(["shell", "dumpsys", "battery"]) 171*90c8c64dSAndroid Build Coastguard Worker lines = [line.strip() for line in text.split("\n")][1:] 172*90c8c64dSAndroid Build Coastguard Worker lines = [[s.strip() for s in line.split(":", 1)] for line in lines] 173*90c8c64dSAndroid Build Coastguard Worker lines = [(k,ConvertVal(v)) for k,v in lines] 174*90c8c64dSAndroid Build Coastguard Worker return dict(lines) 175*90c8c64dSAndroid Build Coastguard Worker 176*90c8c64dSAndroid Build Coastguard Worker def GetBatteryLevel(self): 177*90c8c64dSAndroid Build Coastguard Worker """Returns the battery level""" 178*90c8c64dSAndroid Build Coastguard Worker return self.GetBatteryProperties()["level"] 179*90c8c64dSAndroid Build Coastguard Worker 180*90c8c64dSAndroid Build Coastguard Worker 181*90c8c64dSAndroid Build Coastguard Worker 182*90c8c64dSAndroid Build Coastguard Workerdef CurrentTimestamp(): 183*90c8c64dSAndroid Build Coastguard Worker """Returns the current time in a format suitable for filenames.""" 184*90c8c64dSAndroid Build Coastguard Worker return datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S") 185*90c8c64dSAndroid Build Coastguard Worker 186*90c8c64dSAndroid Build Coastguard Worker 187*90c8c64dSAndroid Build Coastguard Workerdef ParseOptions(): 188*90c8c64dSAndroid Build Coastguard Worker """Parse the command line options. 189*90c8c64dSAndroid Build Coastguard Worker 190*90c8c64dSAndroid Build Coastguard Worker Returns an argparse options object. 191*90c8c64dSAndroid Build Coastguard Worker """ 192*90c8c64dSAndroid Build Coastguard Worker parser = argparse.ArgumentParser(description="Run monkeys and collect the results.") 193*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("--dir", action="store", 194*90c8c64dSAndroid Build Coastguard Worker help="output directory for results of monkey runs") 195*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("--events", action="store", type=int, default=125000, 196*90c8c64dSAndroid Build Coastguard Worker help="number of events per monkey run") 197*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("-p", action="append", dest="packages", 198*90c8c64dSAndroid Build Coastguard Worker help="package to use (default is a set of system-wide packages") 199*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("--runs", action="store", type=int, default=10000000, 200*90c8c64dSAndroid Build Coastguard Worker help="number of monkey runs to perform") 201*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("--type", choices=["crash", "anr"], 202*90c8c64dSAndroid Build Coastguard Worker help="only stop on errors of the given type (crash or anr)") 203*90c8c64dSAndroid Build Coastguard Worker parser.add_argument("--description", action="store", 204*90c8c64dSAndroid Build Coastguard Worker help="only stop if the error description contains DESCRIPTION") 205*90c8c64dSAndroid Build Coastguard Worker 206*90c8c64dSAndroid Build Coastguard Worker options = parser.parse_args() 207*90c8c64dSAndroid Build Coastguard Worker 208*90c8c64dSAndroid Build Coastguard Worker if not options.dir: 209*90c8c64dSAndroid Build Coastguard Worker options.dir = "monkeys-%s" % CurrentTimestamp() 210*90c8c64dSAndroid Build Coastguard Worker 211*90c8c64dSAndroid Build Coastguard Worker if not options.packages: 212*90c8c64dSAndroid Build Coastguard Worker options.packages = [ 213*90c8c64dSAndroid Build Coastguard Worker "com.google.android.deskclock", 214*90c8c64dSAndroid Build Coastguard Worker "com.android.calculator2", 215*90c8c64dSAndroid Build Coastguard Worker "com.google.android.contacts", 216*90c8c64dSAndroid Build Coastguard Worker "com.android.launcher", 217*90c8c64dSAndroid Build Coastguard Worker "com.google.android.launcher", 218*90c8c64dSAndroid Build Coastguard Worker "com.android.mms", 219*90c8c64dSAndroid Build Coastguard Worker "com.google.android.apps.messaging", 220*90c8c64dSAndroid Build Coastguard Worker "com.android.phone", 221*90c8c64dSAndroid Build Coastguard Worker "com.google.android.dialer", 222*90c8c64dSAndroid Build Coastguard Worker "com.android.providers.downloads.ui", 223*90c8c64dSAndroid Build Coastguard Worker "com.android.settings", 224*90c8c64dSAndroid Build Coastguard Worker "com.google.android.calendar", 225*90c8c64dSAndroid Build Coastguard Worker "com.google.android.GoogleCamera", 226*90c8c64dSAndroid Build Coastguard Worker "com.google.android.apps.photos", 227*90c8c64dSAndroid Build Coastguard Worker "com.google.android.gms", 228*90c8c64dSAndroid Build Coastguard Worker "com.google.android.setupwizard", 229*90c8c64dSAndroid Build Coastguard Worker "com.google.android.googlequicksearchbox", 230*90c8c64dSAndroid Build Coastguard Worker "com.google.android.packageinstaller", 231*90c8c64dSAndroid Build Coastguard Worker "com.google.android.apps.nexuslauncher" 232*90c8c64dSAndroid Build Coastguard Worker ] 233*90c8c64dSAndroid Build Coastguard Worker 234*90c8c64dSAndroid Build Coastguard Worker return options 235*90c8c64dSAndroid Build Coastguard Worker 236*90c8c64dSAndroid Build Coastguard Worker 237*90c8c64dSAndroid Build Coastguard Workeradb = Adb() 238*90c8c64dSAndroid Build Coastguard Worker 239*90c8c64dSAndroid Build Coastguard Workerdef main(): 240*90c8c64dSAndroid Build Coastguard Worker """Main entry point.""" 241*90c8c64dSAndroid Build Coastguard Worker 242*90c8c64dSAndroid Build Coastguard Worker def LogcatThreadFunc(): 243*90c8c64dSAndroid Build Coastguard Worker logcatProcess.communicate() 244*90c8c64dSAndroid Build Coastguard Worker 245*90c8c64dSAndroid Build Coastguard Worker options = ParseOptions() 246*90c8c64dSAndroid Build Coastguard Worker 247*90c8c64dSAndroid Build Coastguard Worker # Set up the device a little bit 248*90c8c64dSAndroid Build Coastguard Worker PrintStatus("Setting up the device") 249*90c8c64dSAndroid Build Coastguard Worker adb.Run(["root"]) 250*90c8c64dSAndroid Build Coastguard Worker time.sleep(2) 251*90c8c64dSAndroid Build Coastguard Worker adb.WaitForDevice() 252*90c8c64dSAndroid Build Coastguard Worker adb.Run(["remount"]) 253*90c8c64dSAndroid Build Coastguard Worker time.sleep(2) 254*90c8c64dSAndroid Build Coastguard Worker adb.WaitForDevice() 255*90c8c64dSAndroid Build Coastguard Worker adb.Shell(["echo ro.audio.silent=1 > /data/local.prop"]) 256*90c8c64dSAndroid Build Coastguard Worker adb.Shell(["chmod 644 /data/local.prop"]) 257*90c8c64dSAndroid Build Coastguard Worker 258*90c8c64dSAndroid Build Coastguard Worker # Figure out how many leading zeroes we need. 259*90c8c64dSAndroid Build Coastguard Worker pattern = "%%0%dd" % len(str(options.runs-1)) 260*90c8c64dSAndroid Build Coastguard Worker 261*90c8c64dSAndroid Build Coastguard Worker # Make the output directory 262*90c8c64dSAndroid Build Coastguard Worker if os.path.exists(options.dir) and not os.path.isdir(options.dir): 263*90c8c64dSAndroid Build Coastguard Worker sys.stderr.write("Output directory already exists and is not a directory: %s\n" 264*90c8c64dSAndroid Build Coastguard Worker % options.dir) 265*90c8c64dSAndroid Build Coastguard Worker sys.exit(1) 266*90c8c64dSAndroid Build Coastguard Worker elif not os.path.exists(options.dir): 267*90c8c64dSAndroid Build Coastguard Worker os.makedirs(options.dir) 268*90c8c64dSAndroid Build Coastguard Worker 269*90c8c64dSAndroid Build Coastguard Worker # Run the tests 270*90c8c64dSAndroid Build Coastguard Worker for run in range(1, options.runs+1): 271*90c8c64dSAndroid Build Coastguard Worker PrintStatus("Run %d of %d: %s" % (run, options.runs, 272*90c8c64dSAndroid Build Coastguard Worker datetime.datetime.now().strftime("%A, %B %d %Y %I:%M %p"))) 273*90c8c64dSAndroid Build Coastguard Worker 274*90c8c64dSAndroid Build Coastguard Worker # Reboot and wait for 30 seconds to let the system quiet down so the 275*90c8c64dSAndroid Build Coastguard Worker # log isn't polluted with all the boot completed crap. 276*90c8c64dSAndroid Build Coastguard Worker if True: 277*90c8c64dSAndroid Build Coastguard Worker adb.Reboot() 278*90c8c64dSAndroid Build Coastguard Worker PrintCommand(["sleep", "30"]) 279*90c8c64dSAndroid Build Coastguard Worker time.sleep(30) 280*90c8c64dSAndroid Build Coastguard Worker 281*90c8c64dSAndroid Build Coastguard Worker # Monkeys can outrun the battery, so if it's getting low, pause to 282*90c8c64dSAndroid Build Coastguard Worker # let it charge. 283*90c8c64dSAndroid Build Coastguard Worker if True: 284*90c8c64dSAndroid Build Coastguard Worker targetBatteryLevel = 20 285*90c8c64dSAndroid Build Coastguard Worker while True: 286*90c8c64dSAndroid Build Coastguard Worker level = adb.GetBatteryLevel() 287*90c8c64dSAndroid Build Coastguard Worker if level > targetBatteryLevel: 288*90c8c64dSAndroid Build Coastguard Worker break 289*90c8c64dSAndroid Build Coastguard Worker print "Battery level is %d%%. Pausing to let it charge above %d%%." % ( 290*90c8c64dSAndroid Build Coastguard Worker level, targetBatteryLevel) 291*90c8c64dSAndroid Build Coastguard Worker time.sleep(60) 292*90c8c64dSAndroid Build Coastguard Worker 293*90c8c64dSAndroid Build Coastguard Worker filebase = os.path.sep.join((options.dir, pattern % run)) 294*90c8c64dSAndroid Build Coastguard Worker bugreportFilename = filebase + "-bugreport.txt" 295*90c8c64dSAndroid Build Coastguard Worker monkeyFilename = filebase + "-monkey.txt" 296*90c8c64dSAndroid Build Coastguard Worker logcatFilename = filebase + "-logcat.txt" 297*90c8c64dSAndroid Build Coastguard Worker htmlFilename = filebase + ".html" 298*90c8c64dSAndroid Build Coastguard Worker 299*90c8c64dSAndroid Build Coastguard Worker monkeyFile = file(monkeyFilename, "w") 300*90c8c64dSAndroid Build Coastguard Worker logcatFile = file(logcatFilename, "w") 301*90c8c64dSAndroid Build Coastguard Worker bugreportFile = None 302*90c8c64dSAndroid Build Coastguard Worker 303*90c8c64dSAndroid Build Coastguard Worker # Clear the log, then start logcat 304*90c8c64dSAndroid Build Coastguard Worker adb.Shell(["logcat", "-c", "-b", "main,system,events,crash"]) 305*90c8c64dSAndroid Build Coastguard Worker cmd = ["adb", "logcat", "-b", "main,system,events,crash"] 306*90c8c64dSAndroid Build Coastguard Worker PrintCommand(cmd) 307*90c8c64dSAndroid Build Coastguard Worker logcatProcess = subprocess.Popen(cmd, stdout=logcatFile, stderr=None) 308*90c8c64dSAndroid Build Coastguard Worker logcatThread = threading.Thread(target=LogcatThreadFunc) 309*90c8c64dSAndroid Build Coastguard Worker logcatThread.start() 310*90c8c64dSAndroid Build Coastguard Worker 311*90c8c64dSAndroid Build Coastguard Worker # Run monkeys 312*90c8c64dSAndroid Build Coastguard Worker cmd = [ 313*90c8c64dSAndroid Build Coastguard Worker "monkey", 314*90c8c64dSAndroid Build Coastguard Worker "-c", "android.intent.category.LAUNCHER", 315*90c8c64dSAndroid Build Coastguard Worker "--ignore-security-exceptions", 316*90c8c64dSAndroid Build Coastguard Worker "--monitor-native-crashes", 317*90c8c64dSAndroid Build Coastguard Worker "-v", "-v", "-v" 318*90c8c64dSAndroid Build Coastguard Worker ] 319*90c8c64dSAndroid Build Coastguard Worker for pkg in options.packages: 320*90c8c64dSAndroid Build Coastguard Worker cmd.append("-p") 321*90c8c64dSAndroid Build Coastguard Worker cmd.append(pkg) 322*90c8c64dSAndroid Build Coastguard Worker if options.type == "anr": 323*90c8c64dSAndroid Build Coastguard Worker cmd.append("--ignore-crashes") 324*90c8c64dSAndroid Build Coastguard Worker cmd.append("--ignore-native-crashes") 325*90c8c64dSAndroid Build Coastguard Worker if options.type == "crash": 326*90c8c64dSAndroid Build Coastguard Worker cmd.append("--ignore-timeouts") 327*90c8c64dSAndroid Build Coastguard Worker if options.description: 328*90c8c64dSAndroid Build Coastguard Worker cmd.append("--match-description") 329*90c8c64dSAndroid Build Coastguard Worker cmd.append("'" + options.description + "'") 330*90c8c64dSAndroid Build Coastguard Worker cmd.append(str(options.events)) 331*90c8c64dSAndroid Build Coastguard Worker try: 332*90c8c64dSAndroid Build Coastguard Worker adb.Shell(cmd, stdout=monkeyFile, stderr=monkeyFile) 333*90c8c64dSAndroid Build Coastguard Worker needReport = False 334*90c8c64dSAndroid Build Coastguard Worker except ExecutionException: 335*90c8c64dSAndroid Build Coastguard Worker # Monkeys failed, take a bugreport 336*90c8c64dSAndroid Build Coastguard Worker bugreportFile = file(bugreportFilename, "w") 337*90c8c64dSAndroid Build Coastguard Worker adb.Shell(["bugreport"], stdout=bugreportFile, stderr=None) 338*90c8c64dSAndroid Build Coastguard Worker needReport = True 339*90c8c64dSAndroid Build Coastguard Worker finally: 340*90c8c64dSAndroid Build Coastguard Worker monkeyFile.close() 341*90c8c64dSAndroid Build Coastguard Worker try: 342*90c8c64dSAndroid Build Coastguard Worker logcatProcess.terminate() 343*90c8c64dSAndroid Build Coastguard Worker except OSError: 344*90c8c64dSAndroid Build Coastguard Worker pass # it must have died on its own 345*90c8c64dSAndroid Build Coastguard Worker logcatThread.join() 346*90c8c64dSAndroid Build Coastguard Worker logcatFile.close() 347*90c8c64dSAndroid Build Coastguard Worker if bugreportFile: 348*90c8c64dSAndroid Build Coastguard Worker bugreportFile.close() 349*90c8c64dSAndroid Build Coastguard Worker 350*90c8c64dSAndroid Build Coastguard Worker if needReport: 351*90c8c64dSAndroid Build Coastguard Worker # Generate the html 352*90c8c64dSAndroid Build Coastguard Worker cmd = ["bugreport", "--monkey", monkeyFilename, "--html", htmlFilename, 353*90c8c64dSAndroid Build Coastguard Worker "--logcat", logcatFilename, bugreportFilename] 354*90c8c64dSAndroid Build Coastguard Worker PrintCommand(cmd) 355*90c8c64dSAndroid Build Coastguard Worker result = subprocess.call(cmd) 356*90c8c64dSAndroid Build Coastguard Worker 357*90c8c64dSAndroid Build Coastguard Worker 358*90c8c64dSAndroid Build Coastguard Worker 359*90c8c64dSAndroid Build Coastguard Workerif __name__ == "__main__": 360*90c8c64dSAndroid Build Coastguard Worker main() 361*90c8c64dSAndroid Build Coastguard Worker 362*90c8c64dSAndroid Build Coastguard Worker# vim: set ts=2 sw=2 sts=2 expandtab nocindent autoindent: 363