1#!/usr/bin/env python3
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# This is test util for subscription setup.
18# It will be deleted once we have better solution for subscription ids.
19from future import standard_library
20standard_library.install_aliases()
21from acts.test_utils.tel.tel_defines import INVALID_SUB_ID
22from acts.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_DATA_SUB_ID
23from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_NW_SELECTION
24
25import time
26
27
28def initial_set_up_for_subid_infomation(log, ad):
29    """Initial subid setup for voice, message and data according to ad's
30    attribute.
31
32    Setup sub id properties for android device. Including the followings:
33        incoming_voice_sub_id
34        incoming_message_sub_id
35        outgoing_voice_sub_id
36        outgoing_message_sub_id
37        default_data_sub_id
38
39    Args:
40        log: log object
41        ad: android device object
42
43    Returns:
44        None
45    """
46    # outgoing_voice_sub_id
47    # If default_voice_sim_slot_index is set in config file, then use sub_id
48    # of this SIM as default_outgoing_sub_id. If default_voice_sim_slot_index
49    # is not set, then use default voice sub_id as default_outgoing_sub_id.
50    # Outgoing voice call will be made on default_outgoing_sub_id by default.
51    if hasattr(ad, "default_voice_sim_slot_index"):
52        outgoing_voice_sub_id = get_subid_from_slot_index(
53            log, ad, ad.default_voice_sim_slot_index)
54        set_subid_for_outgoing_call(ad, outgoing_voice_sub_id)
55    else:
56        outgoing_voice_sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
57    setattr(ad, "outgoing_voice_sub_id", outgoing_voice_sub_id)
58
59    # outgoing_message_sub_id
60    # If default_message_sim_slot_index is set in config file, then use sub_id
61    # of this SIM as outgoing_message_sub_id. If default_message_sim_slot_index
62    # is not set, then use default Sms sub_id as outgoing_message_sub_id.
63    # Outgoing SMS will be sent on outgoing_message_sub_id by default.
64    if hasattr(ad, "default_message_sim_slot_index"):
65        outgoing_message_sub_id = get_subid_from_slot_index(
66            log, ad, ad.default_message_sim_slot_index)
67        set_subid_for_message(ad, outgoing_message_sub_id)
68    else:
69        outgoing_message_sub_id = ad.droid.subscriptionGetDefaultSmsSubId()
70    setattr(ad, "outgoing_message_sub_id", outgoing_message_sub_id)
71
72    # default_data_sub_id
73    # If default_data_sim_slot_index is set in config file, then use sub_id
74    # of this SIM as default_data_sub_id. If default_data_sim_slot_index
75    # is not set, then use default Data sub_id as default_data_sub_id.
76    # Data connection will be established on default_data_sub_id by default.
77    if hasattr(ad, "default_data_sim_slot_index"):
78        default_data_sub_id = get_subid_from_slot_index(
79            log, ad, ad.default_data_sim_slot_index)
80        set_subid_for_data(ad, default_data_sub_id, 0)
81    else:
82        default_data_sub_id = ad.droid.subscriptionGetDefaultDataSubId()
83    setattr(ad, "default_data_sub_id", default_data_sub_id)
84
85    # This is for Incoming Voice Sub ID
86    # If "incoming_voice_sim_slot_index" is set in config file, then
87    # incoming voice call will call to the phone number of the SIM in
88    # "incoming_voice_sim_slot_index".
89    # If "incoming_voice_sim_slot_index" is NOT set in config file,
90    # then incoming voice call will call to the phone number of default
91    # subId.
92    if hasattr(ad, "incoming_voice_sim_slot_index"):
93        incoming_voice_sub_id = get_subid_from_slot_index(
94            log, ad, ad.incoming_voice_sim_slot_index)
95    else:
96        incoming_voice_sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
97    setattr(ad, "incoming_voice_sub_id", incoming_voice_sub_id)
98
99    # This is for Incoming SMS Sub ID
100    # If "incoming_message_sim_slot_index" is set in config file, then
101    # incoming SMS be sent to the phone number of the SIM in
102    # "incoming_message_sim_slot_index".
103    # If "incoming_message_sim_slot_index" is NOT set in config file,
104    # then incoming SMS be sent to the phone number of default
105    # subId.
106    if hasattr(ad, "incoming_message_sim_slot_index"):
107        incoming_message_sub_id = get_subid_from_slot_index(
108            log, ad, ad.incoming_message_sim_slot_index)
109    else:
110        incoming_message_sub_id = ad.droid.subscriptionGetDefaultSmsSubId()
111    setattr(ad, "incoming_message_sub_id", incoming_message_sub_id)
112
113
114def get_default_data_sub_id(ad):
115    """ Get default data subscription id
116    """
117    if hasattr(ad, "default_data_sub_id"):
118        return ad.default_data_sub_id
119    else:
120        return ad.droid.subscriptionGetDefaultDataSubId()
121
122
123def get_outgoing_message_sub_id(ad):
124    """ Get outgoing message subscription id
125    """
126    if hasattr(ad, "outgoing_message_sub_id"):
127        return ad.outgoing_message_sub_id
128    else:
129        return ad.droid.subscriptionGetDefaultSmsSubId()
130
131
132def get_outgoing_voice_sub_id(ad):
133    """ Get outgoing voice subscription id
134    """
135    if hasattr(ad, "outgoing_voice_sub_id"):
136        return ad.outgoing_voice_sub_id
137    else:
138        return ad.droid.subscriptionGetDefaultVoiceSubId()
139
140
141def get_incoming_voice_sub_id(ad):
142    """ Get incoming voice subscription id
143    """
144    if hasattr(ad, "incoming_voice_sub_id"):
145        return ad.incoming_voice_sub_id
146    else:
147        return ad.droid.subscriptionGetDefaultVoiceSubId()
148
149
150def get_incoming_message_sub_id(ad):
151    """ Get incoming message subscription id
152    """
153    if hasattr(ad, "incoming_message_sub_id"):
154        return ad.incoming_message_sub_id
155    else:
156        return ad.droid.subscriptionGetDefaultSmsSubId()
157
158
159def get_subid_from_slot_index(log, ad, sim_slot_index):
160    """ Get the subscription ID for a SIM at a particular slot
161
162    Args:
163        ad: android_device object.
164
165    Returns:
166        result: Subscription ID
167    """
168    subInfo = ad.droid.subscriptionGetAllSubInfoList()
169    for info in subInfo:
170        if info['simSlotIndex'] == sim_slot_index:
171            return info['subscriptionId']
172    return INVALID_SUB_ID
173
174
175def get_operatorname_from_slot_index(ad, sim_slot_index):
176    """ Get the operator name for a SIM at a particular slot
177
178    Args:
179        ad: android_device object.
180
181    Returns:
182        result: Operator Name
183    """
184    subInfo = ad.droid.subscriptionGetAllSubInfoList()
185    for info in subInfo:
186        if info['simSlotIndex'] == sim_slot_index:
187            return info['displayName']
188    return None
189
190
191def get_carrierid_from_slot_index(ad, sim_slot_index):
192    """ Get the carrierId for a SIM at a particular slot
193
194    Args:
195        ad: android_device object.
196        sim_slot_index: slot 0 or slot 1
197
198    Returns:
199        result: CarrierId
200    """
201    subInfo = ad.droid.subscriptionGetAllSubInfoList()
202    for info in subInfo:
203        if info['simSlotIndex'] == sim_slot_index:
204            return info['carrierId']
205    return None
206
207def get_isopportunistic_from_slot_index(ad, sim_slot_index):
208    """ Get the isOppotunistic field for a particular slot
209
210    Args:
211        ad: android_device object.
212        sim_slot_index: slot 0 or slot 1
213
214    Returns:
215        result: True or False based on Value set
216    """
217    subInfo = ad.droid.subscriptionGetAllSubInfoList()
218    for info in subInfo:
219        if info['simSlotIndex'] == sim_slot_index:
220            return info['isOpportunistic']
221    return None
222
223def set_subid_for_data(ad, sub_id, time_to_sleep=WAIT_TIME_CHANGE_DATA_SUB_ID):
224    """Set subId for data
225
226    Args:
227        ad: android device object.
228        sub_id: subscription id (integer)
229
230    Returns:
231        None
232    """
233    # TODO: Need to check onSubscriptionChanged event. b/27843365
234    if ad.droid.subscriptionGetDefaultDataSubId() != sub_id:
235        ad.droid.subscriptionSetDefaultDataSubId(sub_id)
236        time.sleep(time_to_sleep)
237        setattr(ad, "default_data_sub_id", sub_id)
238
239
240def set_subid_for_message(ad, sub_id):
241    """Set subId for outgoing message
242
243    Args:
244        ad: android device object.
245        sub_id: subscription id (integer)
246
247    Returns:
248        None
249    """
250    ad.droid.subscriptionSetDefaultSmsSubId(sub_id)
251    if hasattr(ad, "outgoing_message_sub_id"):
252        ad.outgoing_message_sub_id = sub_id
253
254
255def set_subid_for_outgoing_call(ad, sub_id):
256    """Set subId for outgoing voice call
257
258    Args:
259        ad: android device object.
260        sub_id: subscription id (integer)
261
262    Returns:
263        None
264    """
265    ad.droid.telecomSetUserSelectedOutgoingPhoneAccountBySubId(sub_id)
266    if hasattr(ad, "outgoing_voice_sub_id"):
267        ad.outgoing_voice_sub_id = sub_id
268
269
270def set_incoming_voice_sub_id(ad, sub_id):
271    """Set default subId for voice calls
272
273    Args:
274        ad: android device object.
275        sub_id: subscription id (integer)
276
277    Returns:
278        None
279    """
280    ad.droid.subscriptionSetDefaultVoiceSubId(sub_id)
281    if hasattr(ad, "incoming_voice_sub_id"):
282        ad.incoming_voice_sub_id = sub_id
283
284
285def set_default_sub_for_all_services(ad, slot_id=0):
286    """Set subId for all services
287
288    Args:
289        ad: android device object.
290        slot_id: 0 or 1 (integer)
291
292    Returns:
293        None
294    """
295    sub_id = get_subid_from_slot_index(ad.log, ad, slot_id)
296    ad.log.info("Default Subid for all service is %s", sub_id)
297    set_subid_for_outgoing_call(ad, sub_id)
298    set_incoming_voice_sub_id(ad, sub_id)
299    set_subid_for_data(ad, sub_id)
300    set_subid_for_message(ad, sub_id)
301    ad.droid.telephonyToggleDataConnection(True)
302
303
304def perform_dds_switch(ad):
305    slot_dict = {0: {}, 1: {}}
306    for slot in (0,1):
307        slot_dict[slot]['sub_id'] = get_subid_from_slot_index(ad.log, ad, slot)
308        slot_dict[slot]['operator'] = get_operatorname_from_slot_index(ad, slot)
309    ad.log.debug("%s", slot_dict)
310
311    current_data = get_default_data_sub_id(ad)
312    if slot_dict[0]['sub_id'] == current_data:
313        ad.log.info("DDS Switch from %s to %s", slot_dict[0]['operator'],
314                                                slot_dict[1]['operator'])
315        new_data = slot_dict[1]['sub_id']
316        new_oper = slot_dict[1]['operator']
317    else:
318        ad.log.info("DDS Switch from %s to %s", slot_dict[1]['operator'],
319                                                slot_dict[0]['operator'])
320        new_data = slot_dict[0]['sub_id']
321        new_oper = slot_dict[0]['operator']
322    set_subid_for_data(ad, new_data)
323    ad.droid.telephonyToggleDataConnection(True)
324    if get_default_data_sub_id(ad) == new_data:
325        return new_oper
326    else:
327        ad.log.error("DDS Switch Failed")
328        return False
329
330
331def set_dds_on_slot_0(ad):
332    sub_id = get_subid_from_slot_index(ad.log, ad, 0)
333    operator = get_operatorname_from_slot_index(ad, 0)
334    if get_default_data_sub_id(ad) == sub_id:
335        ad.log.info("Current DDS is already on %s", operator)
336        return True
337    ad.log.info("Setting DDS on %s", operator)
338    set_subid_for_data(ad, sub_id)
339    ad.droid.telephonyToggleDataConnection(True)
340    time.sleep(WAIT_TIME_CHANGE_DATA_SUB_ID)
341    if get_default_data_sub_id(ad) == sub_id:
342        return True
343    else:
344        return False
345
346
347def set_dds_on_slot_1(ad):
348    sub_id = get_subid_from_slot_index(ad.log, ad, 1)
349    operator = get_operatorname_from_slot_index(ad, 1)
350    if get_default_data_sub_id(ad) == sub_id:
351        ad.log.info("Current DDS is already on %s", operator)
352        return True
353    ad.log.info("Setting DDS on %s", operator)
354    set_subid_for_data(ad, sub_id)
355    ad.droid.telephonyToggleDataConnection(True)
356    time.sleep(WAIT_TIME_CHANGE_DATA_SUB_ID)
357    if get_default_data_sub_id(ad) == sub_id:
358        return True
359    else:
360        return False
361
362
363def set_slways_allow_mms_data(ad, sub_id, state=True):
364    """Set always allow mms data on sub_id
365
366    Args:
367        ad: android device object.
368        sub_id: subscription id (integer)
369        state: True or False
370
371    Returns:
372        None
373    """
374    if "sdm" in ad.model or "msm" in ad.model:
375        ad.log.info("Always allow MMS Data is not supported on platform")
376    else:
377        ad.log.debug("Setting MMS Data Always ON %s sub_id %s", state, sub_id)
378        try:
379            ad.droid.subscriptionSetAlwaysAllowMmsData(sub_id, state)
380        except Exception as e:
381            ad.log.error(e)
382            ad.droid.telephonySetAlwaysAllowMmsData(sub_id, state)
383    return True
384
385
386def get_cbrs_and_default_sub_id(ad):
387    """Gets CBRS and Default SubId
388
389    Args:
390        ad: android device object.
391
392    Returns:
393        cbrs_subId
394        default_subId
395    """
396    cbrs_subid, default_subid = None, None
397    slot_dict = {0: {}, 1: {}}
398    for slot in (0, 1):
399        slot_dict[slot]['sub_id'] = get_subid_from_slot_index(
400            ad.log, ad, slot)
401        slot_dict[slot]['carrier_id'] = get_carrierid_from_slot_index(
402            ad, slot)
403        slot_dict[slot]['operator'] = get_operatorname_from_slot_index(
404            ad, slot)
405        if slot_dict[slot]['carrier_id'] == 2340:
406            cbrs_subid = slot_dict[slot]['sub_id']
407        else:
408            default_subid = slot_dict[slot]['sub_id']
409        ad.log.info("Slot %d - Sub %s - Carrier %d - %s", slot,
410                    slot_dict[slot]['sub_id'],
411                    slot_dict[slot]['carrier_id'],
412                    slot_dict[slot]['operator'])
413        if not cbrs_subid:
414            ad.log.error("CBRS sub_id is not ACTIVE")
415    return cbrs_subid, default_subid
416
417def get_subid_on_same_network_of_host_ad(ads, host_sub_id=None, type="voice"):
418    ad_host = ads[0]
419    ad_p1 = ads[1]
420
421    try:
422        ad_p2 = ads[2]
423    except:
424        ad_p2 = None
425
426    if not host_sub_id:
427        if type == "sms":
428            host_sub_id = get_outgoing_message_sub_id(ad_host)
429        else:
430            host_sub_id = get_incoming_voice_sub_id(ad_host)
431    host_mcc = ad_host.telephony["subscription"][host_sub_id]["mcc"]
432    host_mnc = ad_host.telephony["subscription"][host_sub_id]["mnc"]
433    p1_sub_id = INVALID_SUB_ID
434    p2_sub_id = INVALID_SUB_ID
435    p1_mcc = None
436    p1_mnc = None
437    p2_mcc = None
438    p2_mnc = None
439
440    for ad in [ad_p1, ad_p2]:
441        if ad:
442            for sub_id in ad.telephony["subscription"]:
443                mcc = ad.telephony["subscription"][sub_id]["mcc"]
444                mnc = ad.telephony["subscription"][sub_id]["mnc"]
445
446                if ad == ad_p1:
447                    if p1_sub_id == INVALID_SUB_ID:
448                        p1_sub_id = sub_id
449                    if not p1_mcc:
450                        p1_mcc = mcc
451                    if not p1_mnc:
452                        p1_mnc = mnc
453                elif ad == ad_p2:
454                    if p2_sub_id == INVALID_SUB_ID:
455                        p2_sub_id = sub_id
456                    if not p2_mcc:
457                        p2_mcc = mcc
458                    if not p2_mnc:
459                        p2_mnc = mnc
460
461                if mcc == host_mcc and mnc == host_mnc:
462                    if ad == ad_p1:
463                        p1_sub_id = sub_id
464                        p1_mcc = mcc
465                        p1_mnc = mnc
466
467                    elif ad == ad_p2:
468                        p2_sub_id = sub_id
469                        p2_mcc = mcc
470                        p2_mnc = mnc
471
472    return host_sub_id, p1_sub_id, p2_sub_id