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