1ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad#!/usr/bin/python
2ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport hashlib
3ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport optparse
4ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport os
5ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport re
6ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport shlex
7ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport subprocess
8ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport sys
9ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport threading
10ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadimport time
11ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
12ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_COMPILATION = 'compile'
13ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_DISABLE_OVERLAYS = 'disable overlays'
14ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_ENABLE_MULTIPLE_OVERLAYS = 'enable multiple overlays'
15ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_ENABLE_SINGLE_OVERLAY = 'enable single overlay'
16ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_FILE_EXISTS_TEST = 'test (file exists)'
17ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_GREP_IDMAP_TEST = 'test (grep idmap)'
18ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_MD5_TEST = 'test (md5)'
19ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_IDMAP_PATH = 'idmap --path'
20ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_IDMAP_SCAN = 'idmap --scan'
21ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_INSTRUMENTATION = 'instrumentation'
22ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_INSTRUMENTATION_TEST = 'test (instrumentation)'
23ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_MKDIR = 'mkdir'
24ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_PUSH = 'push'
25ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_ROOT = 'root'
26ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_REMOUNT = 'remount'
27ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_RM = 'rm'
28ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_SETUP_IDMAP_PATH = 'setup idmap --path'
29ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_SETUP_IDMAP_SCAN = 'setup idmap --scan'
30ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_START = 'start'
31ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten KongstadTASK_STOP = 'stop'
32ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
33ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadadb = 'adb'
34ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
35ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _adb_shell(cmd):
36ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    argv = shlex.split(adb + " shell '" + cmd + "; echo $?'")
37ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    proc = subprocess.Popen(argv, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
38ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    (stdout, stderr) = proc.communicate()
39ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    (stdout, stderr) = (stdout.replace('\r', ''), stderr.replace('\r', ''))
40ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    tmp = stdout.rsplit('\n', 2)
41ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    if len(tmp) == 2:
42ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        stdout == ''
43ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        returncode = int(tmp[0])
44ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    else:
45ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        stdout = tmp[0] + '\n'
46ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        returncode = int(tmp[1])
47ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    return returncode, stdout, stderr
48ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
49ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass VerbosePrinter:
50ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    class Ticker(threading.Thread):
51ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        def _print(self):
52ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            s = '\r' + self.text + '[' + '.' * self.i + ' ' * (4 - self.i) + ']'
53ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            sys.stdout.write(s)
54ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            sys.stdout.flush()
55ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.i = (self.i + 1) % 5
56ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
57ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        def __init__(self, cond_var, text):
58ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            threading.Thread.__init__(self)
59ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.text = text
60ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.setDaemon(True)
61ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.cond_var = cond_var
62ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.running = False
63ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.i = 0
64ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self._print()
65ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.running = True
66ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
67ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        def run(self):
68ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.cond_var.acquire()
69ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            while True:
70ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                self.cond_var.wait(0.25)
71ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                running = self.running
72ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                if not running:
73ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                    break
74ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                self._print()
75ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.cond_var.release()
76ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
77ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        def stop(self):
78ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.cond_var.acquire()
79ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.running = False
80ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.cond_var.notify_all()
81ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.cond_var.release()
82ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
83ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def _start_ticker(self):
84ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.ticker = VerbosePrinter.Ticker(self.cond_var, self.text)
85ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.ticker.start()
86ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
87ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def _stop_ticker(self):
88ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.ticker.stop()
89ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.ticker.join()
90ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.ticker = None
91ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
92ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def _format_begin(self, type, name):
93ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        N = self.width - len(type) - len(' [    ] ')
94ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        fmt = '%%s %%-%ds ' % N
95ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return fmt % (type, name)
96ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
97ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, use_color):
98ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.cond_var = threading.Condition()
99ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.ticker = None
100ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if use_color:
101ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.color_RED = '\033[1;31m'
102ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.color_red = '\033[0;31m'
103ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.color_reset = '\033[0;37m'
104ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        else:
105ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.color_RED = ''
106ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.color_red = ''
107ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.color_reset = ''
108ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
109ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        argv = shlex.split('stty size') # get terminal width
110ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
111ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (stdout, stderr) = proc.communicate()
112ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if proc.returncode == 0:
113ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            (h, w) = stdout.split()
114ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.width = int(w)
115ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        else:
116ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            self.width = 72 # conservative guesstimate
117ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
118ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def begin(self, type, name):
119ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.text = self._format_begin(type, name)
120ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write(self.text + '[    ]')
121ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.flush()
122ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self._start_ticker()
123ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
124ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def end_pass(self, type, name):
125ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self._stop_ticker()
126ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write('\r' + self.text + '[ OK ]\n')
127ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.flush()
128ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
129ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def end_fail(self, type, name, msg):
130ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self._stop_ticker()
131ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write('\r' + self.color_RED + self.text + '[FAIL]\n')
132ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write(self.color_red)
133ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write(msg)
134ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write(self.color_reset)
135ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.flush()
136ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
137ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass QuietPrinter:
138ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def begin(self, type, name):
139ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        pass
140ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
141ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def end_pass(self, type, name):
142ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write('PASS ' + type + ' ' + name + '\n')
143ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.flush()
144ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
145ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def end_fail(self, type, name, msg):
146ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.write('FAIL ' + type + ' ' + name + '\n')
147ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        sys.stdout.flush()
148ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
149ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass CompilationTask:
150ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, makefile):
151ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.makefile = makefile
152ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
153ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
154ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_COMPILATION
155ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
156ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
157ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.makefile
158ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
159ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
160ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        os.putenv('ONE_SHOT_MAKEFILE', os.getcwd() + "/" + self.makefile)
161ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        argv = shlex.split('make -C "../../../../../" files')
162ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
163ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (stdout, stderr) = proc.communicate()
164ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return proc.returncode, stdout, stderr
165ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
166ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass InstrumentationTask:
167ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, instrumentation_class):
168ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.instrumentation_class = instrumentation_class
169ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
170ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
171ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_INSTRUMENTATION
172ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
173ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
174ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.instrumentation_class
175ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
176ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
177ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('am instrument -r -w -e class %s com.android.overlaytest/android.test.InstrumentationTestRunner' % self.instrumentation_class)
178ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
179ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass PushTask:
180ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, src, dest):
181ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.src = src
182ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.dest = dest
183ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
184ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
185ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_PUSH
186ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
187ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
188ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return "%s -> %s" % (self.src, self.dest)
189ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
190ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
191ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        src = os.getenv('OUT') + "/" + self.src
192ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        argv = shlex.split(adb + ' push %s %s' % (src, self.dest))
193ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
194ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (stdout, stderr) = proc.communicate()
195ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return proc.returncode, stdout, stderr
196ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
197ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass MkdirTask:
198ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, path):
199ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path = path
200ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
201ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
202ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_MKDIR
203ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
204ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
205ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.path
206ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
207ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
208ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('mkdir -p %s' % self.path)
209ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
210ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass RmTask:
211ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, path):
212ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path = path
213ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
214ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
215ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_RM
216ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
217ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
218ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.path
219ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
220ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
221ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        returncode, stdout, stderr = _adb_shell('ls %s' % self.path)
222ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if returncode != 0 and stdout.endswith(': No such file or directory\n'):
223ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return 0, "", ""
224ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('rm -r %s' % self.path)
225ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
226ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass IdmapPathTask:
227ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, path_target_apk, path_overlay_apk, path_idmap):
228ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path_target_apk = path_target_apk
229ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path_overlay_apk = path_overlay_apk
230ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path_idmap = path_idmap
231ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
232ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
233ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_IDMAP_PATH
234ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
235ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
236ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.path_idmap
237ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
238ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
239ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('su system idmap --path "%s" "%s" "%s"' % (self.path_target_apk, self.path_overlay_apk, self.path_idmap))
240ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
241ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass IdmapScanTask:
242ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, overlay_dir, target_pkg_name, target_pkg, idmap_dir, symlink_dir):
243ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.overlay_dir = overlay_dir
244ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.target_pkg_name = target_pkg_name
245ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.target_pkg = target_pkg
246ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.idmap_dir = idmap_dir
247ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.symlink_dir = symlink_dir
248ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
249ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
250ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_IDMAP_SCAN
251ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
252ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
253ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.target_pkg_name
254ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
255ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
256ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('su system idmap --scan "%s" "%s" "%s" "%s"' % (self.overlay_dir, self.target_pkg_name, self.target_pkg, self.idmap_dir))
257ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
258ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass FileExistsTest:
259ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, path):
260ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path = path
261ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
262ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
263ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_FILE_EXISTS_TEST
264ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
265ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
266ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.path
267ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
268ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
269ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('ls %s' % self.path)
270ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
271ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass GrepIdmapTest:
272ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, path_idmap, pattern, expected_n):
273ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path_idmap = path_idmap
274ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.pattern = pattern
275ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.expected_n = expected_n
276ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
277ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
278ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_GREP_IDMAP_TEST
279ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
280ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
281ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.pattern
282ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
283ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
284ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        returncode, stdout, stderr = _adb_shell('idmap --inspect %s' % self.path_idmap)
285ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if returncode != 0:
286ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return returncode, stdout, stderr
287ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        all_matches = re.findall('\s' + self.pattern + '$', stdout, flags=re.MULTILINE)
288ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if len(all_matches) != self.expected_n:
289ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return 1, 'pattern=%s idmap=%s expected=%d found=%d\n' % (self.pattern, self.path_idmap, self.expected_n, len(all_matches)), ''
290ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return 0, "", ""
291ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
292ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass Md5Test:
293ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, path, expected_content):
294ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.path = path
295ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.expected_md5 = hashlib.md5(expected_content).hexdigest()
296ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
297ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
298ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_MD5_TEST
299ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
300ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
301ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.path
302ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
303ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
304415fa1f5c0eab260211eb192629f61097ed059f3Stephen Smalley        returncode, stdout, stderr = _adb_shell('md5sum %s' % self.path)
305ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if returncode != 0:
306ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return returncode, stdout, stderr
307ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        actual_md5 = stdout.split()[0]
308ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if actual_md5 != self.expected_md5:
309ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return 1, 'expected %s, got %s\n' % (self.expected_md5, actual_md5), ''
310ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return 0, "", ""
311ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
312ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass StartTask:
313ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
314ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_START
315ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
316ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
317ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return ""
318ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
319ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
320ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (returncode, stdout, stderr) = _adb_shell('start')
321ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if returncode != 0:
322ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return returncode, stdout, stderr
323ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
324ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        while True:
325ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            (returncode, stdout, stderr) = _adb_shell('getprop dev.bootcomplete')
326ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            if returncode != 0:
327ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                return returncode, stdout, stderr
328ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            if stdout.strip() == "1":
329ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                break
330ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            time.sleep(0.5)
331ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
332ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return 0, "", ""
333ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
334ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass StopTask:
335ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
336ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_STOP
337ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
338ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
339ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return ""
340ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
341ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
342ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (returncode, stdout, stderr) = _adb_shell('stop')
343ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if returncode != 0:
344ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return returncode, stdout, stderr
345ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return _adb_shell('setprop dev.bootcomplete 0')
346ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
347ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass RootTask:
348ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
349ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_ROOT
350ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
351ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
352ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return ""
353ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
354ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
355ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (returncode, stdout, stderr) = _adb_shell('getprop service.adb.root 0')
356ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if returncode != 0:
357ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return returncode, stdout, stderr
358ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if stdout.strip() == '1': # already root
359ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return 0, "", ""
360ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
361ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        argv = shlex.split(adb + ' root')
362ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
363ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (stdout, stderr) = proc.communicate()
364ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if proc.returncode != 0:
365ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return proc.returncode, stdout, stderr
366ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
367ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        argv = shlex.split(adb + ' wait-for-device')
368ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
369ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (stdout, stderr) = proc.communicate()
370ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return proc.returncode, stdout, stderr
371ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
372ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass RemountTask:
373ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
374ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return TASK_REMOUNT
375ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
376ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
377ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return ""
378ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
379ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
380ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        argv = shlex.split(adb + ' remount')
381ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
382ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        (stdout, stderr) = proc.communicate()
383ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        # adb remount returns 0 even if the operation failed, so check stdout
384ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if stdout.startswith('remount failed:'):
385ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            return 1, stdout, stderr
386ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return proc.returncode, stdout, stderr
387ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
388ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstadclass CompoundTask:
389ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def __init__(self, type, tasks):
390ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.type = type
391ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        self.tasks = tasks
392ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
393ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_type(self):
394ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return self.type
395ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
396ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def get_name(self):
397ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return ""
398ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
399ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    def execute(self):
400ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        for t in self.tasks:
401ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            (returncode, stdout, stderr) = t.execute()
402ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            if returncode != 0:
403ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                return returncode, stdout, stderr
404ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        return 0, "", ""
405ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
406ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _create_disable_overlays_task():
407ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    tasks = [
408ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/vendor/overlay/framework_a.apk"),
409ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/vendor/overlay/framework_b.apk"),
410ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/data/resource-cache/vendor@overlay@framework_a.apk@idmap"),
411ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/data/resource-cache/vendor@overlay@framework_b.apk@idmap"),
412ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/vendor/overlay/app_a.apk"),
413ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/vendor/overlay/app_b.apk"),
414ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/data/resource-cache/vendor@overlay@app_a.apk@idmap"),
415ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask("/data/resource-cache/vendor@overlay@app_b.apk@idmap"),
416ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    ]
417ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    return CompoundTask(TASK_DISABLE_OVERLAYS, tasks)
418ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
419ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _create_enable_single_overlay_task():
420ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    tasks = [
421ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        _create_disable_overlays_task(),
422ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask('/system/vendor'),
423ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask('/vendor/overlay'),
42497b5df764344c32f8551483385ac4be742427580Mårten Kongstad        PushTask('/data/app/com.android.overlaytest.overlay/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_a.apk'),
42597b5df764344c32f8551483385ac4be742427580Mårten Kongstad        PushTask('/data/app/com.android.overlaytest.first_app_overlay/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
426ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    ]
427ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    return CompoundTask(TASK_ENABLE_SINGLE_OVERLAY, tasks)
428ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
429ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _create_enable_multiple_overlays_task():
430ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    tasks = [
431ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        _create_disable_overlays_task(),
432ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask('/system/vendor'),
433ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask('/vendor/overlay'),
434ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
43597b5df764344c32f8551483385ac4be742427580Mårten Kongstad        PushTask('/data/app/com.android.overlaytest.overlay/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_b.apk'),
43697b5df764344c32f8551483385ac4be742427580Mårten Kongstad        PushTask('/data/app/com.android.overlaytest.first_app_overlay/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
43797b5df764344c32f8551483385ac4be742427580Mårten Kongstad        PushTask('/data/app/com.android.overlaytest.second_app_overlay/com.android.overlaytest.second_app_overlay.apk', '/vendor/overlay/app_b.apk'),
438ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    ]
439ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    return CompoundTask(TASK_ENABLE_MULTIPLE_OVERLAYS, tasks)
440ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
441ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _create_setup_idmap_path_task(idmaps, symlinks):
442ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    tasks = [
443ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        _create_enable_single_overlay_task(),
444ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask(symlinks),
445ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask(idmaps),
446ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask(idmaps),
447ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask(symlinks),
448ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    ]
449ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    return CompoundTask(TASK_SETUP_IDMAP_PATH, tasks)
450ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
451ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _create_setup_idmap_scan_task(idmaps, symlinks):
452ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    tasks = [
453ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        _create_enable_single_overlay_task(),
454ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask(symlinks),
455ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        RmTask(idmaps),
456ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask(idmaps),
457ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        MkdirTask(symlinks),
458ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        _create_enable_multiple_overlays_task(),
459ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    ]
460ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    return CompoundTask(TASK_SETUP_IDMAP_SCAN, tasks)
461ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
462ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstaddef _handle_instrumentation_task_output(stdout, printer):
463ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    regex_status_code = re.compile(r'^INSTRUMENTATION_STATUS_CODE: -?(\d+)')
464ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    regex_name = re.compile(r'^INSTRUMENTATION_STATUS: test=(.*)')
465ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    regex_begin_stack = re.compile(r'^INSTRUMENTATION_STATUS: stack=(.*)')
466ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    regex_end_stack = re.compile(r'^$')
467ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
468ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    failed_tests = 0
469ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    current_test = None
470ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    current_stack = []
471ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    mode_stack = False
472ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad    for line in stdout.split("\n"):
473ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        line = line.rstrip() # strip \r from adb output
474ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        m = regex_status_code.match(line)
475ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if m:
476ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            c = int(m.group(1))
477ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            if c == 1:
478ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                printer.begin(TASK_INSTRUMENTATION_TEST, current_test)
479ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            elif c == 0:
480ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                printer.end_pass(TASK_INSTRUMENTATION_TEST, current_test)
481ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            else:
482ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                failed_tests += 1
483ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                current_stack.append("\n")
484ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                msg = "\n".join(current_stack)
485ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad                printer.end_fail(TASK_INSTRUMENTATION_TEST, current_test, msg.rstrip() + '\n')
486ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            continue
487ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
488ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        m = regex_name.match(line)
489ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if m:
490ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            current_test = m.group(1)
491ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            continue
492ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad
493ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        m = regex_begin_stack.match(line)
494ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad        if m:
495ad6ed950dbfa152c193dd7e49c369d9e831f1591Mårten Kongstad            mode_stack = True
496