• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
19import re
20import time
21
22from acts_contrib.test_utils.tel.tel_defines import CHIPSET_MODELS_LIST
23from acts_contrib.test_utils.tel.tel_defines import INVALID_SIM_SLOT_INDEX
24from acts_contrib.test_utils.tel.tel_defines import INVALID_SUB_ID
25from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_DATA_SUB_ID
26from future import standard_library
27
28standard_library.install_aliases()
29
30
31def initial_set_up_for_subid_information(log, ad):
32    """Initial subid setup for voice, message and data according to ad's
33    attribute.
34
35    Setup sub id properties for android device. Including the followings:
36        incoming_voice_sub_id
37        incoming_message_sub_id
38        outgoing_voice_sub_id
39        outgoing_message_sub_id
40        default_data_sub_id
41
42    Args:
43        log: log object
44        ad: android device object
45
46    Returns:
47        None
48    """
49    # outgoing_voice_sub_id
50    # If default_voice_sim_slot_index is set in config file, then use sub_id
51    # of this SIM as default_outgoing_sub_id. If default_voice_sim_slot_index
52    # is not set, then use default voice sub_id as default_outgoing_sub_id.
53    # Outgoing voice call will be made on default_outgoing_sub_id by default.
54    if hasattr(ad, "default_voice_sim_slot_index"):
55        outgoing_voice_sub_id = get_subid_from_slot_index(
56            log, ad, ad.default_voice_sim_slot_index)
57        set_subid_for_outgoing_call(ad, outgoing_voice_sub_id)
58    else:
59        outgoing_voice_sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
60    setattr(ad, "outgoing_voice_sub_id", outgoing_voice_sub_id)
61
62    # outgoing_message_sub_id
63    # If default_message_sim_slot_index is set in config file, then use sub_id
64    # of this SIM as outgoing_message_sub_id. If default_message_sim_slot_index
65    # is not set, then use default Sms sub_id as outgoing_message_sub_id.
66    # Outgoing SMS will be sent on outgoing_message_sub_id by default.
67    if hasattr(ad, "default_message_sim_slot_index"):
68        outgoing_message_sub_id = get_subid_from_slot_index(
69            log, ad, ad.default_message_sim_slot_index)
70        set_subid_for_message(ad, outgoing_message_sub_id)
71    else:
72        outgoing_message_sub_id = ad.droid.subscriptionGetDefaultSmsSubId()
73    setattr(ad, "outgoing_message_sub_id", outgoing_message_sub_id)
74
75    # default_data_sub_id
76    # If default_data_sim_slot_index is set in config file, then use sub_id
77    # of this SIM as default_data_sub_id. If default_data_sim_slot_index
78    # is not set, then use default Data sub_id as default_data_sub_id.
79    # Data connection will be established on default_data_sub_id by default.
80    if hasattr(ad, "default_data_sim_slot_index"):
81        default_data_sub_id = get_subid_from_slot_index(
82            log, ad, ad.default_data_sim_slot_index)
83        set_subid_for_data(ad, default_data_sub_id, 0)
84    else:
85        default_data_sub_id = ad.droid.subscriptionGetDefaultDataSubId()
86    setattr(ad, "default_data_sub_id", default_data_sub_id)
87
88    # This is for Incoming Voice Sub ID
89    # If "incoming_voice_sim_slot_index" is set in config file, then
90    # incoming voice call will call to the phone number of the SIM in
91    # "incoming_voice_sim_slot_index".
92    # If "incoming_voice_sim_slot_index" is NOT set in config file,
93    # then incoming voice call will call to the phone number of default
94    # subId.
95    if hasattr(ad, "incoming_voice_sim_slot_index"):
96        incoming_voice_sub_id = get_subid_from_slot_index(
97            log, ad, ad.incoming_voice_sim_slot_index)
98    else:
99        incoming_voice_sub_id = ad.droid.subscriptionGetDefaultVoiceSubId()
100    setattr(ad, "incoming_voice_sub_id", incoming_voice_sub_id)
101
102    # This is for Incoming SMS Sub ID
103    # If "incoming_message_sim_slot_index" is set in config file, then
104    # incoming SMS be sent to the phone number of the SIM in
105    # "incoming_message_sim_slot_index".
106    # If "incoming_message_sim_slot_index" is NOT set in config file,
107    # then incoming SMS be sent to the phone number of default
108    # subId.
109    if hasattr(ad, "incoming_message_sim_slot_index"):
110        incoming_message_sub_id = get_subid_from_slot_index(
111            log, ad, ad.incoming_message_sim_slot_index)
112    else:
113        incoming_message_sub_id = ad.droid.subscriptionGetDefaultSmsSubId()
114    setattr(ad, "incoming_message_sub_id", incoming_message_sub_id)
115
116
117def get_default_data_sub_id(ad):
118    """ Get default data subscription id
119    """
120    if hasattr(ad, "default_data_sub_id"):
121        return ad.default_data_sub_id
122    else:
123        return ad.droid.subscriptionGetDefaultDataSubId()
124
125
126def get_outgoing_message_sub_id(ad):
127    """ Get outgoing message subscription id
128    """
129    if hasattr(ad, "outgoing_message_sub_id"):
130        return ad.outgoing_message_sub_id
131    else:
132        return ad.droid.subscriptionGetDefaultSmsSubId()
133
134
135def get_outgoing_voice_sub_id(ad):
136    """ Get outgoing voice subscription id
137    """
138    if hasattr(ad, "outgoing_voice_sub_id"):
139        return ad.outgoing_voice_sub_id
140    else:
141        return ad.droid.subscriptionGetDefaultVoiceSubId()
142
143
144def get_incoming_voice_sub_id(ad):
145    """ Get incoming voice subscription id
146    """
147    if hasattr(ad, "incoming_voice_sub_id"):
148        return ad.incoming_voice_sub_id
149    else:
150        return ad.droid.subscriptionGetDefaultVoiceSubId()
151
152
153def get_incoming_message_sub_id(ad):
154    """ Get incoming message subscription id
155    """
156    if hasattr(ad, "incoming_message_sub_id"):
157        return ad.incoming_message_sub_id
158    else:
159        return ad.droid.subscriptionGetDefaultSmsSubId()
160
161
162def get_subid_by_adb(ad, sim_slot_index):
163    """Get the subscription ID for a SIM at a particular slot via adb command.
164
165    Args:
166        ad: android device object.
167        sim_slot_index: slot 0 or slot 1.
168
169    Returns:
170        Subscription ID.
171    """
172    try:
173        output = ad.adb.shell("dumpsys isub | grep subIds")
174        pattern = re.compile(r"sSlotIndexToSubId\[%d\]:\s*subIds=%d=\[(\d)\]" %
175            (sim_slot_index, sim_slot_index))
176        sub_id = pattern.findall(output)
177    except Exception as e:
178        error_msg = "%s due to %s" % ("Failed to get the subid", e)
179        ad.log.error(error_msg)
180        return INVALID_SUB_ID
181    return int(sub_id[0]) if sub_id else INVALID_SUB_ID
182
183
184def get_subid_from_slot_index(log, ad, sim_slot_index):
185    """ Get the subscription ID for a SIM at a particular slot
186
187    Args:
188        ad: android_device object.
189
190    Returns:
191        result: Subscription ID
192    """
193    subInfo = ad.droid.subscriptionGetAllSubInfoList()
194    for info in subInfo:
195        if info['simSlotIndex'] == sim_slot_index:
196            return info['subscriptionId']
197    return INVALID_SUB_ID
198
199
200def get_operatorname_from_slot_index(ad, sim_slot_index):
201    """ Get the operator name for a SIM at a particular slot
202
203    Args:
204        ad: android_device object.
205
206    Returns:
207        result: Operator Name
208    """
209    subInfo = ad.droid.subscriptionGetAllSubInfoList()
210    for info in subInfo:
211        if info['simSlotIndex'] == sim_slot_index:
212            return info['displayName']
213    return None
214
215
216def get_carrierid_from_slot_index(ad, sim_slot_index):
217    """ Get the carrierId for a SIM at a particular slot
218
219    Args:
220        ad: android_device object.
221        sim_slot_index: slot 0 or slot 1
222
223    Returns:
224        result: CarrierId
225    """
226    subInfo = ad.droid.subscriptionGetAllSubInfoList()
227    for info in subInfo:
228        if info['simSlotIndex'] == sim_slot_index:
229            return info['carrierId']
230    return None
231
232
233def get_isopportunistic_from_slot_index(ad, sim_slot_index):
234    """ Get the isOppotunistic field for a particular slot
235
236    Args:
237        ad: android_device object.
238        sim_slot_index: slot 0 or slot 1
239
240    Returns:
241        result: True or False based on Value set
242    """
243    subInfo = ad.droid.subscriptionGetAllSubInfoList()
244    for info in subInfo:
245        if info['simSlotIndex'] == sim_slot_index:
246            return info['isOpportunistic']
247    return None
248
249
250def set_subid_for_data(ad, sub_id, time_to_sleep=WAIT_TIME_CHANGE_DATA_SUB_ID):
251    """Set subId for data
252
253    Args:
254        ad: android device object.
255        sub_id: subscription id (integer)
256
257    Returns:
258        None
259    """
260    # TODO: Need to check onSubscriptionChanged event. b/27843365
261    if ad.droid.subscriptionGetDefaultDataSubId() != sub_id:
262        ad.droid.subscriptionSetDefaultDataSubId(sub_id)
263        time.sleep(time_to_sleep)
264        setattr(ad, "default_data_sub_id", sub_id)
265
266
267def set_subid_for_message(ad, sub_id):
268    """Set subId for outgoing message
269
270    Args:
271        ad: android device object.
272        sub_id: subscription id (integer)
273
274    Returns:
275        None
276    """
277    ad.droid.subscriptionSetDefaultSmsSubId(sub_id)
278    if hasattr(ad, "outgoing_message_sub_id"):
279        ad.outgoing_message_sub_id = sub_id
280
281
282def set_message_subid(ad, sub_id):
283    """Set subId for both outgoing and incoming messages
284
285    Args:
286        ad: android device object.
287        sub_id: subscription id (integer)
288
289    Returns:
290        None
291    """
292    ad.droid.subscriptionSetDefaultSmsSubId(sub_id)
293    if hasattr(ad, "outgoing_message_sub_id"):
294        ad.outgoing_message_sub_id = sub_id
295    if hasattr(ad, "incoming_message_sub_id"):
296        ad.incoming_message_sub_id = sub_id
297
298
299def set_subid_for_outgoing_call(ad, sub_id):
300    """Set subId for outgoing voice call
301
302    Args:
303        ad: android device object.
304        sub_id: subscription id (integer)
305
306    Returns:
307        None
308    """
309    ad.droid.telecomSetUserSelectedOutgoingPhoneAccountBySubId(sub_id)
310    if hasattr(ad, "outgoing_voice_sub_id"):
311        ad.outgoing_voice_sub_id = sub_id
312
313
314def set_incoming_voice_sub_id(ad, sub_id):
315    """Set default subId for voice calls
316
317    Args:
318        ad: android device object.
319        sub_id: subscription id (integer)
320
321    Returns:
322        None
323    """
324    ad.droid.subscriptionSetDefaultVoiceSubId(sub_id)
325    if hasattr(ad, "incoming_voice_sub_id"):
326        ad.incoming_voice_sub_id = sub_id
327
328
329def set_voice_sub_id(ad, sub_id):
330    """Set default subId for both incoming and outgoing voice calls
331
332    Args:
333        ad: android device object.
334        sub_id: subscription id (integer)
335
336    Returns:
337        None
338    """
339    ad.droid.subscriptionSetDefaultVoiceSubId(sub_id)
340    if hasattr(ad, "incoming_voice_sub_id"):
341        ad.incoming_voice_sub_id = sub_id
342    if hasattr(ad, "outgoing_voice_sub_id"):
343        ad.outgoing_voice_sub_id = sub_id
344
345
346def set_default_sub_for_all_services(ad, slot_id=0):
347    """Set subId for all services
348
349    Args:
350        ad: android device object.
351        slot_id: 0 or 1 (integer)
352
353    Returns:
354        None
355    """
356    sub_id = get_subid_from_slot_index(ad.log, ad, slot_id)
357    ad.log.info("Default Subid for all service is %s", sub_id)
358    set_subid_for_outgoing_call(ad, sub_id)
359    set_incoming_voice_sub_id(ad, sub_id)
360    set_subid_for_data(ad, sub_id)
361    set_subid_for_message(ad, sub_id)
362    ad.droid.telephonyToggleDataConnection(True)
363
364
365def perform_dds_switch(ad):
366    slot_dict = {0: {}, 1: {}}
367    for slot in (0,1):
368        slot_dict[slot]['sub_id'] = get_subid_from_slot_index(ad.log, ad, slot)
369        slot_dict[slot]['operator'] = get_operatorname_from_slot_index(ad, slot)
370    ad.log.debug("%s", slot_dict)
371
372    current_data = get_default_data_sub_id(ad)
373    if slot_dict[0]['sub_id'] == current_data:
374        ad.log.info("DDS Switch from %s to %s", slot_dict[0]['operator'],
375                                                slot_dict[1]['operator'])
376        new_data = slot_dict[1]['sub_id']
377        new_oper = slot_dict[1]['operator']
378    else:
379        ad.log.info("DDS Switch from %s to %s", slot_dict[1]['operator'],
380                                                slot_dict[0]['operator'])
381        new_data = slot_dict[0]['sub_id']
382        new_oper = slot_dict[0]['operator']
383    set_subid_for_data(ad, new_data)
384    ad.droid.telephonyToggleDataConnection(True)
385    if get_default_data_sub_id(ad) == new_data:
386        return new_oper
387    else:
388        ad.log.error("DDS Switch Failed")
389        return False
390
391
392def set_dds_on_slot_0(ad):
393    sub_id = get_subid_from_slot_index(ad.log, ad, 0)
394    if sub_id == INVALID_SUB_ID:
395        ad.log.warning("Invalid sub ID at slot 0")
396        return False
397    operator = get_operatorname_from_slot_index(ad, 0)
398    if get_default_data_sub_id(ad) == sub_id:
399        ad.log.info("Current DDS is already on %s", operator)
400        return True
401    ad.log.info("Setting DDS on %s", operator)
402    set_subid_for_data(ad, sub_id)
403    ad.droid.telephonyToggleDataConnection(True)
404    time.sleep(WAIT_TIME_CHANGE_DATA_SUB_ID)
405    if get_default_data_sub_id(ad) == sub_id:
406        return True
407    else:
408        return False
409
410
411def set_dds_on_slot_1(ad):
412    sub_id = get_subid_from_slot_index(ad.log, ad, 1)
413    if sub_id == INVALID_SUB_ID:
414        ad.log.warning("Invalid sub ID at slot 1")
415        return False
416    operator = get_operatorname_from_slot_index(ad, 1)
417    if get_default_data_sub_id(ad) == sub_id:
418        ad.log.info("Current DDS is already on %s", operator)
419        return True
420    ad.log.info("Setting DDS on %s", operator)
421    set_subid_for_data(ad, sub_id)
422    ad.droid.telephonyToggleDataConnection(True)
423    time.sleep(WAIT_TIME_CHANGE_DATA_SUB_ID)
424    if get_default_data_sub_id(ad) == sub_id:
425        return True
426    else:
427        return False
428
429
430def set_dds_on_slot(ad, dds_slot):
431    """Switch DDS to given slot.
432
433    Args:
434        ad: android device object.
435        dds_slot: the slot which be set to DDS.
436
437    Returns:
438        True if success, False if fail.
439    """
440    sub_id = get_subid_from_slot_index(ad.log, ad, dds_slot)
441    if sub_id == INVALID_SUB_ID:
442        ad.log.warning("Invalid sub ID at slot %d", dds_slot)
443        return False
444    operator = get_operatorname_from_slot_index(ad, dds_slot)
445    if get_default_data_sub_id(ad) == sub_id:
446        ad.log.info("Current DDS is already on %s", operator)
447        return True
448    ad.log.info("Setting DDS on %s", operator)
449    set_subid_for_data(ad, sub_id)
450    ad.droid.telephonyToggleDataConnection(True)
451    time.sleep(WAIT_TIME_CHANGE_DATA_SUB_ID)
452    if get_default_data_sub_id(ad) == sub_id:
453        return True
454    else:
455        return False
456
457
458def set_always_allow_mms_data(ad, sub_id, state=True):
459    """Set always allow mms data on sub_id
460
461    Args:
462        ad: android device object.
463        sub_id: subscription id (integer)
464        state: True or False
465
466    Returns:
467        None
468    """
469    if any(model in ad.model for model in CHIPSET_MODELS_LIST):
470        ad.log.debug("SKIP telephonySetAlwaysAllowMmsData")
471    else:
472        ad.log.debug("telephonySetAlwaysAllowMmsData %s sub_id %s", state, sub_id)
473        ad.droid.telephonySetAlwaysAllowMmsData(sub_id, state)
474    return True
475
476
477def get_cbrs_and_default_sub_id(ad):
478    """Gets CBRS and Default SubId
479
480    Args:
481        ad: android device object.
482
483    Returns:
484        cbrs_subId
485        default_subId
486    """
487    cbrs_subid, default_subid = None, None
488    slot_dict = {0: {}, 1: {}}
489    for slot in (0, 1):
490        slot_dict[slot]['sub_id'] = get_subid_from_slot_index(
491            ad.log, ad, slot)
492        slot_dict[slot]['carrier_id'] = get_carrierid_from_slot_index(
493            ad, slot)
494        slot_dict[slot]['operator'] = get_operatorname_from_slot_index(
495            ad, slot)
496        if slot_dict[slot]['carrier_id'] == 2340:
497            cbrs_subid = slot_dict[slot]['sub_id']
498        else:
499            default_subid = slot_dict[slot]['sub_id']
500        ad.log.info("Slot %d - Sub %s - Carrier %d - %s", slot,
501                    slot_dict[slot]['sub_id'],
502                    slot_dict[slot]['carrier_id'],
503                    slot_dict[slot]['operator'])
504        if not cbrs_subid:
505            ad.log.error("CBRS sub_id is not ACTIVE")
506    return cbrs_subid, default_subid
507
508
509def get_subid_on_same_network_of_host_ad(ads, host_sub_id=None, type="voice"):
510    ad_host = ads[0]
511    ad_p1 = ads[1]
512
513    try:
514        ad_p2 = ads[2]
515    except:
516        ad_p2 = None
517
518    if not host_sub_id:
519        if type == "sms":
520            host_sub_id = get_outgoing_message_sub_id(ad_host)
521        else:
522            host_sub_id = get_incoming_voice_sub_id(ad_host)
523    host_mcc = ad_host.telephony["subscription"][host_sub_id]["mcc"]
524    host_mnc = ad_host.telephony["subscription"][host_sub_id]["mnc"]
525    p1_sub_id = INVALID_SUB_ID
526    p2_sub_id = INVALID_SUB_ID
527    p1_mcc = None
528    p1_mnc = None
529    p2_mcc = None
530    p2_mnc = None
531
532    for ad in [ad_p1, ad_p2]:
533        if ad:
534            for sub_id in ad.telephony["subscription"]:
535                mcc = ad.telephony["subscription"][sub_id]["mcc"]
536                mnc = ad.telephony["subscription"][sub_id]["mnc"]
537
538                if ad == ad_p1:
539                    if p1_sub_id == INVALID_SUB_ID:
540                        p1_sub_id = sub_id
541                    if not p1_mcc:
542                        p1_mcc = mcc
543                    if not p1_mnc:
544                        p1_mnc = mnc
545                elif ad == ad_p2:
546                    if p2_sub_id == INVALID_SUB_ID:
547                        p2_sub_id = sub_id
548                    if not p2_mcc:
549                        p2_mcc = mcc
550                    if not p2_mnc:
551                        p2_mnc = mnc
552
553                if mcc == host_mcc and mnc == host_mnc:
554                    if ad == ad_p1:
555                        p1_sub_id = sub_id
556                        p1_mcc = mcc
557                        p1_mnc = mnc
558
559                    elif ad == ad_p2:
560                        p2_sub_id = sub_id
561                        p2_mcc = mcc
562                        p2_mnc = mnc
563
564    return host_sub_id, p1_sub_id, p2_sub_id
565
566
567def get_slot_index_from_subid(ad, sub_id):
568    try:
569        info = ad.droid.subscriptionGetSubInfoForSubscriber(sub_id)
570        return info['simSlotIndex']
571    except KeyError:
572        return INVALID_SIM_SLOT_INDEX
573
574
575def get_slot_index_from_data_sub_id(ad):
576    """Get slot index from given sub ID for data
577
578    Args:
579        ad: Android object
580
581    Returns:
582        0 for pSIM or 1 for eSIM. Otherwise -1 will be returned.
583    """
584    data_sub_id = get_default_data_sub_id(ad)
585    sub_info = ad.droid.subscriptionGetAllSubInfoList()
586    for info in sub_info:
587        if info['subscriptionId'] == data_sub_id:
588            return info['simSlotIndex']
589    return INVALID_SUB_ID
590
591
592def get_slot_index_from_voice_sub_id(ad):
593    """Get slot index from the current voice sub ID.
594
595    Args:
596        ad: android object
597
598    Returns:
599        0: pSIM
600        1: eSIM
601        INVALID_SUB_ID (-1): if no sub ID is equal to current voice sub ID.
602    """
603    voice_sub_id = get_incoming_voice_sub_id(ad)
604    sub_info = ad.droid.subscriptionGetAllSubInfoList()
605    for info in sub_info:
606        if info['subscriptionId'] == voice_sub_id:
607            return info['simSlotIndex']
608    return INVALID_SUB_ID
609
610
611def get_all_sub_id(ad):
612    """Return all valid subscription IDs.
613
614    Args:
615        ad: Android object
616
617    Returns:
618        List containing all valid subscription IDs.
619    """
620    sub_id_list = []
621    sub_info = ad.droid.subscriptionGetAllSubInfoList()
622    for info in sub_info:
623        if info['simSlotIndex'] != INVALID_SUB_ID:
624            sub_id_list.append(info['subscriptionId'])
625
626    return sub_id_list