Exemplo n.º 1
0
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()
Exemplo n.º 2
0
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)
Exemplo n.º 3
0
    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()
Exemplo n.º 4
0
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())
Exemplo n.º 5
0
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)
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
    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()
Exemplo n.º 8
0
 def setUp(self):
     helpers.patch_environ(self)
     environment.set_value('OS_OVERRIDE', 'ANDROID')
     environment.set_bot_environment()
     adb.setup_adb()
     adb.run_as_root()
Exemplo n.º 9
0
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)
Exemplo n.º 10
0
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())