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 18 import os 19 import sys 20 import threading 21 import time 22 import traceback 23 import Queue 24 sys.path.append(sys.path[0]) 25 from android_device import * 26 27 CTS_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 37 OUT_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. 41 def 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 83 def 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 90 def getResDir(outPath, resName): 91 resDir = outPath + "/" + resName 92 return resDir 93 94 def doCapturing(setup, deviceSerial): 95 (themeApkPath, outPath) = setup 96 97 print "Found device: " + deviceSerial 98 device = androidDevice(deviceSerial) 99 100 density = device.getDensity() 101 if CTS_THEME_dict.has_key(density): 102 resName = CTS_THEME_dict[density] 103 else: 104 resName = str(density) + "dpi" 105 106 device.uninstallApk("android.theme.app") 107 108 (out, err, success) = device.installApk(themeApkPath) 109 if not success: 110 print "Failed to install APK on " + deviceSerial 111 printAdbResult(deviceSerial, out, err) 112 return False 113 114 print "Generating images on " + deviceSerial + "..." 115 try: 116 (out, err) = device.runInstrumentationTest("android.theme.app/android.support.test.runner.AndroidJUnitRunner") 117 except KeyboardInterrupt: 118 raise 119 except: 120 (out, err) = device.runInstrumentationTest("android.theme.app/android.test.InstrumentationTestRunner") 121 122 # Detect test failure and abort. 123 if "FAILURES!!!" in out.split(): 124 printAdbResult(deviceSerial, out, err) 125 return False 126 127 # Make sure that the run is complete by checking the process itself 128 print "Waiting for " + deviceSerial + "..." 129 waitTime = 0 130 while device.isProcessAlive("android.theme.app"): 131 time.sleep(1) 132 waitTime = waitTime + 1 133 if waitTime > 180: 134 print "Timed out" 135 break 136 137 time.sleep(10) 138 resDir = getResDir(outPath, resName) 139 140 print "Pulling images from " + deviceSerial + " to " + resDir + ".zip" 141 device.runAdbCommand("pull " + OUT_FILE + " " + resDir + ".zip") 142 device.runAdbCommand("shell rm -rf " + OUT_FILE) 143 return True 144 145 def main(argv): 146 if len(argv) < 3: 147 print "run_theme_capture_device.py themeApkPath outDir" 148 sys.exit(1) 149 themeApkPath = argv[1] 150 outPath = os.path.abspath(argv[2]) 151 os.system("mkdir -p " + outPath) 152 153 tasks = [] 154 tasks.append(doCapturing) 155 156 devices = runAdbDevices(); 157 numberThreads = len(devices) 158 159 configQ = Queue.Queue() 160 for device in devices: 161 configQ.put(device) 162 setup = (themeApkPath, outPath) 163 result = executeParallel(tasks, setup, configQ, numberThreads) 164 165 if result > 0: 166 print 'Generated reference images for %(count)d devices' % {"count": result} 167 else: 168 print 'Failed to generate reference images' 169 170 if __name__ == '__main__': 171 main(sys.argv) 172