• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2017 - Google
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"""
17    Test Script for Telephony Pre Check In Sanity
18"""
19
20import re
21import time
22from acts import signals
23from acts.test_decorators import test_tracker_info
24from acts.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
25from acts.test_utils.tel.tel_defines import CAPABILITY_WFC
26from acts.test_utils.tel.tel_defines import DEFAULT_DEVICE_PASSWORD
27from acts.test_utils.tel.tel_defines import PHONE_TYPE_CDMA
28from acts.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
29from acts.test_utils.tel.tel_lookup_tables import operator_capabilities
30from acts.test_utils.tel.tel_test_utils import abort_all_tests
31from acts.test_utils.tel.tel_test_utils import call_setup_teardown
32from acts.test_utils.tel.tel_test_utils import dumpsys_last_call_info
33from acts.test_utils.tel.tel_test_utils import dumpsys_last_call_number
34from acts.test_utils.tel.tel_test_utils import dumpsys_new_call_info
35from acts.test_utils.tel.tel_test_utils import ensure_phone_default_state
36from acts.test_utils.tel.tel_test_utils import get_operator_name
37from acts.test_utils.tel.tel_test_utils import get_service_state_by_adb
38from acts.test_utils.tel.tel_test_utils import fastboot_wipe
39from acts.test_utils.tel.tel_test_utils import hangup_call_by_adb
40from acts.test_utils.tel.tel_test_utils import initiate_call
41from acts.test_utils.tel.tel_test_utils import is_sim_lock_enabled
42from acts.test_utils.tel.tel_test_utils import initiate_emergency_dialer_call_by_adb
43from acts.test_utils.tel.tel_test_utils import last_call_drop_reason
44from acts.test_utils.tel.tel_test_utils import reset_device_password
45from acts.test_utils.tel.tel_test_utils import toggle_airplane_mode_by_adb
46from acts.test_utils.tel.tel_test_utils import unlock_sim
47from acts.test_utils.tel.tel_test_utils import verify_internet_connection
48from acts.test_utils.tel.tel_test_utils import wait_for_cell_data_connection
49from acts.test_utils.tel.tel_test_utils import wait_for_sim_ready_by_adb
50from acts.test_utils.tel.tel_voice_utils import phone_setup_csfb
51from acts.test_utils.tel.tel_voice_utils import phone_setup_iwlan
52from acts.test_utils.tel.tel_voice_utils import phone_setup_voice_3g
53from acts.test_utils.tel.tel_voice_utils import phone_setup_voice_2g
54from acts.utils import get_current_epoch_time
55
56CARRIER_OVERRIDE_CMD = (
57    "am broadcast -a com.google.android.carrier.action.LOCAL_OVERRIDE -n "
58    "com.google.android.carrier/.ConfigOverridingReceiver --ez")
59IMS_FIRST = "carrier_use_ims_first_for_emergency_bool"
60ALLOW_NON_EMERGENCY_CALL = "allow_non_emergency_calls_in_ecm_bool"
61BLOCK_DURATION_CMD = "duration_blocking_disabled_after_emergency_int"
62BLOCK_DURATION = 300
63
64
65class TelLiveEmergencyBase(TelephonyBaseTest):
66    def __init__(self, controllers):
67        TelephonyBaseTest.__init__(self, controllers)
68        self.number_of_devices = 1
69        fake_number = self.user_params.get("fake_emergency_number", "411")
70        self.fake_emergency_number = fake_number.strip("+").replace("-", "")
71        self.my_devices = self.android_devices[:]
72
73    def setup_class(self):
74        TelephonyBaseTest.setup_class(self)
75        for ad in self.android_devices:
76            if not is_sim_lock_enabled(ad):
77                self.setup_dut(ad)
78                return True
79        self.log.error("No device meets SIM READY or LOADED requirement")
80        raise signals.TestAbortClass("No device meets SIM requirement")
81
82    def setup_dut(self, ad):
83        self.dut = ad
84        output = self.dut.adb.shell("dumpsys carrier_config")
85        self.default_settings = {}
86        for setting in (IMS_FIRST, ALLOW_NON_EMERGENCY_CALL,
87                        BLOCK_DURATION_CMD):
88            values = re.findall(r"%s = (\S+)" % setting, output)
89            if values:
90                self.default_settings[setting] = values[-1]
91            else:
92                self.default_settings[setting] = ""
93        self.dut.adb.shell(" ".join(
94            [CARRIER_OVERRIDE_CMD, BLOCK_DURATION_CMD,
95             "%s" % BLOCK_DURATION]))
96        self.dut_operator = get_operator_name(self.log, ad)
97        if self.dut_operator == "tmo":
98            self.fake_emergency_number = "611"
99        elif self.dut_operator == "vzw":
100            self.fake_emergency_number = "922"
101        elif self.dut_operator == "spt":
102            self.fake_emergency_number = "526"
103        if len(self.my_devices) > 1:
104            self.android_devices.remove(ad)
105            self.android_devices.insert(0, ad)
106
107    def teardown_class(self):
108        self.android_devices = self.my_devices
109        TelephonyBaseTest.teardown_class(self)
110
111    def setup_test(self):
112        if not unlock_sim(self.dut):
113            abort_all_tests(self.dut.log, "unable to unlock SIM")
114        self.expected_call_result = True
115
116    def teardown_test(self):
117        self.dut.ensure_screen_on()
118        self.dut.exit_setup_wizard()
119        reset_device_password(self.dut, None)
120        output = self.dut.adb.shell("dumpsys carrier_config")
121        for setting, state in self.default_settings.items():
122            values = re.findall(r"%s = (\S+)" % setting, output)
123            if values and values[-1] != state:
124                self.dut.adb.shell(" ".join(
125                    [CARRIER_OVERRIDE_CMD, setting, state]))
126        ensure_phone_default_state(self.log, self.dut)
127
128    def change_emergency_number_list(self):
129        test_number = "%s:%s" % (self.fake_emergency_number,
130                                 self.fake_emergency_number)
131        output = self.dut.adb.getprop("ril.test.emergencynumber")
132        if output != test_number:
133            cmd = "setprop ril.test.emergencynumber %s" % test_number
134            self.dut.log.info(cmd)
135            self.dut.adb.shell(cmd)
136        for _ in range(5):
137            existing = self.dut.adb.getprop("ril.ecclist")
138            self.dut.log.info("Existing ril.ecclist is: %s", existing)
139            if self.fake_emergency_number in existing:
140                return True
141            emergency_numbers = "%s,%s" % (existing,
142                                           self.fake_emergency_number)
143            cmd = "setprop ril.ecclist %s" % emergency_numbers
144            self.dut.log.info(cmd)
145            self.dut.adb.shell(cmd)
146            # After some system events, ril.ecclist might change
147            # wait sometime for it to settle
148            time.sleep(10)
149            if self.fake_emergency_number in existing:
150                return True
151        return False
152
153    def change_qcril_emergency_source_mcc_table(self):
154        # This will add the fake number into emergency number list for a mcc
155        # in qcril. Please note, the fake number will be send as an emergency
156        # number by modem and reach the real 911 by this
157        qcril_database_path = self.dut.adb.shell("find /data -iname  qcril.db")
158        if not qcril_database_path: return
159        mcc = self.dut.droid.telephonyGetNetworkOperator()
160        mcc = mcc[:3]
161        self.dut.log.info("Add %s mcc %s in qcril_emergency_source_mcc_table")
162        self.dut.adb.shell(
163            "sqlite3 %s \"INSERT INTO qcril_emergency_source_mcc_table VALUES('%s','%s','','')\""
164            % (qcril_database_path, mcc, self.fake_emergency_number))
165
166    def fake_emergency_call_test(self, by_emergency_dialer=True, attemps=3):
167        self.dut.log.info("ServiceState is in %s",
168                          get_service_state_by_adb(self.log, self.dut))
169        if by_emergency_dialer:
170            dialing_func = initiate_emergency_dialer_call_by_adb
171            callee = self.fake_emergency_number
172        else:
173            dialing_func = initiate_call
174            # Initiate_call method has to have "+" in front
175            # otherwise the number will be in dialer without dial out
176            # with sl4a fascade. Need further investigation
177            callee = "+%s" % self.fake_emergency_number
178        for i in range(attemps):
179            begin_time = get_current_epoch_time()
180            result = True
181            if not self.change_emergency_number_list():
182                self.dut.log.error("Unable to add number to ril.ecclist")
183                return False
184            time.sleep(1)
185            last_call_number = dumpsys_last_call_number(self.dut)
186            call_result = dialing_func(self.log, self.dut, callee)
187            time.sleep(3)
188            hangup_call_by_adb(self.dut)
189            if not call_result:
190                last_call_drop_reason(self.dut, begin_time)
191            self.dut.send_keycode("BACK")
192            self.dut.send_keycode("BACK")
193            if not dumpsys_new_call_info(self.dut, last_call_number):
194                result = False
195            if call_result == self.expected_call_result:
196                self.dut.log.info("Call to %s returns %s as expected", callee,
197                                  self.expected_call_result)
198            else:
199                self.dut.log.info("Call to %s returns %s", callee,
200                                  not self.expected_call_result)
201                result = False
202            if result:
203                return True
204            ecclist = self.dut.adb.getprop("ril.ecclist")
205            self.dut.log.info("ril.ecclist = %s", ecclist)
206            if self.fake_emergency_number in ecclist:
207                if i == attemps - 1:
208                    self.dut.log.error("%s is in ril-ecclist, but call failed",
209                                       self.fake_emergency_number)
210                else:
211                    self.dut.log.warning(
212                        "%s is in ril-ecclist, but call failed, try again",
213                        self.fake_emergency_number)
214            else:
215                if i == attemps - 1:
216                    self.dut.log.error("Fail to write %s to ril-ecclist",
217                                       self.fake_emergency_number)
218                else:
219                    self.dut.log.info("%s is not in ril-ecclist",
220                                      self.fake_emergency_number)
221        self.dut.log.info("fake_emergency_call_test result is %s", result)
222        return result
223
224    def set_ims_first(self, state):
225        output = self.dut.adb.shell(
226            "dumpsys carrier_config | grep %s | tail -1" % IMS_FIRST)
227        self.dut.log.info(output)
228        if state in output: return
229        cmd = " ".join([CARRIER_OVERRIDE_CMD, IMS_FIRST, state])
230        self.dut.log.info(cmd)
231        self.dut.adb.shell(cmd)
232        self.dut.log.info(
233            self.dut.adb.shell(
234                "dumpsys carrier_config | grep %s | tail -1" % IMS_FIRST))
235
236    def set_allow_non_emergency_call(self, state):
237        output = self.dut.adb.shell(
238            "dumpsys carrier_config | grep %s | tail -1" %
239            ALLOW_NON_EMERGENCY_CALL)
240        self.dut.log.info(output)
241        if state in output: return
242        cmd = " ".join([CARRIER_OVERRIDE_CMD, ALLOW_NON_EMERGENCY_CALL, state])
243        self.dut.log.info(cmd)
244        self.dut.adb.shell(cmd)
245        self.dut.log.info(
246            self.dut.adb.shell("dumpsys carrier_config | grep %s | tail -1" %
247                               ALLOW_NON_EMERGENCY_CALL))
248
249    def check_emergency_call_back_mode(self,
250                                       by_emergency_dialer=True,
251                                       non_emergency_call_allowed=True,
252                                       attemps=3):
253        state = "true" if non_emergency_call_allowed else "false"
254        self.set_allow_non_emergency_call(state)
255        result = True
256        for _ in range(attemps):
257            if not self.change_emergency_number_list():
258                self.dut.log.error("Unable to add number to ril.ecclist")
259                return False
260            last_call_number = dumpsys_last_call_number(self.dut)
261            self.dut.log.info("Hung up fake emergency call in ringing")
262            if by_emergency_dialer:
263                initiate_emergency_dialer_call_by_adb(
264                    self.log, self.dut, self.fake_emergency_number, timeout=0)
265            else:
266                callee = "+%s" % self.fake_emergency_number
267                self.dut.droid.telecomCallNumber(callee)
268            time.sleep(3)
269            hangup_call_by_adb(self.dut)
270            ecclist = self.dut.adb.getprop("ril.ecclist")
271            self.dut.log.info("ril.ecclist = %s", ecclist)
272            if self.fake_emergency_number in ecclist:
273                break
274        call_info = dumpsys_new_call_info(self.dut, last_call_number)
275        if not call_info:
276            return False
277        call_tech = call_info.get("callTechnologies", "")
278        if "CDMA" in call_tech:
279            expected_ecbm = True
280            expected_data = False
281            expected_call = non_emergency_call_allowed
282        elif "GSM" in call_tech:
283            expected_ecbm = True
284            expected_data = True
285            expected_call = True
286        else:
287            expected_ecbm = False
288            expected_data = True
289            expected_call = True
290        last_call_number = dumpsys_last_call_number(self.dut)
291        begin_time = get_current_epoch_time()
292        self.dut.ensure_screen_on()
293        self.dut.exit_setup_wizard()
294        reset_device_password(self.dut, None)
295        call_check = call_setup_teardown(
296            self.log, self.dut, self.android_devices[1], ad_hangup=self.dut)
297        if call_check != expected_call:
298            self.dut.log.error("Regular phone call is %s, expecting %s",
299                               call_check, expected_call)
300            result = False
301        call_info = dumpsys_new_call_info(self.dut, last_call_number)
302        if not call_info:
303            self.dut.log.error("New call is not in dumpsys telecom")
304            return False
305        if expected_ecbm:
306            if "ecbm" in call_info["callProperties"]:
307                self.dut.log.info("New call is in ecbm.")
308            else:
309                self.dut.log.error(
310                    "New call is not in emergency call back mode.")
311                result = False
312        else:
313            if "ecbm" in call_info["callProperties"]:
314                self.dut.log.error("New call is in emergency call back mode")
315                result = False
316        if not expected_data:
317            if self.dut.droid.telephonyGetDataConnectionState():
318                self.dut.log.info(
319                    "Data connection is off as expected in ECB mode")
320                self.dut.log.info("Wait for getting out of ecbm")
321                if not wait_for_cell_data_connection(self.log, self.dut, True,
322                                                     400):
323                    self.dut.log.error(
324                        "Data connection didn't come back after 5 minutes")
325                    result = False
326                #if not self.dut.droid.telephonyGetDataConnectionState():
327                #    self.dut.log.error(
328                #        "Data connection is not coming back")
329                #    result = False
330                elif not verify_internet_connection(self.log, self.dut):
331                    self.dut.log.error(
332                        "Internet connection check failed after getting out of ECB"
333                    )
334                    result = False
335
336            else:
337                self.dut.log.error("Data connection is not off in ECB mode")
338                if not verify_internet_connection(self.log, self.dut, False):
339                    self.dut.log.error("Internet connection is not off")
340                    result = False
341        else:
342            if self.dut.droid.telephonyGetDataConnectionState():
343                self.dut.log.info("Data connection is on as expected")
344                if not verify_internet_connection(self.log, self.dut):
345                    self.dut.log.error("Internet connection check failed")
346                    result = False
347            else:
348                self.dut.log.error("Data connection is off, expecting on")
349                result = False
350        if expected_call:
351            return result
352        elapsed_time = (get_current_epoch_time() - begin_time) / 1000
353        if elapsed_time < BLOCK_DURATION:
354            time.sleep(BLOCK_DURATION - elapsed_time + 10)
355        if not call_setup_teardown(
356                self.log, self.dut, self.android_devices[1],
357                ad_hangup=self.dut):
358            self.dut.log.error("Regular phone call failed after out of ecbm")
359            result = False
360        return result
361
362    def check_normal_call(self):
363        result = True
364        if "wfc" not in self.test_name:
365            toggle_airplane_mode_by_adb(self.log, self.dut, False)
366        self.dut.ensure_screen_on()
367        self.dut.exit_setup_wizard()
368        reset_device_password(self.dut, None)
369        begin_time = get_current_epoch_time()
370        if not call_setup_teardown(
371                self.log,
372                self.android_devices[1],
373                self.dut,
374                ad_hangup=self.android_devices[1]):
375            self.dut.log.error("Regular MT phone call fails")
376            self.dut.log.info("call_info = %s", dumpsys_last_call_info(
377                self.dut))
378            result = False
379        if not call_setup_teardown(
380                self.log, self.dut, self.android_devices[1],
381                ad_hangup=self.dut):
382            self.dut.log.error("Regular MO phone call fails")
383            self.dut.log.info("call_info = %s", dumpsys_last_call_info(
384                self.dut))
385            result = False
386        return result
387