1# 2# Copyright 2022 - The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16import logging 17import os 18import random 19import socket 20import threading 21import time 22 23from acts import asserts 24from acts import base_test 25from acts import utils 26from acts import signals 27from acts import test_runner 28from acts.controllers import adb 29from acts.test_decorators import test_tracker_info 30from acts_contrib.test_utils.net import net_test_utils as nutils 31from acts_contrib.test_utils.tel.tel_test_utils import _check_file_existence 32from acts_contrib.test_utils.tel.tel_test_utils import _generate_file_directory_and_file_name 33from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 34from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_NONE as NONE 35from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_HANDOVER as HANDOVER 36from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_RELIABILITY as RELIABILITY 37from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_PERFORMANCE as PERFORMANCE 38 39DOWNLOAD_PATH = "/sdcard/Download/" 40RELIABLE = RELIABILITY | HANDOVER 41TIMEOUT = 6 42 43class DataCostTest(base_test.BaseTestClass): 44 """ Tests for Wifi Tethering """ 45 46 def setup_class(self): 47 """ Setup devices for tethering and unpack params """ 48 49 req_params = ("wifi_network", "download_file") 50 self.unpack_userparams(req_params) 51 52 for ad in self.android_devices: 53 nutils.verify_lte_data_and_tethering_supported(ad) 54 55 self.tcpdump_pid = None 56 57 def teardown_class(self): 58 """ Reset settings to default """ 59 for ad in self.android_devices: 60 sub_id = str(ad.droid.telephonyGetSubscriberId()) 61 ad.droid.connectivityFactoryResetNetworkPolicies(sub_id) 62 ad.droid.connectivitySetDataWarningLimit(sub_id, -1) 63 wutils.reset_wifi(ad) 64 65 66 def teardown_test(self): 67 if self.tcpdump_pid: 68 nutils.stop_tcpdump(self.dut, self.tcpdump_pid, self.test_name) 69 self.tcpdump_pid = None 70 71 def on_fail(self, test_name, begin_time): 72 self.dut.take_bug_report(test_name, begin_time) 73 dumpsys_info=self.dut.adb.shell("dumpsys netstats --uid") 74 self.dut.log.info(dumpsys_info) 75 76 """ Helper functions """ 77 78 def _clear_netstats(self, ad): 79 """ Clear netstats stored on device 80 81 Args: 82 ad: Android device object 83 """ 84 ad.log.info("Clear netstats record.") 85 ad.adb.shell("rm /data/system/netstats/*") 86 asserts.assert_equal("", ad.adb.shell("ls /data/system/netstats/"), 87 "Fail to clear netstats.") 88 ad.reboot() 89 time.sleep(30) 90 nutils.verify_lte_data_and_tethering_supported(ad) 91 self._check_multipath_preference_from_dumpsys(ad) 92 93 def _check_multipath_preference_from_dumpsys(self, ad): 94 """ Check cell multipath_preference from dumpsys 95 96 Args: 97 ad: Android device object 98 """ 99 try: 100 out = ad.adb.shell("dumpsys connectivity | grep budget") 101 except TimeoutError: 102 ad.log.warning("Fail to get status from dumpsys.") 103 out = "" 104 ad.log.info("MultipathPolicyTracker: %s" % out) 105 if out: 106 asserts.assert_true( 107 "HANDOVER|RELIABILITY" in out, 108 "Cell multipath preference should be HANDOVER|RELIABILITY." 109 ) 110 111 def _get_total_data_usage_for_device(self, ad, conn_type, sub_id): 112 """ Get total data usage in MB for device 113 114 Args: 115 ad: Android device object 116 conn_type: MOBILE/WIFI data usage 117 sub_id: subscription id 118 119 Returns: 120 Data usage in MB 121 """ 122 # end time should be in milli seconds and at least 2 hours more than the 123 # actual end time. NetStats:bucket is of size 2 hours and to ensure to 124 # get the most recent data usage, end_time should be +2hours 125 end_time = int(time.time() * 1000) + 2 * 1000 * 60 * 60 126 data_usage = ad.droid.connectivityQuerySummaryForDevice( 127 conn_type, sub_id, 0, end_time) 128 data_usage /= 1000.0 * 1000.0 # convert data_usage to MB 129 self.log.info("Total data usage is: %s" % data_usage) 130 return data_usage 131 132 def _check_if_multipath_preference_valid(self, val, exp): 133 """ Check if multipath value is same as expected 134 135 Args: 136 val: multipath preference for the network 137 exp: expected multipath preference value 138 """ 139 if exp == NONE: 140 asserts.assert_true(val == exp, "Multipath value should be 0") 141 else: 142 asserts.assert_true(val >= exp, 143 "Multipath value should be at least %s" % exp) 144 145 def _verify_multipath_preferences(self, 146 ad, 147 wifi_pref, 148 cell_pref, 149 wifi_network, 150 cell_network): 151 """ Verify mutlipath preferences for wifi and cell networks 152 153 Args: 154 ad: Android device object 155 wifi_pref: Expected multipath value for wifi network 156 cell_pref: Expected multipath value for cell network 157 wifi_network: Wifi network id on the device 158 cell_network: Cell network id on the device 159 """ 160 wifi_multipath = \ 161 ad.droid.connectivityGetMultipathPreferenceForNetwork(wifi_network) 162 cell_multipath = \ 163 ad.droid.connectivityGetMultipathPreferenceForNetwork(cell_network) 164 self.log.info("WiFi multipath preference: %s" % wifi_multipath) 165 self.log.info("Cell multipath preference: %s" % cell_multipath) 166 self.log.info("Checking multipath preference for wifi") 167 self._check_if_multipath_preference_valid(wifi_multipath, wifi_pref) 168 self.log.info("Checking multipath preference for cell") 169 self._check_if_multipath_preference_valid(cell_multipath, cell_pref) 170 171 """ Test Cases """ 172 173 @test_tracker_info(uuid="e86c8108-3e84-4668-bae4-e5d2c8c27910") 174 def test_multipath_preference_low_data_limit(self): 175 """ Verify multipath preference when mobile data limit is low 176 177 Steps: 178 1. DUT has WiFi and LTE data 179 2. Set mobile data usage limit to low value 180 3. Verify that multipath preference is 0 for cell network 181 """ 182 # set vars 183 ad = self.android_devices[0] 184 self.dut = ad 185 self._clear_netstats(ad) 186 utils.sync_device_time(ad) 187 self.tcpdump_pid = nutils.start_tcpdump(ad, self.test_name) 188 189 sub_id = str(ad.droid.telephonyGetSubscriberId()) 190 cell_network = ad.droid.connectivityGetActiveNetwork() 191 self.log.info("cell network %s" % cell_network) 192 wutils.wifi_connect(ad, self.wifi_network) 193 wifi_network = ad.droid.connectivityGetActiveNetwork() 194 self.log.info("wifi network %s" % wifi_network) 195 196 # verify mulipath preference values 197 self._verify_multipath_preferences( 198 ad, RELIABLE, RELIABLE, wifi_network, cell_network) 199 200 # set low data limit on mobile data 201 total_pre = self._get_total_data_usage_for_device(ad, 0, sub_id) 202 self.log.info("Setting data usage limit to %sMB" % (total_pre + 5)) 203 ad.droid.connectivitySetDataUsageLimit( 204 sub_id, int((total_pre + 5) * 1000.0 * 1000.0)) 205 self.log.info("Setting data warning limit to %sMB" % (total_pre + 5)) 206 ad.droid.connectivitySetDataWarningLimit( 207 sub_id, int((total_pre + 5) * 1000.0 * 1000.0)) 208 209 # verify multipath preference values 210 curr_time = time.time() 211 while time.time() < curr_time + TIMEOUT: 212 try: 213 self._verify_multipath_preferences( 214 ad, RELIABLE, NONE, wifi_network, cell_network) 215 return True 216 except signals.TestFailure as e: 217 self.log.debug("%s" % e) 218 time.sleep(1) 219 return False 220 221 @test_tracker_info(uuid="a2781411-d880-476a-9f40-2c67e0f97db9") 222 def test_multipath_preference_data_download(self): 223 """ Verify multipath preference when large file is downloaded 224 225 Steps: 226 1. DUT has WiFi and LTE data 227 2. WiFi is active network 228 3. Download large file over cell network 229 4. Verify multipath preference on cell network is 0 230 """ 231 # set vars 232 ad = self.android_devices[1] 233 self.dut = ad 234 self._clear_netstats(ad) 235 utils.sync_device_time(ad) 236 self.tcpdump_pid = nutils.start_tcpdump(ad, self.test_name) 237 238 cell_network = ad.droid.connectivityGetActiveNetwork() 239 self.log.info("cell network %s" % cell_network) 240 wutils.wifi_connect(ad, self.wifi_network) 241 wifi_network = ad.droid.connectivityGetActiveNetwork() 242 self.log.info("wifi network %s" % wifi_network) 243 244 # verify multipath preference for wifi and cell networks 245 self._verify_multipath_preferences( 246 ad, RELIABLE, RELIABLE, wifi_network, cell_network) 247 248 # download file with cell network 249 ad.droid.connectivityNetworkOpenConnection(cell_network, 250 self.download_file) 251 file_folder, file_name = _generate_file_directory_and_file_name( 252 self.download_file, DOWNLOAD_PATH) 253 file_path = os.path.join(file_folder, file_name) 254 self.log.info("File path: %s" % file_path) 255 if _check_file_existence(ad, file_path): 256 self.log.info("File exists. Removing file %s" % file_name) 257 ad.adb.shell("rm -rf %s%s" % (DOWNLOAD_PATH, file_name)) 258 259 # verify multipath preference values 260 curr_time = time.time() 261 while time.time() < curr_time + TIMEOUT: 262 try: 263 self._verify_multipath_preferences( 264 ad, RELIABLE, NONE, wifi_network, cell_network) 265 return True 266 except signals.TestFailure as e: 267 self.log.debug("%s" % e) 268 time.sleep(1) 269 return False 270 271 # TODO gmoturu@: Need to add tests that use the mobility rig and test when 272 # the WiFi signal is poor and data signal is good. 273