blob: 47778a3b30e38d3884f00c64d83b5c2b3eade7a2 [file] [log] [blame]
Victor Hsieh2eba8922016-08-17 12:54:14 -07001# Copyright 2015 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
Victor Hsieh2593d862018-05-16 15:45:48 -07005import collections
Victor Hsieh2eba8922016-08-17 12:54:14 -07006import glob
7import logging
8import os
9import pipes
10import re
11import shutil
Luis Hector Chavez4443ced2018-06-22 10:58:12 -070012import socket
Victor Hsieh2eba8922016-08-17 12:54:14 -070013import sys
14import tempfile
Ben Lin474f1af2019-03-20 14:51:21 -070015import time
Victor Hsieh2eba8922016-08-17 12:54:14 -070016
17from autotest_lib.client.bin import test, utils
18from autotest_lib.client.common_lib import error
19from autotest_lib.client.common_lib.cros import chrome, arc_common
20
21_ADB_KEYS_PATH = '/tmp/adb_keys'
22_ADB_VENDOR_KEYS = 'ADB_VENDOR_KEYS'
yusukeseee955a2018-01-08 11:18:28 -080023_ANDROID_CONTAINER_PID_PATH = '/run/containers/android*/container.pid'
Dominik Laskowski16656d92018-01-04 19:01:35 -080024_ANDROID_DATA_ROOT_PATH = '/opt/google/containers/android/rootfs/android-data'
yusukesccf3be72018-01-10 09:00:51 -080025_ANDROID_CONTAINER_ROOT_PATH = '/opt/google/containers/android/rootfs'
Victor Hsieh2eba8922016-08-17 12:54:14 -070026_SCREENSHOT_DIR_PATH = '/var/log/arc-screenshots'
27_SCREENSHOT_BASENAME = 'arc-screenshot'
28_MAX_SCREENSHOT_NUM = 10
Luis Hector Chavez4443ced2018-06-22 10:58:12 -070029# This address should match the one present in
30# https://chromium.googlesource.com/chromiumos/overlays/chromiumos-overlay/+/master/chromeos-base/arc-sslh-init/files/sslh.conf
31_ADBD_ADDRESS = ('100.115.92.2', 5555)
Luis Hector Chavez51c63552018-03-08 09:03:23 -080032_ADBD_PID_PATH = '/run/arc/adbd.pid'
Mike Frysinger898bd552017-04-10 23:56:36 -040033_SDCARD_PID_PATH = '/run/arc/sdcard.pid'
Victor Hsieh2eba8922016-08-17 12:54:14 -070034_ANDROID_ADB_KEYS_PATH = '/data/misc/adb/adb_keys'
35_PROCESS_CHECK_INTERVAL_SECONDS = 1
36_WAIT_FOR_ADB_READY = 60
37_WAIT_FOR_ANDROID_PROCESS_SECONDS = 60
Ted Laide93c932017-09-05 12:36:20 +080038_PLAY_STORE_PKG = 'com.android.vending'
39_SETTINGS_PKG = 'com.android.settings'
Victor Hsieh2eba8922016-08-17 12:54:14 -070040
41
42def setup_adb_host():
43 """Setup ADB host keys.
44
Ilja H. Friedelce8ebd62017-07-11 13:55:49 -070045 This sets up the files and environment variables that wait_for_adb_ready()
46 needs"""
Victor Hsieh2eba8922016-08-17 12:54:14 -070047 if _ADB_VENDOR_KEYS in os.environ:
48 return
49 if not os.path.exists(_ADB_KEYS_PATH):
50 os.mkdir(_ADB_KEYS_PATH)
51 # adb expects $HOME to be writable.
52 os.environ['HOME'] = _ADB_KEYS_PATH
53
54 # Generate and save keys for adb if needed
55 key_path = os.path.join(_ADB_KEYS_PATH, 'test_key')
56 if not os.path.exists(key_path):
57 utils.system('adb keygen ' + pipes.quote(key_path))
58 os.environ[_ADB_VENDOR_KEYS] = key_path
59
60
Luis Hector Chavezfdf1cfa2018-04-09 09:44:24 -070061def adb_connect(attempts=1):
Victor Hsieh2eba8922016-08-17 12:54:14 -070062 """Attempt to connect ADB to the Android container.
63
64 Returns true if successful. Do not call this function directly. Call
Luis Hector Chavez3e6a9352018-05-17 14:09:11 -070065 wait_for_adb_ready() instead.
66 """
Luis Hector Chavezfdf1cfa2018-04-09 09:44:24 -070067 # Kill existing adb server every other invocation to ensure that a full
68 # reconnect is performed.
69 if attempts % 2 == 1:
70 utils.system('adb kill-server', ignore_status=True)
71
Ricky Zhou5c2745d2016-09-19 20:44:39 -070072 if utils.system('adb connect localhost:22', ignore_status=True) != 0:
73 return False
Victor Hsieh2eba8922016-08-17 12:54:14 -070074 return is_adb_connected()
75
76
77def is_adb_connected():
78 """Return true if adb is connected to the container."""
Ricky Zhou5c2745d2016-09-19 20:44:39 -070079 output = utils.system_output('adb get-state', ignore_status=True)
Victor Hsieh2eba8922016-08-17 12:54:14 -070080 logging.debug('adb get-state: %s', output)
81 return output.strip() == 'device'
82
83
Victor Hsieh4ed69e02017-06-20 13:09:40 -070084def _is_android_data_mounted():
85 """Return true if Android's /data is mounted with partial boot enabled."""
86 return _android_shell('getprop ro.data_mounted') == '1'
87
88
Victor Hsiehea585522017-09-20 11:12:15 -070089def get_zygote_type():
90 """Return zygote service type."""
91 return _android_shell('getprop ro.zygote')
92
93
Lloyd Pique647599f2017-10-19 17:12:10 -070094def get_sdk_version():
95 """Return the SDK level version for Android."""
96 return _android_shell('getprop ro.build.version.sdk')
97
98
99def get_product():
100 """Return the product string used for the Android build."""
101 return _android_shell('getprop ro.build.product')
102
103
Luis Hector Chavez4443ced2018-06-22 10:58:12 -0700104def _is_tcp_port_reachable(address):
105 """Return whether a TCP port described by |address| is reachable."""
106 try:
107 s = socket.create_connection(address)
108 s.close()
109 return True
110 except socket.error:
111 return False
112
113
Ben Lin474f1af2019-03-20 14:51:21 -0700114def _wait_for_data_mounted(timeout):
Victor Hsieh4ed69e02017-06-20 13:09:40 -0700115 utils.poll_for_condition(
116 condition=_is_android_data_mounted,
117 desc='Wait for /data mounted',
118 timeout=timeout,
119 sleep_interval=_PROCESS_CHECK_INTERVAL_SECONDS)
120
121
Victor Hsieh2eba8922016-08-17 12:54:14 -0700122def wait_for_adb_ready(timeout=_WAIT_FOR_ADB_READY):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800123 """Wait for the ADB client to connect to the ARC container.
124
125 @param timeout: Timeout in seconds.
126 """
yusukes1c5fdc92018-05-03 13:42:11 -0700127 # Although adbd is started at login screen, we still need /data to be
128 # mounted to set up key-based authentication. /data should be mounted
129 # once the user has logged in.
Ben Lin474f1af2019-03-20 14:51:21 -0700130 start_time = time.time()
131 _wait_for_data_mounted(timeout)
132 timeout -= (time.time() - start_time)
133 start_time = time.time()
134 arc_common.wait_for_android_boot(timeout)
135 timeout -= (time.time() - start_time)
Victor Hsieh4ed69e02017-06-20 13:09:40 -0700136
Victor Hsieh2eba8922016-08-17 12:54:14 -0700137 setup_adb_host()
138 if is_adb_connected():
Ricardo Quesadaa55d47e2018-02-15 12:53:42 -0800139 return
Victor Hsieh2eba8922016-08-17 12:54:14 -0700140
141 # Push keys for adb.
142 pubkey_path = os.environ[_ADB_VENDOR_KEYS] + '.pub'
143 with open(pubkey_path, 'r') as f:
144 _write_android_file(_ANDROID_ADB_KEYS_PATH, f.read())
Luis Hector Chavezb2e7cd72018-04-24 15:06:35 -0700145 _android_shell('chown shell ' + pipes.quote(_ANDROID_ADB_KEYS_PATH))
Victor Hsieh2eba8922016-08-17 12:54:14 -0700146 _android_shell('restorecon ' + pipes.quote(_ANDROID_ADB_KEYS_PATH))
147
Luis Hector Chavezb2e7cd72018-04-24 15:06:35 -0700148 # This starts adbd, restarting it if needed so it can read the updated key.
149 _android_shell('setprop sys.usb.config mtp')
Victor Hsieh2eba8922016-08-17 12:54:14 -0700150 _android_shell('setprop sys.usb.config mtp,adb')
151
Luis Hector Chavez4443ced2018-06-22 10:58:12 -0700152 exception = error.TestFail('Failed to connect to adb in %d seconds.' % timeout)
Luis Hector Chavezfdf1cfa2018-04-09 09:44:24 -0700153
Ricardo Quesada02242792018-05-08 12:57:57 -0700154 # Keeps track of how many times adb has attempted to establish a
155 # connection.
Luis Hector Chavezfdf1cfa2018-04-09 09:44:24 -0700156 def _adb_connect_wrapper():
157 _adb_connect_wrapper.attempts += 1
158 return adb_connect(_adb_connect_wrapper.attempts)
159 _adb_connect_wrapper.attempts = 0
Luis Hector Chavez3e6a9352018-05-17 14:09:11 -0700160 try:
161 utils.poll_for_condition(_adb_connect_wrapper,
162 exception,
163 timeout)
Luis Hector Chavez4443ced2018-06-22 10:58:12 -0700164 except (utils.TimeoutError, error.TestFail):
165 # The operation has failed, but let's try to clarify the failure to
166 # avoid shifting blame to adb.
167
168 # First, collect some information and log it.
169 arc_alive = is_android_container_alive()
170 arc_booted = _android_shell('getprop sys.boot_completed',
171 ignore_status=True)
172 arc_system_events = _android_shell(
173 'logcat -d -b events *:S arc_system_event', ignore_status=True)
174 adbd_pid = _android_shell('pidof -s adbd', ignore_status=True)
175 adbd_port_reachable = _is_tcp_port_reachable(_ADBD_ADDRESS)
176 adb_state = utils.system_output('adb get-state', ignore_status=True)
177 logging.debug('ARC alive: %s', arc_alive)
178 logging.debug('ARC booted: %s', arc_booted)
179 logging.debug('ARC system events: %s', arc_system_events)
180 logging.debug('adbd process: %s', adbd_pid)
181 logging.debug('adbd port reachable: %s', adbd_port_reachable)
182 logging.debug('adb state: %s', adb_state)
183
184 # Now go through the usual suspects and raise nicer errors to make the
185 # actual failure clearer.
186 if not arc_alive:
187 raise error.TestFail('ARC is not alive.')
188 if not adbd_pid:
189 raise error.TestFail('adbd is not running.')
190 if arc_booted != '1':
191 raise error.TestFail('ARC did not finish booting.')
192 if not adbd_port_reachable:
193 raise error.TestFail('adbd TCP port is not reachable.')
194
195 # We exhausted all possibilities. Fall back to printing the generic
196 # error.
Luis Hector Chavez3e6a9352018-05-17 14:09:11 -0700197 raise
Victor Hsieh2eba8922016-08-17 12:54:14 -0700198
199
Cheng-Yi Chiang21cf23a2016-09-10 01:31:31 +0800200def grant_permissions(package, permissions):
201 """Grants permissions to a package.
202
203 @param package: Package name.
204 @param permissions: A list of permissions.
205
206 """
207 for permission in permissions:
208 adb_shell('pm grant %s android.permission.%s' % (
209 pipes.quote(package), pipes.quote(permission)))
210
211
Chung-yih Wang57761dd2017-07-03 05:22:14 +0000212def adb_cmd(cmd, **kwargs):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800213 """Executed cmd using adb. Must wait for adb ready.
214
215 @param cmd: Command to run.
216 """
Lloyd Pique9368a8a2018-04-27 13:35:40 -0700217 # TODO(b/79122489) - Assert if cmd == 'root'
Victor Hsieh2eba8922016-08-17 12:54:14 -0700218 wait_for_adb_ready()
Chung-yih Wang57761dd2017-07-03 05:22:14 +0000219 return utils.system_output('adb %s' % cmd, **kwargs)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700220
221
222def adb_shell(cmd, **kwargs):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800223 """Executed shell command with adb.
224
225 @param cmd: Command to run.
226 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700227 output = adb_cmd('shell %s' % pipes.quote(cmd), **kwargs)
228 # Some android commands include a trailing CRLF in their output.
229 if kwargs.pop('strip_trailing_whitespace', True):
Ricardo Quesadaa55d47e2018-02-15 12:53:42 -0800230 output = output.rstrip()
Victor Hsieh2eba8922016-08-17 12:54:14 -0700231 return output
232
233
Lloyd Pique9faedd02018-05-01 12:21:49 -0700234def adb_install(apk, auto_grant_permissions=True):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800235 """Install an apk into container. You must connect first.
236
237 @param apk: Package to install.
Lloyd Pique9faedd02018-05-01 12:21:49 -0700238 @param auto_grant_permissions: Set to false to not automatically grant all
239 permissions. Most tests should not care.
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800240 """
Lloyd Pique9faedd02018-05-01 12:21:49 -0700241 flags = '-g' if auto_grant_permissions else ''
Yuichiro Hanada88036ac2018-11-20 14:58:52 +0900242 return adb_cmd('install -r -t %s %s' % (flags, apk), timeout=60*5)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700243
244
245def adb_uninstall(apk):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800246 """Remove an apk from container. You must connect first.
247
248 @param apk: Package to uninstall.
249 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700250 return adb_cmd('uninstall %s' % apk)
251
252
253def adb_reboot():
Victor Hsieh8bae7782018-05-07 14:27:03 -0700254 """Reboots the container and block until container pid is gone.
255
256 You must connect first.
257 """
258 old_pid = get_container_pid()
Risan5417a382018-11-14 09:54:24 +0900259 logging.info('Trying to reboot PID:%s', old_pid)
Victor Hsieh8bae7782018-05-07 14:27:03 -0700260 adb_cmd('reboot', ignore_status=True)
261 # Ensure that the old container is no longer booted
262 utils.poll_for_condition(
263 lambda: not utils.pid_is_alive(int(old_pid)), timeout=10)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700264
265
Lloyd Pique9368a8a2018-04-27 13:35:40 -0700266# This adb_root() function is deceiving in that it works just fine on debug
267# builds of ARC (user-debug, eng). However "adb root" does not work on user
268# builds as run by the autotest machines when testing prerelease images. In fact
269# it will silently fail. You will need to find another way to do do what you
270# need to do as root.
271#
272# TODO(b/79122489) - Remove this function.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700273def adb_root():
274 """Restart adbd with root permission."""
Lloyd Pique9368a8a2018-04-27 13:35:40 -0700275
Victor Hsieh2eba8922016-08-17 12:54:14 -0700276 adb_cmd('root')
277
278
279def get_container_root():
yusukese1140312018-01-09 13:40:59 -0800280 """Returns path to Android container root directory."""
yusukes19510e72018-02-09 19:26:13 -0800281 return _ANDROID_CONTAINER_ROOT_PATH
yusukese1140312018-01-09 13:40:59 -0800282
283
284def get_container_pid_path():
285 """Returns the container's PID file path.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700286
287 Raises:
yusukese1140312018-01-09 13:40:59 -0800288 TestError if no PID file is found, or more than one files are found.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700289 """
yusukes19510e72018-02-09 19:26:13 -0800290 # Find the PID file rather than the android-XXXXXX/ directory to ignore
291 # stale and empty android-XXXXXX/ directories when they exist.
Yusuke Sato55a81002017-07-07 15:43:31 +0900292 arc_container_pid_files = glob.glob(_ANDROID_CONTAINER_PID_PATH)
293
294 if len(arc_container_pid_files) == 0:
yusukese1140312018-01-09 13:40:59 -0800295 raise error.TestError('Android container.pid not available')
Yusuke Sato55a81002017-07-07 15:43:31 +0900296
297 if len(arc_container_pid_files) > 1:
Ricardo Quesada02242792018-05-08 12:57:57 -0700298 raise error.TestError(
299 'Multiple Android container.pid files found: %r. '
300 'Reboot your DUT to recover.' % (arc_container_pid_files))
Yusuke Sato55a81002017-07-07 15:43:31 +0900301
yusukese1140312018-01-09 13:40:59 -0800302 return arc_container_pid_files[0]
Victor Hsieh2eba8922016-08-17 12:54:14 -0700303
304
Dominik Laskowski16656d92018-01-04 19:01:35 -0800305def get_android_data_root():
306 """Returns path to Chrome OS directory that bind-mounts Android's /data."""
307 return _ANDROID_DATA_ROOT_PATH
308
309
Victor Hsieh2eba8922016-08-17 12:54:14 -0700310def get_job_pid(job_name):
311 """Returns the PID of an upstart job."""
312 status = utils.system_output('status %s' % job_name)
313 match = re.match(r'^%s start/running, process (\d+)$' % job_name,
314 status)
315 if not match:
316 raise error.TestError('Unexpected status: "%s"' % status)
317 return match.group(1)
318
319
320def get_container_pid():
321 """Returns the PID of the container."""
yusukese1140312018-01-09 13:40:59 -0800322 return utils.read_one_line(get_container_pid_path())
Victor Hsieh2eba8922016-08-17 12:54:14 -0700323
324
Luis Hector Chavez51c63552018-03-08 09:03:23 -0800325def get_adbd_pid():
326 """Returns the PID of the adbd proxy container."""
327 if not os.path.exists(_ADBD_PID_PATH):
328 # The adbd proxy does not run on all boards.
329 return None
330 return utils.read_one_line(_ADBD_PID_PATH)
331
332
Victor Hsieh2eba8922016-08-17 12:54:14 -0700333def get_sdcard_pid():
334 """Returns the PID of the sdcard container."""
335 return utils.read_one_line(_SDCARD_PID_PATH)
336
337
Satoshi Niwa36d99c22019-02-15 13:18:21 +0900338def get_mount_passthrough_pid_list():
339 """Returns PIDs of ARC mount-passthrough daemon jobs."""
340 JOB_NAMES = [ 'arc-myfiles', 'arc-myfiles-default',
341 'arc-myfiles-read', 'arc-myfiles-write',
342 'arc-removable-media', 'arc-removable-media-default',
343 'arc-removable-media-read', 'arc-removable-media-write' ]
344 pid_list = []
345 for job_name in JOB_NAMES:
346 try:
Ereth McKnight-MacNeild16ff732019-04-01 16:37:31 -0700347 pid = get_job_pid(job_name)
Satoshi Niwa36d99c22019-02-15 13:18:21 +0900348 pid_list.append(pid)
349 except Exception, e:
350 logging.warning('Failed to find PID for %s : %s', job_name, e)
351 continue
Risan5417a382018-11-14 09:54:24 +0900352
Satoshi Niwa36d99c22019-02-15 13:18:21 +0900353 return pid_list
Risan5417a382018-11-14 09:54:24 +0900354
355
Victor Hsieh2eba8922016-08-17 12:54:14 -0700356def get_obb_mounter_pid():
357 """Returns the PID of the OBB mounter."""
358 return utils.system_output('pgrep -f -u root ^/usr/bin/arc-obb-mounter')
359
360
Victor Hsieh2eba8922016-08-17 12:54:14 -0700361def is_android_process_running(process_name):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800362 """Return whether Android has completed booting.
363
364 @param process_name: Process name.
365 """
Shao-Chuan Lee918c2952019-04-18 15:17:26 +0900366 output = adb_shell('pgrep -c -f %s' % pipes.quote(process_name),
367 ignore_status=True)
Luis Hector Chavez066c89e2018-02-02 14:24:35 -0800368 return int(output) > 0
Victor Hsieh2eba8922016-08-17 12:54:14 -0700369
370
Chen-Hao Chang@google.com1d6f3b42016-09-26 15:17:57 +0800371def check_android_file_exists(filename):
372 """Checks whether the given file exists in the Android filesystem
373
374 @param filename: File to check.
375 """
Shao-Chuan Lee918c2952019-04-18 15:17:26 +0900376 return adb_shell(
377 'test -e {} && echo FileExists'.format(pipes.quote(filename)),
378 ignore_status=True).find("FileExists") >= 0
Chen-Hao Chang@google.com1d6f3b42016-09-26 15:17:57 +0800379
380
Victor Hsieh2eba8922016-08-17 12:54:14 -0700381def read_android_file(filename):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800382 """Reads a file in Android filesystem.
383
384 @param filename: File to read.
385 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700386 with tempfile.NamedTemporaryFile() as tmpfile:
Ilja H. Friedelce8ebd62017-07-11 13:55:49 -0700387 adb_cmd('pull %s %s' % (pipes.quote(filename),
388 pipes.quote(tmpfile.name)))
Victor Hsieh2eba8922016-08-17 12:54:14 -0700389 with open(tmpfile.name) as f:
390 return f.read()
391
392 return None
393
394
395def write_android_file(filename, data):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800396 """Writes to a file in Android filesystem.
397
398 @param filename: File to write.
399 @param data: Data to write.
400 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700401 with tempfile.NamedTemporaryFile() as tmpfile:
402 tmpfile.write(data)
403 tmpfile.flush()
404
Ilja H. Friedelce8ebd62017-07-11 13:55:49 -0700405 adb_cmd('push %s %s' % (pipes.quote(tmpfile.name),
406 pipes.quote(filename)))
Victor Hsieh2eba8922016-08-17 12:54:14 -0700407
408
409def _write_android_file(filename, data):
410 """Writes to a file in Android filesystem.
411
412 This is an internal function used to bootstrap adb.
413 Tests should use write_android_file instead.
414 """
415 android_cmd = 'cat > %s' % pipes.quote(filename)
416 cros_cmd = 'android-sh -c %s' % pipes.quote(android_cmd)
417 utils.run(cros_cmd, stdin=data)
418
419
Victor Hsieh2593d862018-05-16 15:45:48 -0700420def get_android_file_stats(filename):
421 """Returns an object of file stats for an Android file.
422
423 The returned object supported limited attributes, but can be easily extended
424 if needed. Note that the value are all string.
425
426 This uses _android_shell to run as root, so that it can access to all files
427 inside the container. On non-debuggable build, adb shell is not rootable.
428 """
429 mapping = {
430 '%a': 'mode',
431 '%g': 'gid',
432 '%h': 'nlink',
433 '%u': 'uid',
434 }
435 output = _android_shell(
436 'stat -c "%s" %s' % (' '.join(mapping.keys()), pipes.quote(filename)))
437 stats = output.split(' ')
438 if len(stats) != len(mapping):
439 raise error.TestError('Unexpected output from stat: %s' % output)
440 _Stats = collections.namedtuple('_Stats', mapping.values())
441 return _Stats(*stats)
442
443
Victor Hsieh2eba8922016-08-17 12:54:14 -0700444def remove_android_file(filename):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800445 """Removes a file in Android filesystem.
446
447 @param filename: File to remove.
448 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700449 adb_shell('rm -f %s' % pipes.quote(filename))
450
451
452def wait_for_android_boot(timeout=None):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800453 """Sleep until Android has completed booting or timeout occurs.
454
455 @param timeout: Timeout in seconds.
456 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700457 arc_common.wait_for_android_boot(timeout)
458
459
460def wait_for_android_process(process_name,
461 timeout=_WAIT_FOR_ANDROID_PROCESS_SECONDS):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800462 """Sleep until an Android process is running or timeout occurs.
463
464 @param process_name: Process name.
465 @param timeout: Timeout in seconds.
466 """
Victor Hsieh2eba8922016-08-17 12:54:14 -0700467 condition = lambda: is_android_process_running(process_name)
468 utils.poll_for_condition(condition=condition,
469 desc='%s is running' % process_name,
470 timeout=timeout,
471 sleep_interval=_PROCESS_CHECK_INTERVAL_SECONDS)
472
473
474def _android_shell(cmd, **kwargs):
475 """Execute cmd instead the Android container.
476
Ricardo Quesadaa55d47e2018-02-15 12:53:42 -0800477 This function is strictly for internal use only, as commands do not run in
478 a fully consistent Android environment. Prefer adb_shell instead.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700479 """
480 return utils.system_output('android-sh -c {}'.format(pipes.quote(cmd)),
481 **kwargs)
482
483
484def is_android_container_alive():
485 """Check if android container is alive."""
486 try:
487 container_pid = get_container_pid()
Yusuke Sato55a81002017-07-07 15:43:31 +0900488 except Exception, e:
489 logging.error('is_android_container_alive failed: %r', e)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700490 return False
491 return utils.pid_is_alive(int(container_pid))
492
493
Ted Laide93c932017-09-05 12:36:20 +0800494def _is_in_installed_packages_list(package, option=None):
495 """Check if a package is in the list returned by pm list packages.
496
497 adb must be ready.
498
499 @param package: Package in request.
500 @param option: An option for the command adb shell pm list packages.
501 Valid values include '-s', '-3', '-d', and '-e'.
502 """
503 command = 'pm list packages'
504 if option:
505 command += ' ' + option
506 packages = adb_shell(command).splitlines()
507 package_entry = 'package:' + package
Ricardo Quesada02242792018-05-08 12:57:57 -0700508 ret = package_entry in packages
509
Ricardo Quesada02242792018-05-08 12:57:57 -0700510 if not ret:
Risan5417a382018-11-14 09:54:24 +0900511 logging.info('Could not find "%s" in %s',
Cici Ruanbed8aa62018-11-27 19:31:33 -0800512 package_entry, str(packages))
Ricardo Quesada02242792018-05-08 12:57:57 -0700513 return ret
Ted Laide93c932017-09-05 12:36:20 +0800514
515
Victor Hsieh2eba8922016-08-17 12:54:14 -0700516def is_package_installed(package):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800517 """Check if a package is installed. adb must be ready.
518
519 @param package: Package in request.
520 """
Ted Laide93c932017-09-05 12:36:20 +0800521 return _is_in_installed_packages_list(package)
522
523
524def is_package_disabled(package):
525 """Check if an installed package is disabled. adb must be ready.
526
527 @param package: Package in request.
528 """
529 return _is_in_installed_packages_list(package, '-d')
Victor Hsieh2eba8922016-08-17 12:54:14 -0700530
531
Victor Hsieh189690b2018-05-15 14:04:05 -0700532def get_package_install_path(package):
533 """Returns the apk install location of the given package."""
534 output = adb_shell('pm path {}'.format(pipes.quote(package)))
535 return output.split(':')[1]
536
537
Victor Hsieh2eba8922016-08-17 12:54:14 -0700538def _before_iteration_hook(obj):
539 """Executed by parent class before every iteration.
540
541 This function resets the run_once_finished flag before every iteration
542 so we can detect failure on every single iteration.
543
544 Args:
545 obj: the test itself
546 """
547 obj.run_once_finished = False
548
549
550def _after_iteration_hook(obj):
551 """Executed by parent class after every iteration.
552
553 The parent class will handle exceptions and failures in the run and will
554 always call this hook afterwards. Take a screenshot if the run has not
555 been marked as finished (i.e. there was a failure/exception).
556
557 Args:
558 obj: the test itself
559 """
560 if not obj.run_once_finished:
Ted Lai4656ea82017-09-19 17:03:36 +0800561 if is_adb_connected():
562 logging.debug('Recent activities dump:\n%s',
563 adb_shell('dumpsys activity recents'))
Victor Hsieh2eba8922016-08-17 12:54:14 -0700564 if not os.path.exists(_SCREENSHOT_DIR_PATH):
565 os.mkdir(_SCREENSHOT_DIR_PATH, 0755)
566 obj.num_screenshots += 1
567 if obj.num_screenshots <= _MAX_SCREENSHOT_NUM:
568 logging.warning('Iteration %d failed, taking a screenshot.',
569 obj.iteration)
Ilja H. Friedelce8ebd62017-07-11 13:55:49 -0700570 try:
Shuhei Takahashi0192b772018-06-26 13:38:26 +0900571 utils.run('screenshot "{}/{}_iter{}.png"'.format(
572 _SCREENSHOT_DIR_PATH, _SCREENSHOT_BASENAME, obj.iteration))
Hidehiko Abe19846502017-08-03 15:38:15 +0900573 except Exception as e:
574 logging.warning('Unable to capture screenshot. %s', e)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700575 else:
576 logging.warning('Too many failures, no screenshot taken')
577
578
Chen-Hao Chang@google.com1d6f3b42016-09-26 15:17:57 +0800579def send_keycode(keycode):
580 """Sends the given keycode to the container
581
582 @param keycode: keycode to send.
583 """
584 adb_shell('input keyevent {}'.format(keycode))
585
586
Shuhei Takahashi8f8524d2017-01-31 14:22:53 +0900587def get_android_sdk_version():
588 """Returns the Android SDK version.
589
590 This function can be called before Android container boots.
591 """
592 with open('/etc/lsb-release') as f:
593 values = dict(line.split('=', 1) for line in f.read().splitlines())
594 try:
595 return int(values['CHROMEOS_ARC_ANDROID_SDK_VERSION'])
596 except (KeyError, ValueError):
597 raise error.TestError('Could not determine Android SDK version')
598
599
Ricardo Quesadaa55d47e2018-02-15 12:53:42 -0800600def set_device_mode(device_mode, use_fake_sensor_with_lifetime_secs=0):
601 """Sets the device in either Clamshell or Tablet mode.
602
603 "inject_powerd_input_event" might fail if the DUT does not support Tablet
604 mode, and it will raise an |error.CmdError| exception. To prevent that, use
605 the |use_fake_sensor_with_lifetime_secs| parameter.
606
607 @param device_mode: string with either 'clamshell' or 'tablet'
608 @param use_fake_sensor_with_lifetime_secs: if > 0, it will create the
609 input device with the given lifetime in seconds
610 @raise ValueError: if passed invalid parameters
611 @raise error.CmdError: if inject_powerd_input_event fails
612 """
613 valid_value = ('tablet', 'clamshell')
614 if device_mode not in valid_value:
615 raise ValueError('Invalid device_mode parameter: %s' % device_mode)
616
617 value = 1 if device_mode == 'tablet' else 0
618
619 args = ['--code=tablet', '--value=%d' % value]
620
621 if use_fake_sensor_with_lifetime_secs > 0:
622 args.extend(['--create_dev', '--dev_lifetime=%d' %
623 use_fake_sensor_with_lifetime_secs])
Ricardo Quesadaf507b822018-10-03 15:51:04 -0700624
625 try:
626 utils.run('inject_powerd_input_event', args=args)
627 except error.CmdError as err:
628 # TODO: Fragile code ahead. Correct way to do it is to check
629 # if device is already in desired mode, and do nothing if so.
630 # ATM we don't have a way to check current device mode.
631
632 # Assuming that CmdError means that device does not support
633 # --code=tablet parameter, meaning that device only supports clamshell
634 # mode.
635 if device_mode == 'clamshell' and \
636 use_fake_sensor_with_lifetime_secs == 0:
637 return
638 raise err
Ricardo Quesadaa55d47e2018-02-15 12:53:42 -0800639
640
Lloyd Pique5767c452018-07-11 18:25:43 -0700641def wait_for_userspace_ready():
642 """Waits for userspace apps to be launchable.
643
644 Launches and then closes Android settings as a way to ensure all basic
645 services are ready. This goes a bit beyond waiting for boot-up to complete,
646 as being able to launch an activity requires more of the framework to have
647 started. The boot-complete signal happens fairly early, and the framework
648 system server is still starting services. By waiting for ActivityManager to
649 respond, we automatically wait on more services to be ready.
650 """
651 output = adb_shell('am start -W -a android.settings.SETTINGS')
652 if not output.endswith('Complete'):
653 logging.debug('Output was: %s', output)
654 raise error.TestError('Could not launch SETTINGS')
655 adb_shell('am force-stop com.android.settings')
656
657
Victor Hsieh2eba8922016-08-17 12:54:14 -0700658class ArcTest(test.test):
659 """ Base class of ARC Test.
660
661 This class could be used as super class of an ARC test for saving
662 redundant codes for container bringup, autotest-dep package(s) including
663 uiautomator setup if required, and apks install/remove during
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800664 arc_setup/arc_teardown, respectively. By default arc_setup() is called in
Ricardo Quesada02242792018-05-08 12:57:57 -0700665 initialize() after Android have been brought up. It could also be
666 overridden to perform non-default tasks. For example, a simple
667 ArcHelloWorldTest can be just implemented with print 'HelloWorld' in its
668 run_once() and no other functions are required. We could expect
669 ArcHelloWorldTest would bring up browser and wait for container up, then
670 print 'Hello World', and shutdown browser after. As a precaution, if you
671 overwrite initialize(), arc_setup(), or cleanup() function(s) in ARC test,
672 remember to call the corresponding function(s) in this base class as well.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700673 """
674 version = 1
675 _PKG_UIAUTOMATOR = 'uiautomator'
676 _FULL_PKG_NAME_UIAUTOMATOR = 'com.github.uiautomator'
677
678 def __init__(self, *args, **kwargs):
679 """Initialize flag setting."""
680 super(ArcTest, self).__init__(*args, **kwargs)
681 self.initialized = False
682 # Set the flag run_once_finished to detect if a test is executed
683 # successfully without any exception thrown. Otherwise, generate
684 # a screenshot in /var/log for debugging.
685 self.run_once_finished = False
686 self.logcat_proc = None
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800687 self.dep_package = None
688 self.apks = None
689 self.full_pkg_names = []
690 self.uiautomator = False
Ted Laide93c932017-09-05 12:36:20 +0800691 self._should_reenable_play_store = False
Chen-Hao Chang@google.com1d6f3b42016-09-26 15:17:57 +0800692 self._chrome = None
Victor Hsieh2eba8922016-08-17 12:54:14 -0700693 if os.path.exists(_SCREENSHOT_DIR_PATH):
694 shutil.rmtree(_SCREENSHOT_DIR_PATH)
695 self.register_before_iteration_hook(_before_iteration_hook)
696 self.register_after_iteration_hook(_after_iteration_hook)
697 # Keep track of the number of debug screenshots taken and keep the
698 # total number sane to avoid issues.
699 self.num_screenshots = 0
700
Ted Lai05fe2302017-09-01 11:35:07 +0800701 def initialize(self, extension_path=None, username=None, password=None,
Victor Hsieh2eba8922016-08-17 12:54:14 -0700702 arc_mode=arc_common.ARC_MODE_ENABLED, **chrome_kargs):
703 """Log in to a test account."""
704 extension_paths = [extension_path] if extension_path else []
705 self._chrome = chrome.Chrome(extension_paths=extension_paths,
Ted Lai05fe2302017-09-01 11:35:07 +0800706 username=username,
707 password=password,
Victor Hsieh2eba8922016-08-17 12:54:14 -0700708 arc_mode=arc_mode,
709 **chrome_kargs)
710 if extension_path:
711 self._extension = self._chrome.get_extension(extension_path)
712 else:
713 self._extension = None
714 # With ARC enabled, Chrome will wait until container to boot up
715 # before returning here, see chrome.py.
716 self.initialized = True
Victor Hsieh2eba8922016-08-17 12:54:14 -0700717 try:
718 if is_android_container_alive():
719 self.arc_setup()
720 else:
721 logging.error('Container is alive?')
722 except Exception as err:
Victor Hsieh2eba8922016-08-17 12:54:14 -0700723 raise error.TestFail(err)
724
725 def after_run_once(self):
726 """Executed after run_once() only if there were no errors.
727
728 This function marks the run as finished with a flag. If there was a
729 failure the flag won't be set and the failure can then be detected by
730 testing the run_once_finished flag.
731 """
732 logging.info('After run_once')
733 self.run_once_finished = True
734
735 def cleanup(self):
736 """Log out of Chrome."""
737 if not self.initialized:
738 logging.info('Skipping ARC cleanup: not initialized')
739 return
740 logging.info('Starting ARC cleanup')
741 try:
742 if is_android_container_alive():
743 self.arc_teardown()
744 except Exception as err:
745 raise error.TestFail(err)
746 finally:
747 try:
Luis Hector Chavezb740ab92018-05-17 14:10:51 -0700748 if self.logcat_proc:
749 self.logcat_proc.close()
Victor Hsieh2eba8922016-08-17 12:54:14 -0700750 finally:
Chen-Hao Chang@google.com1d6f3b42016-09-26 15:17:57 +0800751 if self._chrome is not None:
752 self._chrome.close()
Victor Hsieh2eba8922016-08-17 12:54:14 -0700753
Ben Cheng42b86892017-10-25 17:22:25 +0800754 def _install_apks(self, dep_package, apks, full_pkg_names):
755 """"Install apks fetched from the specified package folder.
756
757 @param dep_package: A dependent package directory
758 @param apks: List of apk names to be installed
759 @param full_pkg_names: List of packages to be uninstalled at teardown
760 """
761 apk_path = os.path.join(self.autodir, 'deps', dep_package)
762 if apks:
763 for apk in apks:
764 logging.info('Installing %s', apk)
Ricardo Quesada02242792018-05-08 12:57:57 -0700765 out = adb_install('%s/%s' % (apk_path, apk))
Risan5417a382018-11-14 09:54:24 +0900766 logging.info('Install apk output: %s', str(out))
Ben Cheng42b86892017-10-25 17:22:25 +0800767 # Verify if package(s) are installed correctly
768 if not full_pkg_names:
769 raise error.TestError('Package names of apks expected')
770 for pkg in full_pkg_names:
771 logging.info('Check if %s is installed', pkg)
772 if not is_package_installed(pkg):
773 raise error.TestError('Package %s not found' % pkg)
774 # Make sure full_pkg_names contains installed packages only
775 # so arc_teardown() knows what packages to uninstall.
776 self.full_pkg_names.append(pkg)
777
778 def _count_nested_array_level(self, array):
779 """Count the level of a nested array."""
780 if isinstance(array, list):
781 return 1 + self._count_nested_array_level(array[0])
782 return 0
783
784 def _fix_nested_array_level(self, var_name, expected_level, array):
785 """Enclose array one level deeper if needed."""
786 level = self._count_nested_array_level(array)
787 if level == expected_level:
788 return array
789 if level == expected_level - 1:
790 return [array]
791
792 logging.error("Variable %s nested level is not fixable: "
793 "Expecting %d, seeing %d",
Ricardo Quesadaa55d47e2018-02-15 12:53:42 -0800794 var_name, expected_level, level)
Ben Cheng42b86892017-10-25 17:22:25 +0800795 raise error.TestError('Format error with variable %s' % var_name)
796
797 def arc_setup(self, dep_packages=None, apks=None, full_pkg_names=None,
Ted Laide93c932017-09-05 12:36:20 +0800798 uiautomator=False, block_outbound=False,
799 disable_play_store=False):
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800800 """ARC test setup: Setup dependencies and install apks.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700801
802 This function disables package verification and enables non-market
803 APK installation. Then, it installs specified APK(s) and uiautomator
804 package and path if required in a test.
805
Ben Cheng42b86892017-10-25 17:22:25 +0800806 @param dep_packages: Array of package names of autotest_deps APK
807 packages.
808 @param apks: Array of APK name arrays to be installed in dep_package.
809 @param full_pkg_names: Array of full package name arrays to be removed
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800810 in teardown.
811 @param uiautomator: uiautomator python package is required or not.
Chung-yih Wanga67fce02017-03-28 16:19:17 +0800812 @param block_outbound: block outbound network traffic during a test.
Ted Laide93c932017-09-05 12:36:20 +0800813 @param disable_play_store: Set this to True if you want to prevent
814 GMS Core from updating.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700815 """
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800816 if not self.initialized:
817 logging.info('Skipping ARC setup: not initialized')
818 return
819 logging.info('Starting ARC setup')
Ben Cheng42b86892017-10-25 17:22:25 +0800820
821 # Sample parameters for multi-deps setup after fixup (if needed):
822 # dep_packages: ['Dep1-apk', 'Dep2-apk']
823 # apks: [['com.dep1.arch1.apk', 'com.dep2.arch2.apk'], ['com.dep2.apk']
824 # full_pkg_nmes: [['com.dep1.app'], ['com.dep2.app']]
825 # TODO(crbug/777787): once the parameters of all callers of arc_setup
826 # are refactored, we can delete the safety net here.
827 if dep_packages:
828 dep_packages = self._fix_nested_array_level(
829 'dep_packages', 1, dep_packages)
830 apks = self._fix_nested_array_level('apks', 2, apks)
831 full_pkg_names = self._fix_nested_array_level(
832 'full_pkg_names', 2, full_pkg_names)
833 if (len(dep_packages) != len(apks) or
Ricardo Quesada02242792018-05-08 12:57:57 -0700834 len(apks) != len(full_pkg_names)):
Ben Cheng42b86892017-10-25 17:22:25 +0800835 logging.info('dep_packages length is %d', len(dep_packages))
836 logging.info('apks length is %d', len(apks))
Ricardo Quesada02242792018-05-08 12:57:57 -0700837 logging.info('full_pkg_names length is %d',
838 len(full_pkg_names))
Ben Cheng42b86892017-10-25 17:22:25 +0800839 raise error.TestFail(
840 'dep_packages/apks/full_pkg_names format error')
841
842 self.dep_packages = dep_packages
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800843 self.apks = apks
Ted Laide93c932017-09-05 12:36:20 +0800844 self.uiautomator = uiautomator or disable_play_store
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800845 # Setup dependent packages if required
846 packages = []
Ben Cheng42b86892017-10-25 17:22:25 +0800847 if dep_packages:
848 packages = dep_packages[:]
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800849 if self.uiautomator:
850 packages.append(self._PKG_UIAUTOMATOR)
851 if packages:
852 logging.info('Setting up dependent package(s) %s', packages)
853 self.job.setup_dep(packages)
854
Shuhei Takahashi375783b2018-07-03 15:53:02 +0900855 self.logcat_proc = arc_common.Logcat()
Victor Hsieh2eba8922016-08-17 12:54:14 -0700856
857 wait_for_adb_ready()
858
Lloyd Pique7d1a6ab2017-11-15 16:46:38 -0800859 # Setting verifier_verify_adb_installs to zero suppresses a dialog box
860 # that can appear asking for the user to consent to the install.
861 adb_shell('settings put global verifier_verify_adb_installs 0')
Victor Hsieh2eba8922016-08-17 12:54:14 -0700862
Ben Cheng42b86892017-10-25 17:22:25 +0800863 # Install apks based on dep_packages/apks/full_pkg_names tuples
864 if dep_packages:
865 for i in xrange(len(dep_packages)):
866 self._install_apks(dep_packages[i], apks[i], full_pkg_names[i])
Victor Hsieh2eba8922016-08-17 12:54:14 -0700867
868 if self.uiautomator:
869 path = os.path.join(self.autodir, 'deps', self._PKG_UIAUTOMATOR)
870 sys.path.append(path)
Ted Lai4656ea82017-09-19 17:03:36 +0800871 self._add_ui_object_not_found_handler()
Ted Laide93c932017-09-05 12:36:20 +0800872 if disable_play_store and not is_package_disabled(_PLAY_STORE_PKG):
873 self._disable_play_store()
874 if not is_package_disabled(_PLAY_STORE_PKG):
875 raise error.TestFail('Failed to disable Google Play Store.')
876 self._should_reenable_play_store = True
Chung-yih Wanga67fce02017-03-28 16:19:17 +0800877 if block_outbound:
878 self.block_outbound()
Victor Hsieh2eba8922016-08-17 12:54:14 -0700879
Victor Hsieh2eba8922016-08-17 12:54:14 -0700880 def arc_teardown(self):
881 """ARC test teardown.
882
883 This function removes all installed packages in arc_setup stage
884 first. Then, it restores package verification and disables non-market
885 APK installation.
886
887 """
888 if self.full_pkg_names:
889 for pkg in self.full_pkg_names:
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800890 logging.info('Uninstalling %s', pkg)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700891 if not is_package_installed(pkg):
892 raise error.TestError('Package %s was not installed' % pkg)
893 adb_uninstall(pkg)
894 if self.uiautomator:
Cheng-Yu Leea854fbf2016-09-09 22:25:14 +0800895 logging.info('Uninstalling %s', self._FULL_PKG_NAME_UIAUTOMATOR)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700896 adb_uninstall(self._FULL_PKG_NAME_UIAUTOMATOR)
Ted Laide93c932017-09-05 12:36:20 +0800897 if self._should_reenable_play_store:
898 adb_shell('pm enable ' + _PLAY_STORE_PKG)
Victor Hsieh2eba8922016-08-17 12:54:14 -0700899 adb_shell('settings put secure install_non_market_apps 0')
900 adb_shell('settings put global package_verifier_enable 1')
Victor Hsieh2eba8922016-08-17 12:54:14 -0700901 adb_shell('settings put secure package_verifier_user_consent 0')
902
Luis Hector Chavezb2e7cd72018-04-24 15:06:35 -0700903 # Remove the adb keys without going through adb. This is because the
904 # 'rm' tool does not have permissions to remove the keys once they have
905 # been restorecon(8)ed.
906 utils.system_output('rm -f %s' %
907 pipes.quote(os.path.join(
908 get_android_data_root(),
909 os.path.relpath(_ANDROID_ADB_KEYS_PATH, '/'))))
Victor Hsieh2eba8922016-08-17 12:54:14 -0700910 utils.system_output('adb kill-server')
911
912 def block_outbound(self):
913 """ Blocks the connection from the container to outer network.
914
Abhishek Bhardwajb3b206f2017-04-04 15:52:47 -0700915 The iptables settings accept only 100.115.92.2 port 5555 (adb) and
Chung-yih Wanga67fce02017-03-28 16:19:17 +0800916 all local connections, e.g. uiautomator.
Victor Hsieh2eba8922016-08-17 12:54:14 -0700917 """
918 logging.info('Blocking outbound connection')
Ricardo Quesada0abf3152018-12-06 16:26:35 -0800919 # ipv6
920 _android_shell('ip6tables -I OUTPUT -j REJECT')
921 _android_shell('ip6tables -I OUTPUT -d ip6-localhost -j ACCEPT')
922 # ipv4
Victor Hsieh2eba8922016-08-17 12:54:14 -0700923 _android_shell('iptables -I OUTPUT -j REJECT')
Ricardo Quesada02242792018-05-08 12:57:57 -0700924 _android_shell('iptables -I OUTPUT -p tcp -s 100.115.92.2 '
925 '--sport 5555 '
Ilja H. Friedelce8ebd62017-07-11 13:55:49 -0700926 '-j ACCEPT')
Ricardo Quesada0abf3152018-12-06 16:26:35 -0800927 _android_shell('iptables -I OUTPUT -d localhost -j ACCEPT')
Victor Hsieh2eba8922016-08-17 12:54:14 -0700928
Victor Hsieh2eba8922016-08-17 12:54:14 -0700929 def unblock_outbound(self):
930 """ Unblocks the connection from the container to outer network.
931
932 The iptables settings are not permanent which means they reset on
933 each instance invocation. But we can still use this function to
934 unblock the outbound connections during the test if needed.
935 """
936 logging.info('Unblocking outbound connection')
Ricardo Quesada0abf3152018-12-06 16:26:35 -0800937 # ipv4
938 _android_shell('iptables -D OUTPUT -d localhost -j ACCEPT')
Ricardo Quesada02242792018-05-08 12:57:57 -0700939 _android_shell('iptables -D OUTPUT -p tcp -s 100.115.92.2 '
940 '--sport 5555 '
Ilja H. Friedelce8ebd62017-07-11 13:55:49 -0700941 '-j ACCEPT')
Chung-yih Wangc58c7ab2017-06-30 17:31:56 +0800942 _android_shell('iptables -D OUTPUT -j REJECT')
Ricardo Quesada0abf3152018-12-06 16:26:35 -0800943 # ipv6
944 _android_shell('ip6tables -D OUTPUT -d ip6-localhost -j ACCEPT')
945 _android_shell('ip6tables -D OUTPUT -j REJECT')
Ted Laide93c932017-09-05 12:36:20 +0800946
Ted Lai4656ea82017-09-19 17:03:36 +0800947 def _add_ui_object_not_found_handler(self):
948 """Logs the device dump upon uiautomator.UiObjectNotFoundException."""
949 from uiautomator import device as d
950 d.handlers.on(lambda d: logging.debug('Device window dump:\n%s',
951 d.dump()))
952
Ted Laide93c932017-09-05 12:36:20 +0800953 def _disable_play_store(self):
954 """Disables the Google Play Store app."""
955 if is_package_disabled(_PLAY_STORE_PKG):
956 return
Ted Laide93c932017-09-05 12:36:20 +0800957 adb_shell('am force-stop ' + _PLAY_STORE_PKG)
Lloyd Pique9368a8a2018-04-27 13:35:40 -0700958 adb_shell('am start -a android.settings.APPLICATION_DETAILS_SETTINGS '
959 '-d package:' + _PLAY_STORE_PKG)
960
961 # Note: the straightforward "pm disable <package>" command would be
962 # better, but that requires root permissions, which aren't available on
963 # a pre-release image being tested. The only other way is through the
964 # Settings UI, but which might change.
965 from uiautomator import device as d
966 d(textMatches='(?i)DISABLE', packageName=_SETTINGS_PKG).wait.exists()
967 d(textMatches='(?i)DISABLE', packageName=_SETTINGS_PKG).click.wait()
Ted Laide93c932017-09-05 12:36:20 +0800968 d(textMatches='(?i)DISABLE APP').click.wait()
969 ok_button = d(textMatches='(?i)OK')
970 if ok_button.exists:
971 ok_button.click.wait()
Hidehiko Abe755e8a32018-05-02 21:32:05 +0900972 adb_shell('am force-stop ' + _SETTINGS_PKG)