def initialize_device(): """Prepares android device for app install.""" # Set up ADB. adb.setup_adb() # General device configuration settings. configure_build_properties_if_needed() configure_device_settings() # FIXME: This functionality is disabled until a user account is whitelisted so # as to not trigger GAIA alerts. add_test_accounts_if_needed() # Setup AddressSanitizer if needed. setup_asan_if_needed() # Reboot device as above steps would need it and also it brings device in a # good state. reboot() # Make sure we are running as root after restart. adb.run_as_root() # Setup helper environment for quick access to values like codename, etc. # This must be done after the reboot so that we get values from device in # a good state. initialize_environment() # Other configuration tasks (only to done after reboot). configure_wifi_and_airplane_mode() setup_host_and_device_forwarder_if_needed() adb.clear_notifications() adb.change_se_linux_to_permissive_mode() adb.wait_until_package_optimization_complete() unlock_screen_if_locked()
def configure_device_settings(): """Configures device settings for test environment.""" # FIXME: We shouldn't need repeat invocation of this. We need to do this # in case previous invocations of any of the below commands failed. # Write our test environment settings in content database. adb.run_as_root() set_content_settings('com.google.settings/partner', 'use_location_for_services', 0) set_content_settings('settings/global', 'assisted_gps_enabled', 0) set_content_settings('settings/global', 'development_settings_enabled', 0) set_content_settings('settings/global', 'stay_on_while_plugged_in', 3) set_content_settings('settings/global', 'send_action_app_error', 0) set_content_settings('settings/global', 'verifier_verify_adb_installs', 0) set_content_settings('settings/global', 'wifi_scan_always_enabled', 0) set_content_settings('settings/secure', 'anr_show_background', 0) set_content_settings('settings/secure', 'doze_enabled', 0) set_content_settings('settings/secure', 'location_providers_allowed', '') set_content_settings('settings/secure', 'lockscreen.disabled', 1) set_content_settings('settings/secure', 'screensaver_enabled', 0) set_content_settings('settings/system', 'accelerometer_rotation', 0) set_content_settings('settings/system', 'auto_time', 0) set_content_settings('settings/system', 'auto_timezone', 0) set_content_settings('settings/system', 'lockscreen.disabled', 1) set_content_settings('settings/system', 'notification_light_pulse', 0) set_content_settings('settings/system', 'screen_brightness_mode', 0) set_content_settings('settings/system', 'screen_brightness', 1) set_content_settings('settings/system', 'user_rotation', 0) # The following line filled with magic numbers will set media volume to 0 # 3 is the 3rd function in the IAudioServiceList and the following # i32's specify 32 bit integer arguments to the function adb.run_adb_shell_command('service call audio 3 i32 3 i32 0 i32 1') # FIXME: We shouldn't need repeat invocation of this. We need to do this # in case previous invocations of any of the below commands failed. # On certain device/Android configurations we need to disable the lock screen # in a different database. Additionally, the password type must be set to 0. adb.update_key_in_sqlite_db(LOCKSCREEN_DB, LOCKSCREEN_TABLE_NAME, 'lockscreen.disabled', 1) adb.update_key_in_sqlite_db(LOCKSCREEN_DB, LOCKSCREEN_TABLE_NAME, 'lockscreen.password_type', 0) adb.update_key_in_sqlite_db(LOCKSCREEN_DB, LOCKSCREEN_TABLE_NAME, 'lockscreen.password_type_alternate', 0) adb.disable_packages_that_crash_with_gestures() # Create a list of property name and names to be used in local.prop file. local_properties_settings_list = copy.deepcopy(LOCAL_PROP_SETTINGS) # Add debugging flags to local settings list so that they persist across # reboots. local_properties_settings_list += get_debug_props_and_values() # Write the local properties file settings. local_properties_file_contents = '\n'.join(local_properties_settings_list) adb.write_data_to_file(local_properties_file_contents, LOCAL_PROP_PATH)
def setUp(self): test_helpers.patch_environ(self) # Set Android specific environment variables like DEVICE_TMP_DIR, etc. environment.set_value('OS_OVERRIDE', 'ANDROID') environment.set_bot_environment() # Clear and create temporary directory on device. self.device_temp_dir = adb.DEVICE_TMP_DIR adb.remove_directory(self.device_temp_dir, recreate=True) # Create local temp directory. self.local_temp_dir = tempfile.mkdtemp() # Run adb as root. adb.run_as_root()
def add_test_accounts_if_needed(): """Add test account to work with GmsCore, etc.""" last_test_account_check_time = persistent_cache.get_value( LAST_TEST_ACCOUNT_CHECK_KEY, constructor=datetime.datetime.utcfromtimestamp) needs_test_account_update = (last_test_account_check_time is None or dates.time_has_expired( last_test_account_check_time, seconds=ADD_TEST_ACCOUNT_CHECK_INTERVAL)) if not needs_test_account_update: return config = db_config.get() test_account_email = config.test_account_email test_account_password = config.test_account_password if not test_account_email or not test_account_password: return adb.run_as_root() configure_wifi_and_airplane_mode(wifi_enabled=True) if not adb.is_package_installed(ADD_TEST_ACCOUNT_PKG_NAME): logs.log('Installing helper apk for adding test account.') android_directory = environment.get_platform_resources_directory() add_test_account_apk_path = os.path.join(android_directory, ADD_TEST_ACCOUNT_APK_NAME) adb.install_package(add_test_account_apk_path) logs.log('Trying to add test account.') output = adb.run_adb_shell_command( 'am instrument -e account %s -e password %s -w %s' % (test_account_email, test_account_password, ADD_TEST_ACCOUNT_CALL_PATH), timeout=ADD_TEST_ACCOUNT_TIMEOUT) if not output or test_account_email not in output: logs.log('Failed to add test account, probably due to wifi issues.') return logs.log('Test account added successfully.') persistent_cache.set_value(LAST_TEST_ACCOUNT_CHECK_KEY, time.time())
def setup_memory_monitor_script_if_needed(): """Run check_process_mem.sh to monitor the memory usage""" # The script should only start if this is a low end device. device_codename = environment.get_value('DEVICE_CODENAME', get_codename()) if device_codename not in MEMORY_CONSTRAINED_DEVICES: return adb.run_as_root() if get_pid_for_script(MEMORY_MONITOR_SCRIPT): # The script is already running, no work to do. return android_directory = environment.get_platform_resources_directory() script_host_path = os.path.join(android_directory, MEMORY_MONITOR_SCRIPT) script_device_path = os.path.join(adb.DEVICE_TMP_DIR, MEMORY_MONITOR_SCRIPT) # Push memory monitor script onto device and make it executable (if needed). if not adb.file_exists(script_device_path): adb.run_adb_command(['push', script_host_path, adb.DEVICE_TMP_DIR]) adb.run_adb_shell_command(['chmod', '0755', script_device_path]) # Run the memory monitor script. adb.run_adb_shell_command('sh %s 2>/dev/null 1>/dev/null &' % script_device_path) # Wait one second to allow the script to run. time.sleep(1) # Change the priority of the process so that it will not be easily killed # by lowmemorykiller. pid = get_pid_for_script(MEMORY_MONITOR_SCRIPT) if not pid: logs.log_error('Memory monitor script failed to run.') return adb.run_adb_shell_command('echo -1000 \\> /proc/%s/oom_score_adj' % pid) adb.run_adb_shell_command('echo 0 \\> /proc/%s/oom_score' % pid) adb.run_adb_shell_command('echo -17 \\> /proc/%s/oom_adj' % pid)
def update_system_web_view(): """Updates the system webview on the device.""" app_directory = environment.get_value('APP_DIR') system_webview_apk = os.path.join(app_directory, SYSTEM_WEBVIEW_APK_NAME) if not os.path.exists(system_webview_apk): logs.log_error('System Webview apk not found.') return adb.set_property('persist.sys.webview.vmsize', SYSTEM_WEBVIEW_VMSIZE_BYTES) adb.run_as_root() if any([adb.directory_exists(d) for d in SYSTEM_WEBVIEW_DIRS]): adb.remount() adb.stop_shell() adb.run_adb_shell_command(['rm', '-rf', ' '.join(SYSTEM_WEBVIEW_DIRS)]) reboot() adb.uninstall_package(SYSTEM_WEBVIEW_PACKAGE) adb.install_package(system_webview_apk) if not adb.is_package_installed(SYSTEM_WEBVIEW_PACKAGE): logs.log_error('Package %s was not installed successfully.' % SYSTEM_WEBVIEW_PACKAGE)
def setUp(self): test_helpers.patch_environ(self) if environment.platform() != 'LINUX': self.skipTest( 'Adb tests are only applicable to run on a linux host.') android_serial = environment.get_value('ANDROID_SERIAL') if not android_serial: self.skipTest('No ANDROID_SERIAL is set, skipping adb tests.') # Set Android specific environment variables like DEVICE_TMP_DIR, etc. environment.set_value('OS_OVERRIDE', 'ANDROID') environment.set_bot_environment() # Clear and create temporary directory on device. self.device_temp_dir = adb.DEVICE_TMP_DIR adb.remove_directory(self.device_temp_dir, recreate=True) # Create local temp directory. self.local_temp_dir = tempfile.mkdtemp() # Run adb as root. adb.run_as_root()
def setUp(self): helpers.patch_environ(self) environment.set_value('OS_OVERRIDE', 'ANDROID') environment.set_bot_environment() adb.setup_adb() adb.run_as_root()
def configure_build_properties_if_needed(): """Edits /system/build.prop for better boot speed and power use.""" # Check md5 checksum of build.prop to see if already updated, # in which case exit. If build.prop does not exist, something # is very wrong with the device, so bail. old_md5 = persistent_cache.get_value(BUILD_PROP_MD5_KEY) current_md5 = adb.get_file_checksum(BUILD_PROP_PATH) if current_md5 is None: logs.log_error('Unable to find %s on device.' % BUILD_PROP_PATH) return if old_md5 == current_md5: return # Pull to tmp file. bot_tmp_directory = environment.get_value('BOT_TMPDIR') old_build_prop_path = os.path.join(bot_tmp_directory, 'old.prop') adb.run_adb_command(['pull', BUILD_PROP_PATH, old_build_prop_path]) if not os.path.exists(old_build_prop_path): logs.log_error('Unable to fetch %s from device.' % BUILD_PROP_PATH) return # Write new build.prop. new_build_prop_path = os.path.join(bot_tmp_directory, 'new.prop') old_build_prop_file_content = open(old_build_prop_path, 'r') new_build_prop_file_content = open(new_build_prop_path, 'w') new_content_notification = '### CHANGED OR ADDED PROPERTIES ###' for line in old_build_prop_file_content: property_name = line.split('=')[0].strip() if property_name in BUILD_PROPERTIES: continue if new_content_notification in line: continue new_build_prop_file_content.write(line) new_build_prop_file_content.write(new_content_notification + '\n') for flag, value in BUILD_PROPERTIES.iteritems(): new_build_prop_file_content.write('%s=%s\n' % (flag, value)) old_build_prop_file_content.close() new_build_prop_file_content.close() # Keep verified boot disabled for M and higher releases. This makes it easy # to modify system's app_process to load asan libraries. build_version = get_build_version() if is_build_at_least(build_version, 'M'): adb.run_as_root() adb.run_adb_command('disable-verity') reboot() # Make /system writable. adb.run_as_root() adb.remount() # Remove seccomp policies (on N and higher) as ASan requires extra syscalls. if is_build_at_least(build_version, 'N'): policy_files = adb.run_adb_shell_command( ['find', '/system/etc/seccomp_policy/', '-type', 'f']) for policy_file in policy_files.splitlines(): adb.run_adb_shell_command(['rm', policy_file.strip()]) # Remove Google Plus app from non-Google devices. Makes it easy to install # older Gallery app on these devices. Otherwise, we run into duplicate # permission errors. if not google_device(): adb.run_adb_shell_command(['rm', '/system/app/PlusOne.apk']) adb.run_adb_shell_command(['rm', '/system/app/PlusOne/PlusOne.apk']) # Push new build.prop and backup to device. logs.log('Pushing new build properties file on device.') adb.run_adb_command( ['push', '-p', old_build_prop_path, BUILD_PROP_BACKUP_PATH]) adb.run_adb_command(['push', '-p', new_build_prop_path, BUILD_PROP_PATH]) adb.run_adb_shell_command(['chmod', '644', BUILD_PROP_PATH]) # Set persistent cache key containing and md5sum. current_md5 = adb.get_file_checksum(BUILD_PROP_PATH) persistent_cache.set_value(BUILD_PROP_MD5_KEY, current_md5)
def flash_to_latest_build_if_needed(): """Wipes user data, resetting the device to original factory state.""" if environment.get_value('LOCAL_DEVELOPMENT'): # Don't reimage local development devices. return run_timeout = environment.get_value('RUN_TIMEOUT') if run_timeout: # If we have a run timeout, then we are already scheduled to bail out and # will be probably get re-imaged. E.g. using frameworks like Tradefed. return # Check if a flash is needed based on last recorded flash time. last_flash_time = persistent_cache.get_value( LAST_FLASH_TIME_KEY, constructor=datetime.datetime.utcfromtimestamp) needs_flash = last_flash_time is None or dates.time_has_expired( last_flash_time, seconds=adb.FLASH_INTERVAL) if not needs_flash: return build_info = {} if adb.is_gce(): adb.recreate_gce_device() else: # Physical device. is_google_device = google_device() if is_google_device is None: logs.log_error('Unable to query device. Reimaging failed.') adb.bad_state_reached() elif not is_google_device: # We can't reimage these, skip. logs.log('Non-Google device found, skipping reimage.') return else: # For Google devices. # Check if both |BUILD_BRANCH| and |BUILD_TARGET| environment variables # are set. If not, we don't have enough data for reimaging and hence # we bail out. branch = environment.get_value('BUILD_BRANCH') target = environment.get_value('BUILD_TARGET') if not target: # We default to userdebug configuration. build_params = get_build_parameters() if build_params: target = build_params.get('target') + '-userdebug' # Cache target in environment. This is also useful for cases when # device is bricked and we don't have this information available. environment.set_value('BUILD_TARGET', target) if not branch or not target: logs.log_warn( 'BUILD_BRANCH and BUILD_TARGET are not set, skipping reimage.' ) return # Download the latest build artifact for this branch and target. build_info = fetch_artifact.get_latest_artifact_info( branch, target) if not build_info: logs.log_error( 'Unable to fetch information on latest build artifact for ' 'branch %s and target %s.' % (branch, target)) return # Check if our local build matches the latest build. If not, we will # download it. build_id = build_info['bid'] target = build_info['target'] image_directory = environment.get_value('IMAGES_DIR') last_build_info = persistent_cache.get_value(LAST_FLASH_BUILD_KEY) if not last_build_info or last_build_info['bid'] != build_id: # Clean up the images directory first. shell.remove_directory(image_directory, recreate=True) # We have a new build, download the build artifacts for it. for image_regex in FLASH_IMAGE_REGEXES: image_file_path = fetch_artifact.get( build_id, target, image_regex, image_directory) if not image_file_path: logs.log_error( 'Failed to download image artifact %s for ' 'branch %s and target %s.' % (image_file_path, branch, target)) return if image_file_path.endswith('.zip'): archive.unpack(image_file_path, image_directory) # We do one device flash at a time on one host, otherwise we run into # failures and device being stuck in a bad state. flash_lock_key_name = 'flash:%s' % socket.gethostname() if not locks.acquire_lock(flash_lock_key_name, by_zone=True): logs.log_error( 'Failed to acquire lock for reimaging, exiting.') return logs.log('Reimaging started.') logs.log('Rebooting into bootloader mode.') for _ in xrange(FLASH_RETRIES): adb.run_as_root() adb.run_adb_command(['reboot-bootloader']) time.sleep(FLASH_REBOOT_BOOTLOADER_WAIT) adb.run_fastboot_command(['oem', 'off-mode-charge', '0']) adb.run_fastboot_command(['-w', 'reboot-bootloader']) for partition, partition_image_filename in FLASH_IMAGE_FILES: partition_image_file_path = os.path.join( image_directory, partition_image_filename) adb.run_fastboot_command( ['flash', partition, partition_image_file_path]) if partition in ['bootloader', 'radio']: adb.run_fastboot_command(['reboot-bootloader']) adb.run_fastboot_command('reboot') time.sleep(FLASH_REBOOT_WAIT) if adb.get_device_state() == 'device': break logs.log_error('Reimaging failed, retrying.') locks.release_lock(flash_lock_key_name, by_zone=True) if adb.get_device_state() != 'device': logs.log_error('Unable to find device. Reimaging failed.') adb.bad_state_reached() logs.log('Reimaging finished.') # Reset all of our persistent keys after wipe. persistent_cache.delete_value(BUILD_PROP_MD5_KEY) persistent_cache.delete_value(LAST_TEST_ACCOUNT_CHECK_KEY) persistent_cache.set_value(LAST_FLASH_BUILD_KEY, build_info) persistent_cache.set_value(LAST_FLASH_TIME_KEY, time.time())