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