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 Queue 23sys.path.append(sys.path[0]) 24from android_device import * 25 26CTS_THEME_dict = { 27 120 : "ldpi", 28 160 : "mdpi", 29 213 : "tvdpi", 30 240 : "hdpi", 31 320 : "xhdpi", 32 400 : "400dpi", 33 480 : "xxhdpi", 34 560 : "560dpi", 35 640 : "xxxhdpi", 36} 37 38OUT_FILE = "/sdcard/cts-theme-assets.zip" 39 40# pass a function with number of instances to be executed in parallel 41# each thread continues until config q is empty. 42def executeParallel(tasks, setup, q, numberThreads): 43 class ParallelExecutor(threading.Thread): 44 def __init__(self, tasks, q): 45 threading.Thread.__init__(self) 46 self._q = q 47 self._tasks = tasks 48 self._setup = setup 49 self._result = 0 50 51 def run(self): 52 try: 53 while True: 54 config = q.get(block=True, timeout=2) 55 for t in self._tasks: 56 try: 57 if t(self._setup, config): 58 self._result += 1 59 except KeyboardInterrupt: 60 raise 61 except: 62 print "Failed to execute thread:", sys.exc_info()[0] 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()) + deviceSerial 101 outPath = outPath + "/%d" % (device.getSdkLevel()) 102 density = device.getDensity() 103 resName = CTS_THEME_dict[density] 104 105 device.uninstallApk("android.theme.app") 106 107 (out, err, success) = device.installApk(themeApkPath) 108 if not success: 109 print "Failed to install APK on " + deviceSerial 110 printAdbResult(device, out, err) 111 return False 112 113 print "Generating images on " + deviceSerial + "..." 114 try: 115 (out, err) = device.runInstrumentationTest("android.theme.app/android.support.test.runner.AndroidJUnitRunner") 116 except KeyboardInterrupt: 117 raise 118 except: 119 (out, err) = device.runInstrumentationTest("android.theme.app/android.test.InstrumentationTestRunner") 120 121 # Detect test failure and abort. 122 if "FAILURES!!!" in out.split(): 123 printAdbResult(deviceSerial, out, err) 124 return False 125 126 # Make sure that the run is complete by checking the process itself 127 print "Waiting for " + deviceSerial + "..." 128 waitTime = 0 129 while device.isProcessAlive("android.theme.app"): 130 time.sleep(1) 131 waitTime = waitTime + 1 132 if waitTime > 180: 133 print "Timed out" 134 break 135 136 time.sleep(10) 137 resDir = getResDir(outPath, resName) 138 139 print "Pulling images from " + deviceSerial + " to " + resDir + ".zip" 140 device.runAdbCommand("pull " + OUT_FILE + " " + resDir + ".zip") 141 device.runAdbCommand("shell rm -rf " + OUT_FILE) 142 return True 143 144def main(argv): 145 if len(argv) < 3: 146 print "run_theme_capture_device.py themeApkPath outDir" 147 sys.exit(1) 148 themeApkPath = argv[1] 149 outPath = os.path.abspath(argv[2]) 150 os.system("mkdir -p " + outPath) 151 152 tasks = [] 153 tasks.append(doCapturing) 154 155 devices = runAdbDevices(); 156 numberThreads = len(devices) 157 158 configQ = Queue.Queue() 159 for device in devices: 160 configQ.put(device) 161 setup = (themeApkPath, outPath) 162 result = executeParallel(tasks, setup, configQ, numberThreads) 163 164 if result > 0: 165 print 'Generated reference images for %(count)d devices' % {"count": result} 166 else: 167 print 'Failed to generate reference images' 168 169if __name__ == '__main__': 170 main(sys.argv) 171