1#
2#   Copyright 2018 - 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 test_runner
26from acts.controllers import adb
27from acts.test_decorators import test_tracker_info
28from acts.test_utils.tel.tel_data_utils import wait_for_cell_data_connection
29from acts.test_utils.tel.tel_test_utils import verify_http_connection
30from acts.test_utils.tel.tel_test_utils import _check_file_existance
31from acts.test_utils.tel.tel_test_utils import _generate_file_directory_and_file_name
32from acts.test_utils.wifi import wifi_test_utils as wutils
33from acts.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_NONE as NONE
34from acts.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_HANDOVER as HANDOVER
35from acts.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_RELIABILITY as RELIABILITY
36from acts.test_utils.net.connectivity_const import MULTIPATH_PREFERENCE_PERFORMANCE as PERFORMANCE
37
38DOWNLOAD_PATH = "/sdcard/Download/"
39RELIABLE = RELIABILITY | HANDOVER
40
41class DataCostTest(base_test.BaseTestClass):
42    """ Tests for Wifi Tethering """
43
44    def setup_class(self):
45        """ Setup devices for tethering and unpack params """
46
47        req_params = ("wifi_network", "download_file")
48        self.unpack_userparams(req_params)
49
50        for ad in self.android_devices:
51            wutils.reset_wifi(ad)
52            ad.droid.telephonyToggleDataConnection(True)
53            wait_for_cell_data_connection(self.log, ad, True)
54            asserts.assert_true(
55                verify_http_connection(self.log, ad),
56                "HTTP verification failed on cell data connection")
57
58    def teardown_class(self):
59        for ad in self.android_devices:
60            wutils.reset_wifi(ad)
61            ad.droid.telephonyToggleDataConnection(True)
62
63    """ Helper functions """
64
65    def _get_total_data_usage_for_device(self, ad, conn_type, sub_id):
66        """ Get total data usage in MB for device
67
68        Args:
69            ad: Android device object
70            conn_type: MOBILE/WIFI data usage
71            sub_id: subscription id
72
73        Returns:
74            Data usage in MB
75        """
76        # end time should be in milli seconds and at least 2 hours more than the
77        # actual end time. NetStats:bucket is of size 2 hours and to ensure to
78        # get the most recent data usage, end_time should be +2hours
79        end_time = int(time.time() * 1000) + 2 * 1000 * 60 * 60
80        data_usage = ad.droid.connectivityQuerySummaryForDevice(
81            conn_type, sub_id, 0, end_time)
82        data_usage /= 1000.0 * 1000.0 # convert data_usage to MB
83        self.log.info("Total data usage is: %s" % data_usage)
84        return data_usage
85
86    def _check_if_multipath_preference_valid(self, val, exp):
87        """ Check if multipath value is same as expected
88
89        Args:
90            val: multipath preference for the network
91            exp: expected multipath preference value
92        """
93        if exp == NONE:
94            asserts.assert_true(val == exp, "Multipath value should be 0")
95        else:
96            asserts.assert_true(val >= exp,
97                                "Multipath value should be at least %s" % exp)
98
99    def _verify_multipath_preferences(self,
100                                      ad,
101                                      wifi_pref,
102                                      cell_pref,
103                                      wifi_network,
104                                      cell_network):
105        """ Verify mutlipath preferences for wifi and cell networks
106
107        Args:
108            ad: Android device object
109            wifi_pref: Expected multipath value for wifi network
110            cell_pref: Expected multipath value for cell network
111            wifi_network: Wifi network id on the device
112            cell_network: Cell network id on the device
113        """
114        wifi_multipath = \
115            ad.droid.connectivityGetMultipathPreferenceForNetwork(wifi_network)
116        cell_multipath = \
117            ad.droid.connectivityGetMultipathPreferenceForNetwork(cell_network)
118        self.log.info("WiFi multipath preference: %s" % wifi_multipath)
119        self.log.info("Cell multipath preference: %s" % cell_multipath)
120        self.log.info("Checking multipath preference for wifi")
121        self._check_if_multipath_preference_valid(wifi_multipath, wifi_pref)
122        self.log.info("Checking multipath preference for cell")
123        self._check_if_multipath_preference_valid(cell_multipath, cell_pref)
124
125    """ Test Cases """
126
127    @test_tracker_info(uuid="e86c8108-3e84-4668-bae4-e5d2c8c27910")
128    def test_multipath_preference_low_data_limit(self):
129        """ Verify multipath preference when mobile data limit is low
130
131        Steps:
132            1. DUT has WiFi and LTE data
133            2. Set mobile data usage limit to low value
134            3. Verify that multipath preference is 0 for cell network
135        """
136        # set vars
137        ad = self.android_devices[0]
138        sub_id = str(ad.droid.telephonyGetSubscriberId())
139        cell_network = ad.droid.connectivityGetActiveNetwork()
140        self.log.info("cell network %s" % cell_network)
141        wutils.wifi_connect(ad, self.wifi_network)
142        wifi_network = ad.droid.connectivityGetActiveNetwork()
143        self.log.info("wifi network %s" % wifi_network)
144
145        # verify mulipath preference values
146        self._verify_multipath_preferences(
147            ad, RELIABLE, RELIABLE, wifi_network, cell_network)
148
149        # set low data limit on mobile data
150        total_pre = self._get_total_data_usage_for_device(ad, 0, sub_id)
151        self.log.info("Setting data usage limit to %sMB" % (total_pre + 5))
152        ad.droid.connectivitySetDataUsageLimit(
153            sub_id, int((total_pre + 5) * 1000.0 * 1000.0))
154        self.log.info("Setting data warning limit to %sMB" % (total_pre + 5))
155        ad.droid.connectivitySetDataWarningLimit(
156            sub_id, int((total_pre + 5) * 1000.0 * 1000.0))
157
158        # reset data limit
159        ad.droid.connectivityFactoryResetNetworkPolicies(sub_id)
160        ad.droid.connectivitySetDataWarningLimit(sub_id, -1)
161
162        # verify multipath preference values
163        self._verify_multipath_preferences(
164            ad, RELIABLE, NONE, wifi_network, cell_network)
165
166    @test_tracker_info(uuid="a2781411-d880-476a-9f40-2c67e0f97db9")
167    def test_multipath_preference_data_download(self):
168        """ Verify multipath preference when large file is downloaded
169
170        Steps:
171            1. DUT has WiFi and LTE data
172            2. WiFi is active network
173            3. Download large file over cell network
174            4. Verify multipath preference on cell network is 0
175        """
176        # set vars
177        ad = self.android_devices[1]
178        cell_network = ad.droid.connectivityGetActiveNetwork()
179        self.log.info("cell network %s" % cell_network)
180        wutils.wifi_connect(ad, self.wifi_network)
181        wifi_network = ad.droid.connectivityGetActiveNetwork()
182        self.log.info("wifi network %s" % wifi_network)
183
184        # verify multipath preference for wifi and cell networks
185        self._verify_multipath_preferences(
186            ad, RELIABLE, RELIABLE, wifi_network, cell_network)
187
188        # download file with cell network
189        ad.droid.connectivityNetworkOpenConnection(cell_network,
190                                                   self.download_file)
191        file_folder, file_name = _generate_file_directory_and_file_name(
192            self.download_file, DOWNLOAD_PATH)
193        file_path = os.path.join(file_folder, file_name)
194        self.log.info("File path: %s" % file_path)
195        if _check_file_existance(ad, file_path):
196            self.log.info("File exists. Removing file %s" % file_name)
197            ad.adb.shell("rm -rf %s%s" % (DOWNLOAD_PATH, file_name))
198
199        #  verify multipath preference values
200        self._verify_multipath_preferences(
201            ad, RELIABLE, NONE, wifi_network, cell_network)
202
203    # TODO gmoturu@: Need to add tests that use the mobility rig and test when
204    # the WiFi signal is poor and data signal is good.
205