Ejemplo n.º 1
0
def set_content_settings(table, key, value):
    """Set a device content setting."""
    content_setting_command = (
        'content insert --uri content://%s --bind name:s:%s --bind value:%s:%s'
        % (table, key, get_type_binding(value), str(value)))

    adb.run_adb_shell_command(content_setting_command)
Ejemplo n.º 2
0
 def test_remount(self):
     """Tests remount."""
     system_test_file_path = os.path.join('/system', 'a')
     adb.write_data_to_file('data', system_test_file_path)
     self.assertEqual(adb.read_data_from_file(system_test_file_path),
                      'data')
     adb.run_adb_shell_command(['rm', system_test_file_path])
Ejemplo n.º 3
0
def turn_off_display_if_needed():
    """Turn off the device screen if needed."""
    power_dump_output = adb.run_adb_shell_command(['dumpsys', 'power'])
    if SCREEN_ON_SEARCH_STRING not in power_dump_output:
        # Screen display is already off, no work to do.
        return

    adb.run_adb_shell_command(['input', 'keyevent', 'KEYCODE_POWER'])
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
def get_pid_for_script(script_name):
    """Get the pid of a running shell script."""
    output = adb.run_adb_shell_command("ps | grep ' sh'")
    pids = PS_REGEX.findall(output)
    for pid in pids:
        cmdline = adb.run_adb_shell_command('cat /proc/%s/cmdline' % pid)
        if script_name in cmdline:
            return pid

    return None
Ejemplo n.º 6
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)
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
def get_screen_dimensions():
    """Return device's screen dimensions."""
    window_policy = adb.run_adb_shell_command(['dumpsys', 'window', 'policy'])
    window_policy = window_policy.split('\r\n')

    for line in window_policy[1:]:
        m = re.search(r'mContent=\((\d+),(\d+)\)-\((\d+),(\d+)\)', line)
        if m:
            return (int(m.group(1)), int(m.group(2)), int(m.group(3)),
                    int(m.group(4)))

    # Fallback to default dimensions.
    return (0, 0, 1920, 1200)
Ejemplo n.º 9
0
def configure_wifi_and_airplane_mode(wifi_enabled=False):
  """Configure airplane mode and wifi on device."""
  # Airplane mode should be disabled in all cases. This can get inadvertently
  # turned on via gestures.
  adb.disable_airplane_mode()

  # Need to disable wifi before changing configuration.
  adb.disable_wifi()

  # Check if wifi needs to be enabled. If not, then no need to modify the
  # supplicant file.
  wifi_enabled = wifi_enabled or environment.get_value('WIFI', True)
  if not wifi_enabled:
    # No more work to do, we already disabled it at start.
    return

  if adb.is_gce():
    wifi_ssid = 'VirtWifi'
    wifi_password = ''
  else:
    config = db_config.get()
    if not config.wifi_ssid:
      logs.log('No wifi ssid is set, skipping wifi config.')
      return
    wifi_ssid = config.wifi_ssid
    wifi_password = config.wifi_password or ''

  adb.enable_wifi()

  # Wait 2 seconds to allow the wifi to be enabled.
  time.sleep(2)

  wifi_util_apk_path = os.path.join(
      environment.get_platform_resources_directory(), 'wifi_util.apk')
  if not adb.is_package_installed(WIFI_UTIL_PACKAGE_NAME):
    adb.install_package(wifi_util_apk_path)

  connect_wifi_command = (
      'am instrument -e method connectToNetwork -e ssid {ssid} ')
  if wifi_password:
    connect_wifi_command += '-e psk {password} '
  connect_wifi_command += '-w {call_path}'

  output = adb.run_adb_shell_command(
      connect_wifi_command.format(
          ssid=quote(wifi_ssid),
          password=quote(wifi_password),
          call_path=WIFI_UTIL_CALL_PATH))
  if 'result=true' not in output:
    logs.log_error('Failed to connect to wifi.', output=output)
Ejemplo n.º 10
0
def unlock_screen_if_locked():
    """Unlocks the screen if it is locked."""
    window_dump_output = adb.run_adb_shell_command(['dumpsys', 'window'])
    if SCREEN_LOCK_SEARCH_STRING not in window_dump_output:
        # Screen is not locked, no work to do.
        return

    # Quick power on and off makes this more reliable.
    adb.run_adb_shell_command(['input', 'keyevent', 'KEYCODE_POWER'])
    adb.run_adb_shell_command(['input', 'keyevent', 'KEYCODE_POWER'])

    # This key does the unlock.
    adb.run_adb_shell_command(['input', 'keyevent', 'KEYCODE_MENU'])

    # Artifical delay to let the unlock to complete.
    time.sleep(1)
