1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the 'License'); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an 'AS IS' BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17from acts.controllers.android_lib.tel import tel_utils 18from acts.controllers.cellular_lib import BaseCellularDut 19import os 20import time 21 22GET_BUILD_VERSION = 'getprop ro.build.version.release' 23PIXELLOGGER_CONTROL = 'am broadcast -n com.android.pixellogger/.receiver.' \ 24 'AlwaysOnLoggingReceiver -a com.android.pixellogger.' \ 25 'service.logging.LoggingService.' \ 26 'ACTION_CONFIGURE_ALWAYS_ON_LOGGING ' \ 27 '-e intent_key_enable "{}"' 28 29NETWORK_TYPE_TO_BITMASK = { 30 BaseCellularDut.PreferredNetworkType.LTE_ONLY: '01000001000000000000', 31 BaseCellularDut.PreferredNetworkType.NR_LTE: '11000001000000000000', 32 BaseCellularDut.PreferredNetworkType.WCDMA_ONLY: '00000100001110000100', 33} 34 35class AndroidCellularDut(BaseCellularDut.BaseCellularDut): 36 """ Android implementation of the cellular DUT class.""" 37 def __init__(self, ad, logger): 38 """ Keeps a handler to the android device. 39 40 Args: 41 ad: Android device handler 42 logger: a handler to the logger object 43 """ 44 self.ad = ad 45 self.log = logger 46 logger.info('Initializing Android DUT with baseband version {}'.format( 47 ad.adb.getprop('gsm.version.baseband'))) 48 49 def toggle_airplane_mode(self, new_state=True): 50 """ Turns airplane mode on / off. 51 52 Args: 53 new_state: True if airplane mode needs to be enabled. 54 """ 55 tel_utils.toggle_airplane_mode_by_adb(self.log, self.ad, new_state) 56 57 def toggle_data_roaming(self, new_state=True): 58 """ Enables or disables cellular data roaming. 59 60 Args: 61 new_state: True if data roaming needs to be enabled. 62 """ 63 tel_utils.toggle_cell_data_roaming(self.ad, new_state) 64 65 def get_rx_tx_power_levels(self): 66 """ Obtains Rx and Tx power levels measured from the DUT. 67 68 Returns: 69 A tuple where the first element is an array with the RSRP value 70 in each Rx chain, and the second element is the Tx power in dBm. 71 Values for invalid or disabled Rx / Tx chains are set to None. 72 """ 73 return tel_utils.get_rx_tx_power_levels(self.log, self.ad) 74 75 def set_apn(self, name, apn, type='default'): 76 """ Sets the Access Point Name. 77 78 Args: 79 name: the APN name 80 apn: the APN 81 type: the APN type 82 """ 83 self.ad.droid.telephonySetAPN(name, apn, type) 84 85 def set_preferred_network_type(self, type): 86 """ Sets the preferred RAT. 87 88 Args: 89 type: an instance of class PreferredNetworkType 90 """ 91 92 self.log.info('setting preferred network type: {}'.format(type)) 93 # If android version is S or later, uses bit mask to set and return. 94 version = self.ad.adb.shell(GET_BUILD_VERSION) 95 self.log.info('The android version is {}'.format(version)) 96 try: 97 version_in_number = int(version) 98 if version_in_number > 11: 99 base_cmd = 'cmd phone set-allowed-network-types-for-users -s 0 ' 100 set_network_cmd = base_cmd + NETWORK_TYPE_TO_BITMASK[type] 101 self.ad.adb.shell(set_network_cmd) 102 get_network_cmd = ('cmd phone ' 103 'get-allowed-network-types-for-users -s 0') 104 allowed_network = self.ad.adb.shell(get_network_cmd) 105 self.log.info('The allowed network: {}'.format(allowed_network)) 106 return 107 except ValueError: 108 self.log.info('The android version is older than S, use sl4a') 109 110 if type == BaseCellularDut.PreferredNetworkType.LTE_ONLY: 111 formatted_type = tel_utils.NETWORK_MODE_LTE_ONLY 112 elif type == BaseCellularDut.PreferredNetworkType.WCDMA_ONLY: 113 formatted_type = tel_utils.NETWORK_MODE_WCDMA_ONLY 114 elif type == BaseCellularDut.PreferredNetworkType.GSM_ONLY: 115 formatted_type = tel_utils.NETWORK_MODE_GSM_ONLY 116 else: 117 raise ValueError('Invalid RAT type.') 118 119 if not self.ad.droid.telephonySetPreferredNetworkTypesForSubscription( 120 formatted_type, self.ad.droid.subscriptionGetDefaultSubId()): 121 self.log.error("Could not set preferred network type.") 122 else: 123 self.log.info("Preferred network type set.") 124 125 def get_telephony_signal_strength(self): 126 """ Wrapper for the method with the same name in tel_utils. 127 128 Will be deprecated and replaced by get_rx_tx_power_levels. """ 129 tel_utils.get_telephony_signal_strength(self.ad) 130 131 def start_modem_logging(self): 132 """ Starts on-device log collection. """ 133 self.ad.adb.shell('rm /data/vendor/slog/*.* -f') 134 self.ad.adb.shell(PIXELLOGGER_CONTROL.format('true')) 135 136 def stop_modem_logging(self): 137 """ Stops log collection and pulls logs. """ 138 output_path = self.ad.device_log_path + '/modem/' 139 os.makedirs(output_path, exist_ok=True) 140 self.ad.adb.shell(PIXELLOGGER_CONTROL.format('false')) 141 142 def toggle_data(self, new_state=True): 143 """ Turns on/off of the cellular data. 144 145 Args: 146 new_state: True to enable cellular data 147 """ 148 self.log.info('Toggles cellular data on: {}'.format(new_state)) 149 if new_state: 150 self.ad.adb.shell('settings put global mobile_data 1') 151 self.ad.adb.shell('svc data enable') 152 time.sleep(5) 153 self.log.info('global mobile data: {}'.format( 154 self.ad.adb.shell('settings get global mobile_data'))) 155 else: 156 self.ad.adb.shell('settings put global mobile_data 0') 157 self.ad.adb.shell('svc data disable') 158 self.log.info('global mobile data: {}'.format( 159 self.ad.adb.shell('settings get global mobile_data'))) 160