blob: 262a3ae8d4ed889b4d4a8c7235e2b47d5d6e61ec [file] [log] [blame]
# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""This script provides all needed device information to run tests.
"""
from __future__ import absolute_import
import collections
import logging
import subprocess
import step
from utilities import util
# iOS attributes to be extracted on the connected iOS device.
# iPad and iPhone are examples of the device class.
_DEVICE_CLASS = 'DeviceClass'
# The name of the connected device.
_DEVICE_NAME = 'DeviceName'
# The Unique Device Identifier also called UDID.
_DEVICE_UDID = 'UniqueDeviceID'
# The device iOS version.
_DEVICE_VERSION = 'ProductVersion'
IOS_DEVICE_CLASSES = {
'iPhone': step.PHONE,
'iPad': step.TABLET,
}
# A dictionary mapping device names to their CPU type.
ANDROID_NAME_TO_CPU = {
'hammerhead': 'arm',
'shamu': 'arm',
'bullhead': 'arm_64',
'sailfish': 'arm_64',
'zerofltedv': 'arm_64',
}
# Android attributes to be extracted via adb from the connected Android device.
# A string that represents certain Android device characteristics, such as the
# device class or whether the device has an SD card.
_ANDROID_BUILD_CHARACTERISTICS = 'ro.build.characteristics'
# The Android device version such as '5.1.1'.
_ANDROID_DEVICE_VERSION = 'ro.build.version.release'
# The Android device name such as Nexus 6.
_ANDROID_DEVICE_NAME = 'ro.product.name'
# The Android device serial number.
_ANDROID_SERIAL_NUMBER = 'ro.serialno'
# The Android architecture.
_ANDROID_CPU_ARCHITECTURE = 'ro.product.cpu.abi'
# The Android API level.
_ANDROID_API_LEVEL = 'ro.build.version.sdk'
# The Android build type.
_ANDROID_BUILD_TYPE = 'ro.build.type'
# The Android product brand.
_ANDROID_PRODUCT_BRAND = 'ro.product.brand'
# The Android build ID.
_ANDROID_BUILD_ID = 'ro.build.id'
# The Android product build ID.
_ANDROID_PRODUCT_BUILD_ID = 'ro.product.build.id'
# The Android product board.
_ANDROID_PRODUCT_BOARD = 'ro.product.board'
# The Android product brand.
_ANDROID_PRODUCT_MODEL = 'ro.product.model'
# User build type.
BUILD_TYPE_USERDEBUG = 'userdebug'
# All information needed about the connected device to run tests on.
# device_class: phone or tablet on iOS and Android.
# id: UDID for iOS i.e. 6a5eb3ef1ee5406f704301b730678416b3f40167 and serial
# number for Android i.e. 285300350.
# name: device name could be any string.
# version: could be 9.3.2 for iOS and 5.1.1 for Android.
# build_type: can be userdebug, release etc. Only for Android.
DeviceInfo = collections.namedtuple('DeviceInfo',
['device_class', 'name', 'id', 'version',
'build_type'])
ANDROID_N_API_VERSION = 24
# Standalone web-view
STANDALONE_SYSTEM_WEBVIEW_PACKAGE = 'com.google.android.webview'
def GetIOSDeviceInformation(device_id):
"""Retrieves information from the connected iOS device.
Args:
device_id: The device ID to getprop from.
Returns:
A tuple of DeviceInfo.
"""
device_class = _GetIDeviceInfoValue(_DEVICE_CLASS, device_id)
name = _GetIDeviceInfoValue(_DEVICE_NAME, device_id)
udid = _GetIDeviceInfoValue(_DEVICE_UDID, device_id)
version = _GetIDeviceInfoValue(_DEVICE_VERSION, device_id)
return DeviceInfo(IOS_DEVICE_CLASSES[device_class], name, udid, version, '')
def GetAndroidCPUInformation(device_id):
"""Retrieves the CPU info of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A string representing the cpu architecture.
"""
name = _GetADBDeviceInfoValue(_DEVICE_NAME, device_id)
cpu_info = _GetADBDeviceInfoValue(_ANDROID_CPU_ARCHITECTURE, device_id)
if name in ANDROID_NAME_TO_CPU:
return ANDROID_NAME_TO_CPU[name]
# Wasn't in dictionary, so try to guess.
if 'arm' in cpu_info:
return 'arm_64' if '64' in cpu_info else 'arm'
if 'x86' in cpu_info:
return 'x86_64' if '64' in cpu_info else 'x86'
return cpu_info
def GetAndroidAPILevel(device_id):
"""Retrieves the API level of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
An int representing the Android API level.
Raises:
ValueError: api_level are not all digits.
"""
api_level = _GetADBDeviceInfoValue(_ANDROID_API_LEVEL, device_id)
if not api_level.isdigit():
logging.error('api_level not all digits, assign it to 99')
return 99
return int(api_level)
def GetAndroidBuildType(device_id):
"""Retrieves the build type of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A string representing the Android build type.
"""
return _GetADBDeviceInfoValue(_ANDROID_BUILD_TYPE, device_id)
def GetAndroidProductBrand(device_id):
"""Retrieves the product brand of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A string representing the Android product brand.
"""
return _GetADBDeviceInfoValue(_ANDROID_PRODUCT_BRAND, device_id)
def GetAndroidProductBoard(device_id):
"""Retrieves the product board of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A string representing the Android product board.
"""
return _GetADBDeviceInfoValue(_ANDROID_PRODUCT_BOARD, device_id)
def GetAndroidProductBuildId(device_id):
"""Retrieves the product build id of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A string representing the Android product build id.
"""
return _GetADBDeviceInfoValue(
_ANDROID_PRODUCT_BUILD_ID, device_id) or _GetADBDeviceInfoValue(
_ANDROID_BUILD_ID, device_id)
def GetAndroidProductModel(device_id):
"""Retrieves the product model of the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A string representing the Android product model.
"""
return _GetADBDeviceInfoValue(_ANDROID_PRODUCT_MODEL, device_id)
def GetAndroidDeviceInformation(device_id):
"""Retrieves information from the connected Android device.
Args:
device_id: The device ID to getprop from.
Returns:
A tuple of DeviceInfo.
"""
device_info = _GetADBDeviceInfoValue(_ANDROID_BUILD_CHARACTERISTICS,
device_id)
device_class = step.PHONE
if step.TABLET in device_info:
device_class = step.TABLET
elif step.EMULATOR in device_info:
device_class = step.EMULATOR
name = _GetADBDeviceInfoValue(_ANDROID_DEVICE_NAME, device_id)
serial_number = device_id
version = _GetADBDeviceInfoValue(_ANDROID_DEVICE_VERSION, device_id)
build_type = GetAndroidBuildType(device_id)
return DeviceInfo(device_class, name, serial_number, version, build_type)
def SystemWebviewInfo(device_id):
"""Gets system WebView info.
Args:
device_id: A device id.
Returns:
Map with keys:
- webview_provider_package
- webview_provider_version
"""
webview_info = {}
# For L and M devices 'webview_provider' is 'com.google.android.webview'
webview_provider_package = STANDALONE_SYSTEM_WEBVIEW_PACKAGE
if GetAndroidAPILevel(device_id) >= ANDROID_N_API_VERSION:
webview_provider_package = util.RunADBProcess(
['shell', 'settings', 'get', 'global', 'webview_provider'],
device_id).strip()
webview_info['webview_provider_package'] = webview_provider_package
# Get the 1st(latest) package version
webview_info['webview_provider_version'] = util.GetPackageVersion(
webview_provider_package, device_id)[0]
return webview_info
def _GetADBDeviceInfoValue(info_name, device_id):
"""Retrieves a getprop value via adb.
Args:
info_name: A string representing the desired Android device information.
device_id: The device ID to getprop from.
Returns:
A string result from the adb getprop command.
"""
return util.RunADBProcess(['shell', 'getprop', info_name], device_id).strip()
def _GetIDeviceInfoValue(info_name, device_id):
"""Returns the ideviceinfo attribute's value for iOS devices.
Args:
info_name: A string representing the name of the deviceinfo requested.
device_id: The device ID to getprop from.
Returns:
A string for the ideviceinfo attribute's value.
"""
if device_id:
return subprocess.check_output(
['ideviceinfo', '-u', device_id, '-k', info_name]).rstrip()
return subprocess.check_output(['ideviceinfo', '-k', info_name]).rstrip()