#!/usr/bin/env python3.4 # # Copyright 2016 - Google # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ Basic script for managing a JSON "database" file of SIM cards. It will look at the list of attached devices, and add their SIMs to a database. We expect to add much more functionality in the future. """ import argparse import json import acts.controllers.android_device as android_device import acts_contrib.test_utils.tel.tel_defines as tel_defines import acts_contrib.test_utils.tel.tel_lookup_tables as tel_lookup_tables import acts_contrib.test_utils.tel.tel_test_utils as tel_test_utils def get_active_sim_list(verbose_warnings=False): """ Get a dictionary of active sims across phones Args: verbose_warnings - print warnings as issues are encountered if True Returns: A dictionary with keys equivalent to the ICCIDs of each SIM containing information about that SIM """ active_list = {} droid_list = android_device.get_all_instances() for droid_device in droid_list: droid = droid_device.get_droid(False) sub_info_list = droid.subscriptionGetActiveSubInfoList() if not sub_info_list: if verbose_warnings: print('No Valid Sim in {} {}! SimState = {}'.format( droid_device.model, droid_device.serial, droid.telephonyGetSimState())) continue for sub_info in sub_info_list: print(sub_info) iccid = sub_info['iccId'] if not sub_info['iccId']: continue active_list[iccid] = {} current = active_list[iccid] current['droid_serial'] = droid_device.serial sub_id = sub_info['subscriptionId'] try: plmn_id = droid.telephonyGetSimOperatorForSubscription(sub_id) current[ 'operator'] = tel_lookup_tables.operator_name_from_plmn_id( plmn_id) except KeyError: if vebose_warnings: print('Unknown Operator {}'.format( droid.telephonyGetSimOperator())) current['operator'] = '' # TODO: add actual capability determination to replace the defaults current['capability'] = ['voice', 'ims', 'volte', 'vt', 'sms', 'tethering', 'data'] phone_num = droid.telephonyGetLine1NumberForSubscription(sub_id) if not phone_num: if verbose_warnings: print('Please manually add a phone number for {}\n'.format( iccid)) current['phone_num'] = '' else: current['phone_num'] = tel_test_utils.phone_number_formatter( phone_num, tel_defines.PHONE_NUMBER_STRING_FORMAT_11_DIGIT) return active_list def add_sims(sim_card_file=None): if not sim_card_file: print('Error: file name is None.') return False try: f = open(sim_card_file, 'r') simconf = json.load(f) f.close() except FileNotFoundError: simconf = {} active_sims = get_active_sim_list(True) if not active_sims: print('No active SIMs, exiting') return False file_write_required = False for iccid in active_sims.keys(): # Add new entry if not exist if iccid in simconf: print('Declining to add a duplicate entry: {}'.format(iccid)) #TODO: Add support for "refreshing" an entry continue simconf[iccid] = {} current = simconf[iccid] file_write_required = True current['operator'] = active_sims[iccid]['operator'] current['capability'] = active_sims[iccid]['capability'] current['phone_num'] = active_sims[iccid]['phone_num'] if file_write_required: f = open(sim_card_file, 'w') json.dump(simconf, f, indent=4, sort_keys=True) f.close() return True def prune_sims(sim_card_file=None): try: f = open(sim_card_file, 'r') simconf = json.load(f) f.close() except FileNotFoundError: print('File {} not found.'.format(sim_card_file if sim_card_file else '')) return False simconf_list = list(simconf.keys()) active_list = get_active_sim_list().keys() delete_list = list(set(simconf_list).difference(set(active_list))) print('active phones: {}'.format(active_list)) file_write_required = False if len(delete_list) > 0: for sim in delete_list: # prune print('Deleting the SIM entry: ', sim) del simconf[sim] file_write_required = True else: print('No entries to prune') if file_write_required: f = open(sim_card_file, 'w') json.dump(simconf, f, indent=4, sort_keys=True) f.close() return True def dump_sims(): active_list = get_active_sim_list() output_format = '{:32.32}{:20.20}{:12.12}{:10.10}' if not active_list: print('No active devices with sims!') return False print(output_format.format('ICCID', 'Android SN', 'Phone #', 'Carrier')) for iccid in active_list.keys(): print( output_format.format( str(iccid), str(active_list[iccid]['droid_serial']), str( active_list[iccid]['phone_num']), str(active_list[iccid][ 'operator']))) if __name__ == '__main__': parser = argparse.ArgumentParser(description=( 'Script to generate, augment and prune' ' SIM list')) parser.add_argument( '-f', '--file', default='./simcard_list.json', help='json file path', type=str) group = parser.add_mutually_exclusive_group() group.add_argument( '-a', '--append', help='(default) Append to the list of SIM entries', action='store_true') group.add_argument( '-p', '--prune', help='Prune the list of SIM entries', action='store_true') group.add_argument( '-d', '--dump', help='Dump a list of SIMs from devices', action='store_true') args = parser.parse_args() if args.prune: prune_sims(args.file) elif args.dump: dump_sims() # implies either no arguments or a && !p elif not args.prune and not args.dump: add_sims(args.file) """ Usage Examples ---------------------------------------------------------------- p3 manage_sim.py -h usage: manage_sim.py [-h] [-f F] [-a | -p] Script to generate, augment and prune SIM list optional arguments: -h, --help show this help message and exit -f F, --file F name for json file -a append to the list of SIM entries -d dump a list of SIMs from all devices -p prune the list of SIM entries ---------------------------------------------------------------- p3 manage_sim.py -f ./simcard_list.json -p OR p3 manage_sim.py -p Namespace(a=False, f='./simcard_list.json', p=True) add_sims: 8901260222780922759 Please manually add a phone number for 8901260222780922759 active phones: 1 ['8901260222780922759'] Deleting the SIM entry: 89148000001280331488 : : Deleting the SIM entry: 89014103277559059196 ---------------------------------------------------------------- p3 manage_sim.py -f ./simcard_list.json -a OR p3 manage_sim.py -a Namespace(a=True, f='./simcard_list.json', p=False) add_sims: 8901260222780922759 Please manually add a phone number for 8901260222780922759 ---------------------------------------------------------------- """