1#!/usr/bin/env python 2# 3# Copyright (C) 2015 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the 'License'); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an 'AS IS' BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16# 17 18import os 19import sys 20import threading 21import time 22import traceback 23import Queue 24sys.path.append(sys.path[0]) 25from android_device import * 26 27CTS_THEME_dict = { 28 120 : "ldpi", 29 160 : "mdpi", 30 213 : "tvdpi", 31 240 : "hdpi", 32 320 : "xhdpi", 33 480 : "xxhdpi", 34 640 : "xxxhdpi", 35} 36 37OUT_FILE = "/sdcard/cts-theme-assets.zip" 38 39# pass a function with number of instances to be executed in parallel 40# each thread continues until config q is empty. 41def executeParallel(tasks, setup, q, numberThreads): 42 class ParallelExecutor(threading.Thread): 43 def __init__(self, tasks, q): 44 threading.Thread.__init__(self) 45 self._q = q 46 self._tasks = tasks 47 self._setup = setup 48 self._result = 0 49 50 def run(self): 51 try: 52 while True: 53 config = q.get(block=True, timeout=2) 54 for t in self._tasks: 55 try: 56 if t(self._setup, config): 57 self._result += 1 58 except KeyboardInterrupt: 59 raise 60 except: 61 print "Failed to execute thread:", sys.exc_info()[0] 62 traceback.print_exc() 63 q.task_done() 64 except KeyboardInterrupt: 65 raise 66 except Queue.Empty: 67 pass 68 69 def getResult(self): 70 return self._result 71 72 result = 0; 73 threads = [] 74 for i in range(numberThreads): 75 t = ParallelExecutor(tasks, q) 76 t.start() 77 threads.append(t) 78 for t in threads: 79 t.join() 80 result += t.getResult() 81 return result; 82 83def printAdbResult(device, out, err): 84 print "device: " + device 85 if out is not None: 86 print "out:\n" + out 87 if err is not None: 88 print "err:\n" + err 89 90def getResDir(outPath, resName): 91 resDir = outPath + "/" + resName 92 return resDir 93 94def doCapturing(setup, deviceSerial): 95 (themeApkPath, outPath) = setup 96 97 print "Found device: " + deviceSerial 98 device = androidDevice(deviceSerial) 99 100 outPath = outPath + "/%d" % (device.getSdkLevel()) 101 density = device.getDensity() 102 if CTS_THEME_dict.has_key(density): 103 resName = CTS_THEME_dict[density] 104 else: 105 resName = str(density) + "dpi" 106 107 device.uninstallApk("android.theme.app") 108 109 (out, err, success) = device.installApk(themeApkPath) 110 if not success: 111 print "Failed to install APK on " + deviceSerial 112 printAdbResult(deviceSerial, out, err) 113 return False 114 115 print "Generating images on " + deviceSerial + "..." 116 try: 117 (out, err) = device.runInstrumentationTest("android.theme.app/android.support.test.runner.AndroidJUnitRunner") 118 except KeyboardInterrupt: 119 raise 120 except: 121 (out, err) = device.runInstrumentationTest("android.theme.app/android.test.InstrumentationTestRunner") 122 123 # Detect test failure and abort. 124 if "FAILURES!!!" in out.split(): 125 printAdbResult(deviceSerial, out, err) 126 return False 127 128 # Make sure that the run is complete by checking the process itself 129 print "Waiting for " + deviceSerial + "..." 130 waitTime = 0 131 while device.isProcessAlive("android.theme.app"): 132 time.sleep(1) 133 waitTime = waitTime + 1 134 if waitTime > 180: 135 print "Timed out" 136 break 137 138 time.sleep(10) 139 resDir = getResDir(outPath, resName) 140 141 print "Pulling images from " + deviceSerial + " to " + resDir + ".zip" 142 device.runAdbCommand("pull " + OUT_FILE + " " + resDir + ".zip") 143 device.runAdbCommand("shell rm -rf " + OUT_FILE) 144 return True 145 146def main(argv): 147 if len(argv) < 3: 148 print "run_theme_capture_device.py themeApkPath outDir" 149 sys.exit(1) 150 themeApkPath = argv[1] 151 outPath = os.path.abspath(argv[2]) 152 os.system("mkdir -p " + outPath) 153 154 tasks = [] 155 tasks.append(doCapturing) 156 157 devices = runAdbDevices(); 158 numberThreads = len(devices) 159 160 configQ = Queue.Queue() 161 for device in devices: 162 configQ.put(device) 163 setup = (themeApkPath, outPath) 164 result = executeParallel(tasks, setup, configQ, numberThreads) 165 166 if result > 0: 167 print 'Generated reference images for %(count)d devices' % {"count": result} 168 else: 169 print 'Failed to generate reference images' 170 171if __name__ == '__main__': 172 main(sys.argv) 173