Ejemplo n.º 11
0
def get_battery_information():
  """Return device's battery level."""
  output = adb.run_adb_shell_command(['dumpsys', 'battery'])

  # Get battery level.
  m_battery_level = re.match(r'.*level: (\d+).*', output, re.DOTALL)
  if not m_battery_level:
    logs.log_error('Error occurred while getting battery status.')
    return None

  # Get battery temperature.
  m_battery_temperature = re.match(r'.*temperature: (\d+).*', output, re.DOTALL)
  if not m_battery_temperature:
    logs.log_error('Error occurred while getting battery temperature.')
    return None

  level = int(m_battery_level.group(1))
  temperature = float(m_battery_temperature.group(1)) / 10.0
  return {'level': level, 'temperature': temperature}
Ejemplo n.º 12
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())
Ejemplo n.º 13
0
def get_crash_info(output):
    """Parse crash output to get (local) minidump path and any other information
     useful for crash uploading, and store in a CrashReportInfo object."""
    crash_stacks_directory = environment.get_value('CRASH_STACKTRACES_DIR')
    platform = environment.platform()

    output_lines = output.splitlines()
    num_lines = len(output_lines)
    for i, line in enumerate(output_lines):
        if platform == 'ANDROID':
            # If we are on Android, the dump extraction is more complicated.
            # The location placed in the crash-stacktrace is of the dump itself but
            # in fact only the MIME of the dump exists, and will have a different
            # extension. We need to pull the MIME and process it.
            match = re.match(CRASH_DUMP_PATH_MARKER, line)
            if not match:
                continue

            minidump_mime_filename_base = None
            for j in range(i + 1, num_lines):
                line = output_lines[j]
                match = re.match(r'(.*)\.dmp', line)
                if match:
                    minidump_mime_filename_base = os.path.basename(
                        match.group(1).strip())
                    break
            if not minidump_mime_filename_base:
                logs.log_error(
                    'Minidump marker was found, but no path in stacktrace.')
                return None

            # Look for MIME. If none found, bail.
            # We might not have copied over the crash dumps yet (copying is buffered),
            # so we want to search both the original directory and the one to which
            # the minidumps should later be copied.
            device_directories_to_search = [
                adb.DEVICE_CRASH_DUMPS_DIR,
                os.path.dirname(line.strip())
            ]
            device_minidump_search_paths = []
            device_minidump_mime_path = None

            for device_directory in device_directories_to_search:
                device_minidump_mime_potential_paths = adb.run_adb_shell_command(
                    ['ls', '"%s"' % device_directory], root=True).splitlines()
                device_minidump_search_paths += device_minidump_mime_potential_paths

                for potential_path in device_minidump_mime_potential_paths:
                    # Check that we actually found a file, and the right one (not logcat).
                    if 'No such file or directory' in potential_path:
                        continue

                    if minidump_mime_filename_base not in potential_path:
                        continue

                    if '.up' in potential_path or '.dmp' in potential_path:
                        device_minidump_mime_path = os.path.join(
                            device_directory, potential_path)
                        break

                # Break if we found a path.
                if device_minidump_mime_path is not None:
                    break

            # If we still didn't find a minidump path, bail.
            if device_minidump_mime_path is None:
                logs.log_error('Could not get MIME path from ls:\n%s' %
                               str(device_minidump_search_paths))
                return None

            # Pull out MIME and parse to minidump file and MIME parameters.
            minidump_mime_filename = '%s.mime' % minidump_mime_filename_base
            local_minidump_mime_path = os.path.join(crash_stacks_directory,
                                                    minidump_mime_filename)
            adb.run_adb_command([
                'pull',
                '"%s"' % device_minidump_mime_path, local_minidump_mime_path
            ])
            if not os.path.exists(local_minidump_mime_path):
                logs.log_error(
                    'Could not pull MIME from %s to %s.' %
                    (device_minidump_mime_path, local_minidump_mime_path))
                return None

            crash_info = parse_mime_to_crash_report_info(
                local_minidump_mime_path)
            if crash_info is None:
                return None

            crash_info.unsymbolized_stacktrace = output
            return crash_info

        else:
            # Other platforms are not currently supported.
            logs.log_error(
                'Unable to fetch crash information for this platform.')
            return None

    # Could not find dump location, bail out. This could also happen when we don't
    # have a minidump location in stack at all, e.g. when testcase does not crash
    # during minimization.
    return None
Ejemplo n.º 14
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)