Home | History | Annotate | Download | only in theme
      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     240 : "hdpi",
     31     320 : "xhdpi",
     32     480 : "xxhdpi",
     33     640 : "xxxhdpi",
     34 }
     35 
     36 OUT_FILE = "/sdcard/cts-theme-assets.zip"
     37 
     38 # pass a function with number of instances to be executed in parallel
     39 # each thread continues until config q is empty.
     40 def executeParallel(tasks, setup, q, numberThreads):
     41     class ParallelExecutor(threading.Thread):
     42         def __init__(self, tasks, q):
     43             threading.Thread.__init__(self)
     44             self._q = q
     45             self._tasks = tasks
     46             self._setup = setup
     47             self._result = 0
     48 
     49         def run(self):
     50             try:
     51                 while True:
     52                     config = q.get(block=True, timeout=2)
     53                     for t in self._tasks:
     54                         try:
     55                             if t(self._setup, config):
     56                                 self._result += 1
     57                         except KeyboardInterrupt:
     58                             raise
     59                         except:
     60                             print "Failed to execute thread:", sys.exc_info()[0]
     61                             traceback.print_exc()
     62                     q.task_done()
     63             except KeyboardInterrupt:
     64                 raise
     65             except Queue.Empty:
     66                 pass
     67 
     68         def getResult(self):
     69             return self._result
     70 
     71     result = 0;
     72     threads = []
     73     for i in range(numberThreads):
     74         t = ParallelExecutor(tasks, q)
     75         t.start()
     76         threads.append(t)
     77     for t in threads:
     78         t.join()
     79         result += t.getResult()
     80     return result;
     81 
     82 def printAdbResult(device, out, err):
     83     print "device: " + device
     84     if out is not None:
     85         print "out:\n" + out
     86     if err is not None:
     87         print "err:\n" + err
     88 
     89 def getResDir(outPath, resName):
     90     resDir = outPath + "/" + resName
     91     return resDir
     92 
     93 def doCapturing(setup, deviceSerial):
     94     (themeApkPath, outPath) = setup
     95 
     96     print "Found device: " + deviceSerial
     97     device = androidDevice(deviceSerial)
     98 
     99     version = device.getVersionCodename()
    100     if version == "REL":
    101         version = str(device.getVersionSdkInt())
    102 
    103     density = device.getDensity()
    104 
    105     # Reference images generated for tv should not be categorized by density
    106     # rather by tv type. This is because TV uses leanback-specific material
    107     # themes.
    108     if CTS_THEME_dict.has_key(density):
    109         densityBucket = CTS_THEME_dict[density]
    110     else:
    111         densityBucket = str(density) + "dpi"
    112 
    113     resName = os.path.join(version, densityBucket)
    114 
    115     device.uninstallApk("android.theme.app")
    116 
    117     (out, err, success) = device.installApk(themeApkPath)
    118     if not success:
    119         print "Failed to install APK on " + deviceSerial
    120         printAdbResult(deviceSerial, out, err)
    121         return False
    122 
    123     print "Generating images on " + deviceSerial + "..."
    124     try:
    125         (out, err) = device.runInstrumentationTest("android.theme.app/android.support.test.runner.AndroidJUnitRunner")
    126     except KeyboardInterrupt:
    127         raise
    128     except:
    129         (out, err) = device.runInstrumentationTest("android.theme.app/android.test.InstrumentationTestRunner")
    130 
    131     # Detect test failure and abort.
    132     if "FAILURES!!!" in out.split():
    133         printAdbResult(deviceSerial, out, err)
    134         return False
    135 
    136     # Make sure that the run is complete by checking the process itself
    137     print "Waiting for " + deviceSerial + "..."
    138     waitTime = 0
    139     while device.isProcessAlive("android.theme.app"):
    140         time.sleep(1)
    141         waitTime = waitTime + 1
    142         if waitTime > 180:
    143             print "Timed out"
    144             break
    145 
    146     time.sleep(10)
    147     resDir = getResDir(outPath, resName)
    148 
    149     print "Pulling images from " + deviceSerial + " to " + resDir + ".zip"
    150     device.runAdbCommand("pull " + OUT_FILE + " " + resDir + ".zip")
    151     device.runAdbCommand("shell rm -rf " + OUT_FILE)
    152     return True
    153 
    154 def main(argv):
    155     if len(argv) < 3:
    156         print "run_theme_capture_device.py themeApkPath outDir"
    157         sys.exit(1)
    158     themeApkPath = argv[1]
    159     outPath = os.path.abspath(argv[2])
    160     os.system("mkdir -p " + outPath)
    161 
    162     tasks = []
    163     tasks.append(doCapturing)
    164 
    165     devices = runAdbDevices();
    166     numberThreads = len(devices)
    167 
    168     configQ = Queue.Queue()
    169     for device in devices:
    170         configQ.put(device)
    171     setup = (themeApkPath, outPath)
    172     result = executeParallel(tasks, setup, configQ, numberThreads)
    173 
    174     if result > 0:
    175         print 'Generated reference images for %(count)d devices' % {"count": result}
    176     else:
    177         print 'Failed to generate reference images'
    178 
    179 if __name__ == '__main__':
    180     main(sys.argv)
    181