• 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    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