1#!/usr/bin/env python3.5
2#
3#   Copyright 2019 - 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.
16import time
17from collections import namedtuple
18
19from acts import asserts
20from acts import signals
21from acts import utils
22from acts.base_test import BaseTestClass
23from acts.test_utils.gnss import gnss_test_utils as gutils
24from acts.test_utils.wifi import wifi_test_utils as wutils
25from acts.test_utils.tel import tel_test_utils as tutils
26
27TEST_PACKAGE_NAME = 'com.google.android.apps.maps'
28LOCATION_PERMISSIONS = [
29    'android.permission.ACCESS_FINE_LOCATION',
30    'android.permission.ACCESS_COARSE_LOCATION'
31]
32BACKGROUND_LOCATION_PERMISSION = 'android.permission.ACCESS_BACKGROUND_LOCATION'
33
34
35class LocationPlatinumTest(BaseTestClass):
36    """Location Platinum Tests"""
37
38    def setup_class(self):
39        super().setup_class()
40        self.ad = self.android_devices[0]
41        req_params = [
42            # A { SSID, password } dictionary. Password is optional.
43            'wifi_network',
44            # A [latitude, longitude] list to identify test location.
45            'test_location',
46            # Cold Start Criteria, a int to define the criteria.
47            'cs_criteria',
48            # Warm Start Criteria, a int to define the criteria.
49            'ws_criteria',
50            # Hot Start Criteria, a int to define the criteria.
51            'hs_criteria',
52            # NetworkLocationProvide Criteria, a int to define the criteria.
53            'nlp_criteria',
54            # A list to identify QXDM log path.
55            'qdsp6m_path'
56        ]
57        self.unpack_userparams(req_param_names=req_params)
58
59        # Init test types Cold Start, Warm Start and Hot Start.
60        test_type = namedtuple('Type', ['command', 'criteria'])
61        self.test_types = {
62            'cs': test_type('Cold Start', self.cs_criteria),
63            'ws': test_type('Warm Start', self.ws_criteria),
64            'hs': test_type('Hot Start', self.hs_criteria)
65        }
66        gutils._init_device(self.ad)
67        self.begin_time = utils.get_current_epoch_time()
68        gutils.clear_logd_gnss_qxdm_log(self.ad)
69        tutils.start_qxdm_logger(self.ad, self.begin_time)
70        tutils.start_adb_tcpdump(self.ad)
71
72    def setup_test(self):
73        """Prepare device with mobile data, wifi and gps ready for test """
74        if int(self.ad.adb.shell('settings get secure location_mode')) != 3:
75            self.ad.adb.shell('settings put secure location_mode 3')
76        if not self.ad.droid.wifiCheckState():
77            wutils.wifi_toggle_state(self.ad, True)
78            gutils.connect_to_wifi_network(self.ad, self.wifi_network)
79        if int(self.ad.adb.shell('settings get global mobile_data')) != 1:
80            gutils.set_mobile_data(self.ad, True)
81        self.grant_location_permission(True)
82        self.ad.adb.shell('pm grant com.android.gpstool %s' %
83                          BACKGROUND_LOCATION_PERMISSION)
84
85    def teardown_class(self):
86        tutils.stop_qxdm_logger(self.ad)
87        gutils.get_gnss_qxdm_log(self.ad, self.qdsp6m_path)
88        tutils.stop_adb_tcpdump(self.ad)
89        tutils.get_tcpdump_log(self.ad, 'location_platinum', self.begin_time)
90        self.ad.take_bug_report('location_platinum', self.begin_time)
91
92    def grant_location_permission(self, option):
93        """Grant or revoke location related permission.
94
95        Args:
96            option: Boolean to grant or revoke location related permissions.
97        """
98        action = 'grant' if option else 'revoke'
99        for permission in LOCATION_PERMISSIONS:
100            self.ad.log.info('%s permission:%s' % (action, permission))
101            self.ad.adb.shell('pm %s %s %s' %
102                              (action, TEST_PACKAGE_NAME, permission))
103
104    def confirm_permission_usage_window(self):
105        """ allow the script to confirm permission keep in use"""
106        time.sleep(1)
107        for _ in range(3):
108            # Press Tab for 3 times
109            self.ad.adb.shell('input keyevent 61')
110        # Press Enter to confirm using current permission set.
111        self.ad.adb.shell('input keyevent 66')
112        time.sleep(1)
113
114    def get_and_verify_ttff(self, mode):
115        """Retrieve ttff with designate mode.
116
117        Args:
118            mode: A string for identify gnss test mode.
119        """
120        if mode in self.test_types:
121            test_type = self.test_types.get(mode)
122        else:
123            raise signals.TestFailure('Unrecognized mode %s' % mode)
124
125        gutils.process_gnss_by_gtw_gpstool(self.ad,
126                                           self.test_types['cs'].criteria)
127        begin_time = gutils.get_current_epoch_time()
128        gutils.start_ttff_by_gtw_gpstool(
129            self.ad, ttff_mode=mode, iteration=1, aid_data=True)
130        ttff_data = gutils.process_ttff_by_gtw_gpstool(self.ad, begin_time,
131                                                       self.test_location)
132        result = gutils.check_ttff_data(
133            self.ad,
134            ttff_data,
135            ttff_mode=test_type.command,
136            criteria=test_type.criteria)
137        asserts.assert_true(
138            result,
139            '%s TTFF fails to reach designated criteria' % test_type.command)
140
141    # Test cases
142    def test_gnss_cold_ttff(self):
143        """
144            1. Send intent to GPSTool for cold start test.
145            2. Retrieve ttff and validate with target criteria.
146        """
147        self.get_and_verify_ttff('cs')
148
149    def test_gnss_warm_ttff(self):
150        """
151            1. Send intent to GPSTool for warm start test.
152            2. Retrieve ttff and validate with target criteria.
153        """
154        self.get_and_verify_ttff('ws')
155
156    def test_gnss_hot_ttff(self):
157        """
158            1. Send intent to GPSTool for hot start test.
159            2. Retrieve ttff and validate with target criteria.
160        """
161        self.get_and_verify_ttff('hs')
162
163    def test_nlp_available_by_wifi(self):
164        """
165            1. Disable mobile data.
166            2. Send intent to GPSTool for NLP.
167            3. Retrieve response time and validate with criteria.
168        """
169        gutils.set_mobile_data(self.ad, False)
170        asserts.assert_true(
171            gutils.check_network_location(
172                self.ad, 1, 'networkLocationType=wifi', self.nlp_criteria),
173            'Fail to get NLP from wifi')
174
175    def test_nlp_available_by_cell(self):
176        """
177            1. Disable wifi.
178            2. Send intent to GPSTool for NLP.
179            3. Retrieve response time and validate with criteria.
180        """
181        wutils.wifi_toggle_state(self.ad, False)
182        asserts.assert_true(
183            gutils.check_network_location(
184                self.ad, 1, 'networkLocationType=cell', self.nlp_criteria),
185            'Fail to get NLP from cell')
186
187    def test_toggle_location_setting_off_on_report_location(self):
188        """
189            1. Toggle location setting off on.
190            2. Open Google Map and ask for location.
191            3. Validate there are location fix in logcat.
192        """
193        self.ad.adb.shell('settings put secure location_mode 0')
194        self.ad.adb.shell('settings put secure location_mode 3')
195        gutils.launch_google_map(self.ad)
196        asserts.assert_true(
197            gutils.check_location_api(self.ad, retries=1),
198            'DUT failed to receive location fix')
199
200    def test_toggle_location_setting_off_not_report_location(self):
201        """
202            1. Toggle location setting off.
203            2. Open Google Map and ask for location.
204            3. Validate there is no location fix in logcat.
205        """
206        self.ad.adb.shell('settings put secure location_mode 0')
207        gutils.launch_google_map(self.ad)
208        asserts.assert_false(
209            gutils.check_location_api(self.ad, retries=1),
210            'DUT Still receive location fix')
211
212    def test_toggle_location_permission_off_on(self):
213        """
214            1. Toggle Google Map location permission off on.
215            2. Open Google Map and ask for location.
216            3. Validate there are location fix in logcat.
217        """
218        self.grant_location_permission(False)
219        self.grant_location_permission(True)
220        gutils.launch_google_map(self.ad)
221        asserts.assert_true(
222            gutils.check_location_api(self.ad, retries=1),
223            'DUT fail to receive location fix')
224
225    def test_toggle_location_permission_off(self):
226        """
227            1. Toggle Google Map location permission off.
228            2. Open Google Map and ask for location.
229            3. Validate there is no location fix in logcat.
230        """
231        self.grant_location_permission(False)
232        gutils.launch_google_map(self.ad)
233        asserts.assert_false(
234            gutils.check_location_api(self.ad, retries=1),
235            'DUT still receive location fix')
236
237    def test_location_only_in_use_state(self):
238        """
239            1. Revoke ACCESS_BACKGROUBND_LOCATION permission on GPSTool.
240            2. Open GPSTool for tracking.
241            3. Validate there are location fix in logcat.
242            4. Turn GPSTool from foreground to background by press home.
243            5. Wait 60 seconds for app clean up.
244            6. Validate GPSTool is skipping for location update in logcat.
245        """
246        self.ad.log.info('Revoke background permission')
247        self.ad.adb.shell('pm revoke com.android.gpstool %s' %
248                          BACKGROUND_LOCATION_PERMISSION)
249        gutils.start_gnss_by_gtw_gpstool(self.ad, True)
250        self.confirm_permission_usage_window()
251        asserts.assert_true(
252            gutils.check_location_api(self.ad, retries=1),
253            'APP failed to receive location fix in foreground')
254        self.ad.log.info('Trun GPSTool from foreground to background')
255        self.ad.adb.shell('input keyevent 3')
256        begin_time = utils.get_current_epoch_time()
257        self.ad.log.info('Wait 60 seconds for app clean up')
258        time.sleep(60)
259        result = self.ad.search_logcat(
260            'skipping loc update for no op app: com.android.gpstool',
261            begin_time)
262        asserts.assert_true(
263            result, 'APP still receive location fix in background')
264