# # Copyright 2022 - The Android Open Source Project # # 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. import os import time from acts import asserts from acts import base_test from acts import utils from acts import signals from acts import test_runner from acts.controllers import adb from acts.test_decorators import test_tracker_info from acts_contrib.test_utils.net import net_test_utils as nutils from acts_contrib.test_utils.tel.tel_test_utils import _check_file_existence from acts_contrib.test_utils.tel.tel_test_utils import _generate_file_directory_and_file_name from acts_contrib.test_utils.wifi import wifi_test_utils as wutils from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_NONE as NONE from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_HANDOVER as HANDOVER from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_RELIABILITY as RELIABILITY from acts_contrib.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_PERFORMANCE as PERFORMANCE DOWNLOAD_PATH = "/sdcard/Download/" RELIABLE = RELIABILITY | HANDOVER TIMEOUT = 6 class DataCostTest(base_test.BaseTestClass): """ Tests for Wifi Tethering """ def setup_class(self): """ Setup devices for tethering and unpack params """ req_params = ("wifi_network", "download_file") self.unpack_userparams(req_params) for ad in self.android_devices: nutils.verify_lte_data_and_tethering_supported(ad) self.tcpdump_pid = None def teardown_class(self): """ Reset settings to default """ for ad in self.android_devices: sub_id = str(ad.droid.telephonyGetSubscriberId()) ad.droid.connectivityFactoryResetNetworkPolicies(sub_id) ad.droid.connectivitySetDataWarningLimit(sub_id, -1) wutils.reset_wifi(ad) def teardown_test(self): if self.tcpdump_pid: nutils.stop_tcpdump(self.dut, self.tcpdump_pid, self.test_name) self.tcpdump_pid = None def on_fail(self, test_name, begin_time): self.dut.take_bug_report(test_name, begin_time) dumpsys_info = self.dut.adb.shell("dumpsys netstats --uid") self.dut.log.info(dumpsys_info) """ Helper functions """ def _clear_netstats(self, ad): """ Clear netstats stored on device Args: ad: Android device object """ ad.log.info("Clear netstats record.") ad.adb.shell("if [ $(ls /data/system/netstats/) ]; then rm /data/system/netstats/*; fi") asserts.assert_equal("", ad.adb.shell("ls /data/system/netstats/"), "Fail to clear netstats.") ad.reboot() time.sleep(30) nutils.verify_lte_data_and_tethering_supported(ad) self._check_multipath_preference_from_dumpsys(ad) def _check_multipath_preference_from_dumpsys(self, ad): """ Check cell multipath_preference from dumpsys Args: ad: Android device object """ try: out = ad.adb.shell("dumpsys connectivity | grep budget") except TimeoutError: ad.log.warning("Fail to get status from dumpsys.") out = "" ad.log.info("MultipathPolicyTracker: %s" % out) if out: asserts.assert_true( "HANDOVER|RELIABILITY" in out, "Cell multipath preference should be HANDOVER|RELIABILITY.") def _get_total_data_usage_for_device(self, ad, conn_type, sub_id): """ Get total data usage in MB for device Args: ad: Android device object conn_type: MOBILE/WIFI data usage sub_id: subscription id Returns: Data usage in MB """ # end time should be in milli seconds and at least 2 hours more than the # actual end time. NetStats:bucket is of size 2 hours and to ensure to # get the most recent data usage, end_time should be +2hours end_time = int(time.time() * 1000) + 2 * 1000 * 60 * 60 data_usage = ad.droid.connectivityQuerySummaryForDevice( conn_type, sub_id, 0, end_time) data_usage /= 1000.0 * 1000.0 # convert data_usage to MB self.log.info("Total data usage is: %s" % data_usage) return data_usage def _check_if_multipath_preference_valid(self, val, exp): """ Check if multipath value is same as expected Args: val: multipath preference for the network exp: expected multipath preference value """ if exp == NONE: asserts.assert_true(val == exp, "Multipath value should be 0") else: asserts.assert_true(val >= exp, "Multipath value should be at least %s" % exp) def _verify_multipath_preferences(self, ad, wifi_pref, cell_pref, wifi_network, cell_network): """ Verify mutlipath preferences for wifi and cell networks Args: ad: Android device object wifi_pref: Expected multipath value for wifi network cell_pref: Expected multipath value for cell network wifi_network: Wifi network id on the device cell_network: Cell network id on the device """ wifi_multipath = \ ad.droid.connectivityGetMultipathPreferenceForNetwork(wifi_network) cell_multipath = \ ad.droid.connectivityGetMultipathPreferenceForNetwork(cell_network) self.log.info("WiFi multipath preference: %s" % wifi_multipath) self.log.info("Cell multipath preference: %s" % cell_multipath) self.log.info("Checking multipath preference for wifi") self._check_if_multipath_preference_valid(wifi_multipath, wifi_pref) self.log.info("Checking multipath preference for cell") self._check_if_multipath_preference_valid(cell_multipath, cell_pref) """ Test Cases """ @test_tracker_info(uuid="e86c8108-3e84-4668-bae4-e5d2c8c27910") def test_multipath_preference_low_data_limit(self): """ Verify multipath preference when mobile data limit is low Steps: 1. DUT has WiFi and LTE data 2. Set mobile data usage limit to low value 3. Verify that multipath preference is 0 for cell network """ # set vars ad = self.android_devices[0] self.dut = ad self._clear_netstats(ad) utils.sync_device_time(ad) self.tcpdump_pid = nutils.start_tcpdump(ad, self.test_name) sub_id = str(ad.droid.telephonyGetSubscriberId()) cell_network = ad.droid.connectivityGetActiveNetwork() self.log.info("cell network %s" % cell_network) wutils.wifi_connect(ad, self.wifi_network) wifi_network = ad.droid.connectivityGetActiveNetwork() self.log.info("wifi network %s" % wifi_network) # verify mulipath preference values self._verify_multipath_preferences(ad, RELIABLE, RELIABLE, wifi_network, cell_network) # set low data limit on mobile data total_pre = self._get_total_data_usage_for_device(ad, 0, sub_id) self.log.info("Setting data usage limit to %sMB" % (total_pre + 5)) ad.droid.connectivitySetDataUsageLimit( sub_id, int((total_pre + 5) * 1000.0 * 1000.0)) self.log.info("Setting data warning limit to %sMB" % (total_pre + 5)) ad.droid.connectivitySetDataWarningLimit( sub_id, int((total_pre + 5) * 1000.0 * 1000.0)) # verify multipath preference values curr_time = time.time() while time.time() < curr_time + TIMEOUT: try: self._verify_multipath_preferences(ad, RELIABLE, NONE, wifi_network, cell_network) return True except signals.TestFailure as e: self.log.debug("%s" % e) time.sleep(1) return False @test_tracker_info(uuid="a2781411-d880-476a-9f40-2c67e0f97db9") def test_multipath_preference_data_download(self): """ Verify multipath preference when large file is downloaded Steps: 1. DUT has WiFi and LTE data 2. WiFi is active network 3. Download large file over cell network 4. Verify multipath preference on cell network is 0 """ # set vars ad = self.android_devices[1] self.dut = ad self._clear_netstats(ad) utils.sync_device_time(ad) self.tcpdump_pid = nutils.start_tcpdump(ad, self.test_name) cell_network = ad.droid.connectivityGetActiveNetwork() self.log.info("cell network %s" % cell_network) wutils.wifi_connect(ad, self.wifi_network) wifi_network = ad.droid.connectivityGetActiveNetwork() self.log.info("wifi network %s" % wifi_network) # verify multipath preference for wifi and cell networks self._verify_multipath_preferences(ad, RELIABLE, RELIABLE, wifi_network, cell_network) # download file with cell network ad.droid.connectivityNetworkOpenConnection(cell_network, self.download_file) file_folder, file_name = _generate_file_directory_and_file_name( self.download_file, DOWNLOAD_PATH) file_path = os.path.join(file_folder, file_name) self.log.info("File path: %s" % file_path) if _check_file_existence(ad, file_path): self.log.info("File exists. Removing file %s" % file_name) ad.adb.shell("rm -rf %s%s" % (DOWNLOAD_PATH, file_name)) # verify multipath preference values curr_time = time.time() while time.time() < curr_time + TIMEOUT: try: self._verify_multipath_preferences(ad, RELIABLE, NONE, wifi_network, cell_network) return True except signals.TestFailure as e: self.log.debug("%s" % e) time.sleep(1) return False # TODO gmoturu@: Need to add tests that use the mobility rig and test when # the WiFi signal is poor and data signal is good.