• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2016 - 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    Base Class for Defining Common Telephony Test Functionality
18"""
19
20import os
21import time
22import traceback
23
24import acts.controllers.diag_logger
25
26from acts.base_test import BaseTestClass
27from acts.signals import TestSignal
28from acts import utils
29
30from acts.test_utils.tel.tel_subscription_utils import \
31    get_subid_from_slot_index
32from acts.test_utils.tel.tel_subscription_utils import \
33    initial_set_up_for_subid_infomation
34from acts.test_utils.tel.tel_subscription_utils import set_subid_for_data
35from acts.test_utils.tel.tel_subscription_utils import \
36    set_subid_for_message
37from acts.test_utils.tel.tel_subscription_utils import \
38    set_subid_for_outgoing_call
39from acts.test_utils.tel.tel_test_utils import ensure_phones_default_state
40from acts.test_utils.tel.tel_test_utils import \
41    reset_preferred_network_type_to_allowable_range
42from acts.test_utils.tel.tel_test_utils import set_phone_screen_on
43from acts.test_utils.tel.tel_test_utils import set_phone_silent_mode
44from acts.test_utils.tel.tel_test_utils import setup_droid_properties
45from acts.test_utils.tel.tel_test_utils import refresh_droid_config
46from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND
47from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING
48from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND
49from acts.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_ENABLED
50from acts.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_DISABLED
51from acts.utils import force_airplane_mode
52
53
54class TelephonyBaseTest(BaseTestClass):
55    def __init__(self, controllers):
56        BaseTestClass.__init__(self, controllers)
57        self.logger_sessions = []
58
59    # Use for logging in the test cases to facilitate
60    # faster log lookup and reduce ambiguity in logging.
61    def tel_test_wrap(fn):
62        def _safe_wrap_test_case(self, *args, **kwargs):
63            test_id = "{}:{}:{}".format(self.__class__.__name__, fn.__name__,
64                                        time.time())
65            log_string = "[Test ID] {}".format(test_id)
66            self.log.info(log_string)
67            try:
68                for ad in self.android_devices:
69                    ad.droid.logI("Started " + log_string)
70                # TODO: b/19002120 start QXDM Logging
71                result = fn(self, *args, **kwargs)
72                if result is not True and "telephony_auto_rerun" in self.user_params:
73                    self.teardown_test()
74                    # re-run only once, if re-run pass, mark as pass
75                    log_string = "[Rerun Test ID] {}. 1st run failed.".format(
76                        test_id)
77                    self.log.info(log_string)
78                    self.setup_test()
79                    for ad in self.android_devices:
80                        ad.droid.logI("Rerun Started " + log_string)
81                    result = fn(self, *args, **kwargs)
82                    if result is True:
83                        self.log.info("Rerun passed.")
84                    elif result is False:
85                        self.log.info("Rerun failed.")
86                    else:
87                        # In the event that we have a non-bool or null
88                        # retval, we want to clearly distinguish this in the
89                        # logs from an explicit failure, though the test will
90                        # still be considered a failure for reporting purposes.
91                        self.log.info("Rerun indeterminate.")
92                        result = False
93                return result
94            except TestSignal:
95                raise
96            except Exception as e:
97                self.log.error(traceback.format_exc())
98                self.log.error(str(e))
99                return False
100            finally:
101                # TODO: b/19002120 stop QXDM Logging
102                for ad in self.android_devices:
103                    try:
104                        ad.adb.wait_for_device()
105                        ad.droid.logI("Finished " + log_string)
106                    except Exception as e:
107                        self.log.error(str(e))
108
109        return _safe_wrap_test_case
110
111    def setup_class(self):
112        setattr(self, "diag_logger",
113                self.register_controller(acts.controllers.diag_logger,
114                                         required=False))
115        for ad in self.android_devices:
116            setup_droid_properties(self.log, ad,
117                                   self.user_params["sim_conf_file"])
118            if not set_phone_screen_on(self.log, ad):
119                self.log.error("Failed to set phone screen-on time.")
120                return False
121            if not set_phone_silent_mode(self.log, ad):
122                self.log.error("Failed to set phone silent mode.")
123                return False
124
125            ad.droid.telephonyAdjustPreciseCallStateListenLevel(
126                PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND, True)
127            ad.droid.telephonyAdjustPreciseCallStateListenLevel(
128                PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING, True)
129            ad.droid.telephonyAdjustPreciseCallStateListenLevel(
130                PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND, True)
131
132            if "enable_wifi_verbose_logging" in self.user_params:
133                ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_ENABLED)
134
135            # Reset preferred network type.
136            reset_preferred_network_type_to_allowable_range(self.log, ad)
137
138        # Sub ID setup
139        for ad in self.android_devices:
140            initial_set_up_for_subid_infomation(self.log, ad)
141        return True
142
143    def teardown_class(self):
144        try:
145            ensure_phones_default_state(self.log, self.android_devices)
146
147            for ad in self.android_devices:
148                ad.droid.telephonyAdjustPreciseCallStateListenLevel(
149                    PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND, False)
150                ad.droid.telephonyAdjustPreciseCallStateListenLevel(
151                    PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING, False)
152                ad.droid.telephonyAdjustPreciseCallStateListenLevel(
153                    PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND, False)
154                if "enable_wifi_verbose_logging" in self.user_params:
155                    ad.droid.wifiEnableVerboseLogging(
156                        WIFI_VERBOSE_LOGGING_DISABLED)
157        finally:
158            for ad in self.android_devices:
159                try:
160                    ad.droid.connectivityToggleAirplaneMode(True)
161                except BrokenPipeError:
162                    # Broken Pipe, can not call SL4A API to turn on Airplane Mode.
163                    # Use adb command to turn on Airplane Mode.
164                    if not force_airplane_mode(ad, True):
165                        self.log.error(
166                            "Can not turn on airplane mode on:{}".format(
167                                ad.serial))
168        return True
169
170    def setup_test(self):
171        for ad in self.android_devices:
172            refresh_droid_config(self.log, ad)
173
174        if getattr(self, "diag_logger", None):
175            for logger in self.diag_logger:
176                self.log.info("Starting a diagnostic session {}".format(
177                    logger))
178                self.logger_sessions.append((logger, logger.start()))
179
180        return ensure_phones_default_state(self.log, self.android_devices)
181
182    def teardown_test(self):
183        for (logger, session) in self.logger_sessions:
184            self.log.info("Resetting a diagnostic session {},{}".format(
185                logger, session))
186            logger.reset()
187        self.logger_sessions = []
188        return True
189
190    def on_exception(self, test_name, begin_time):
191        self._pull_diag_logs(test_name, begin_time)
192        return self._take_bug_report(test_name, begin_time)
193
194    def on_fail(self, test_name, begin_time):
195        self._pull_diag_logs(test_name, begin_time)
196        return self._take_bug_report(test_name, begin_time)
197
198    def _pull_diag_logs(self, test_name, begin_time):
199        for (logger, session) in self.logger_sessions:
200            self.log.info("Pulling diagnostic session {}".format(logger))
201            logger.stop(session)
202            diag_path = os.path.join(self.log_path, begin_time)
203            utils.create_dir(diag_path)
204            logger.pull(session, diag_path)
205
206    def _take_bug_report(self, test_name, begin_time):
207        if "no_bug_report_on_fail" in self.user_params:
208            return
209
210        # magical sleep to ensure the runtime restart or reboot begins
211        time.sleep(1)
212        for ad in self.android_devices:
213            try:
214                ad.adb.wait_for_device()
215                ad.take_bug_report(test_name, begin_time)
216                tombstone_path = os.path.join(
217                    ad.log_path, "BugReports",
218                    "{},{}".format(begin_time, ad.serial).replace(' ', '_'))
219                utils.create_dir(tombstone_path)
220                ad.adb.pull('/data/tombstones/', tombstone_path)
221            except:
222                ad.log.error("Failed to take a bug report for {}, {}"
223                             .format(ad.serial, test_name))
224