• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    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
145def 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
170if __name__ == '__main__':
171    main(sys.argv)
172