• 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    Basic script for managing a JSON "database" file of SIM cards.
18    It will look at the list of attached devices, and add their SIMs to a
19    database.
20    We expect to add much more functionality in the future.
21"""
22
23import argparse
24import json
25import acts.controllers.android_device as android_device
26import acts_contrib.test_utils.tel.tel_defines as tel_defines
27import acts_contrib.test_utils.tel.tel_lookup_tables as tel_lookup_tables
28import acts_contrib.test_utils.tel.tel_test_utils as tel_test_utils
29
30
31def get_active_sim_list(verbose_warnings=False):
32    """ Get a dictionary of active sims across phones
33
34    Args: verbose_warnings - print warnings as issues are encountered if True
35
36    Returns:
37        A dictionary with keys equivalent to the ICCIDs of each SIM containing
38        information about that SIM
39    """
40    active_list = {}
41    droid_list = android_device.get_all_instances()
42    for droid_device in droid_list:
43        droid = droid_device.get_droid(False)
44
45        sub_info_list = droid.subscriptionGetActiveSubInfoList()
46        if not sub_info_list:
47            if verbose_warnings:
48                print('No Valid Sim in {} {}! SimState = {}'.format(
49                    droid_device.model, droid_device.serial, droid.telephonyGetSimState()))
50            continue
51
52        for sub_info in sub_info_list:
53            print(sub_info)
54            iccid = sub_info['iccId']
55            if not sub_info['iccId']:
56                continue
57
58            active_list[iccid] = {}
59            current = active_list[iccid]
60            current['droid_serial'] = droid_device.serial
61
62            sub_id = sub_info['subscriptionId']
63
64            try:
65                plmn_id = droid.telephonyGetSimOperatorForSubscription(sub_id)
66                current[
67                    'operator'] = tel_lookup_tables.operator_name_from_plmn_id(
68                        plmn_id)
69            except KeyError:
70                if verbose_warnings:
71                    print('Unknown Operator {}'.format(
72                        droid.telephonyGetSimOperatorForSubscription(sub_id)))
73                current['operator'] = ''
74
75            # TODO: add actual capability determination to replace the defaults
76            current['capability'] = ['voice', 'ims', 'volte', 'vt', 'sms',
77                                     'tethering', 'data']
78
79            phone_num = droid.telephonyGetLine1NumberForSubscription(sub_id)
80            if not phone_num:
81                if verbose_warnings:
82                    print('Please manually add a phone number for {}\n'.format(
83                        iccid))
84                current['phone_num'] = ''
85            else:
86                # No need to set phone number formatter for South Korea carriers
87                if (current['operator'] == tel_defines.CARRIER_SKT or
88                    current['operator'] == tel_defines.CARRIER_KT or
89                    current['operator'] == tel_defines.CARRIER_LG_UPLUS):
90                    current['phone_num'] = \
91                        tel_test_utils.phone_number_formatter(phone_num)
92                else:
93                    current['phone_num'] = \
94                        tel_test_utils.phone_number_formatter(
95                            phone_num,
96                            tel_defines.PHONE_NUMBER_STRING_FORMAT_11_DIGIT)
97    return active_list
98
99
100def add_sims(sim_card_file=None):
101    if not sim_card_file:
102        print('Error: file name is None.')
103        return False
104    try:
105        f = open(sim_card_file, 'r')
106        simconf = json.load(f)
107        f.close()
108    except FileNotFoundError:
109        simconf = {}
110
111    active_sims = get_active_sim_list(True)
112
113    if not active_sims:
114        print('No active SIMs, exiting')
115        return False
116
117    file_write_required = False
118
119    for iccid in active_sims.keys():
120        # Add new entry if not exist
121        if iccid in simconf:
122            print('Declining to add a duplicate entry: {}'.format(iccid))
123            #TODO: Add support for "refreshing" an entry
124            continue
125
126        simconf[iccid] = {}
127        current = simconf[iccid]
128        file_write_required = True
129
130        current['operator'] = active_sims[iccid]['operator']
131        current['capability'] = active_sims[iccid]['capability']
132        current['phone_num'] = active_sims[iccid]['phone_num']
133
134    if file_write_required:
135        f = open(sim_card_file, 'w')
136        json.dump(simconf, f, indent=4, sort_keys=True)
137        f.close()
138    return True
139
140
141def prune_sims(sim_card_file=None):
142    try:
143        f = open(sim_card_file, 'r')
144        simconf = json.load(f)
145        f.close()
146    except FileNotFoundError:
147        print('File {} not found.'.format(sim_card_file if sim_card_file else
148                                          '<UNSPECIFIED>'))
149        return False
150
151    simconf_list = list(simconf.keys())
152    active_list = get_active_sim_list().keys()
153    delete_list = list(set(simconf_list).difference(set(active_list)))
154
155    print('active phones: {}'.format(active_list))
156
157    file_write_required = False
158
159    if len(delete_list) > 0:
160        for sim in delete_list:
161            # prune
162            print('Deleting the SIM entry: ', sim)
163            del simconf[sim]
164            file_write_required = True
165    else:
166        print('No entries to prune')
167
168    if file_write_required:
169        f = open(sim_card_file, 'w')
170        json.dump(simconf, f, indent=4, sort_keys=True)
171        f.close()
172    return True
173
174
175def dump_sims():
176    active_list = get_active_sim_list()
177    output_format = '{:32.32}{:20.20}{:12.12}{:10.10}'
178    if not active_list:
179        print('No active devices with sims!')
180        return False
181
182    print(output_format.format('ICCID', 'Android SN', 'Phone #', 'Carrier'))
183    for iccid in active_list.keys():
184        print(
185            output_format.format(
186                str(iccid), str(active_list[iccid]['droid_serial']), str(
187                    active_list[iccid]['phone_num']), str(active_list[iccid][
188                        'operator'])))
189
190
191if __name__ == '__main__':
192
193    parser = argparse.ArgumentParser(description=(
194        'Script to generate, augment and prune'
195        ' SIM list'))
196    parser.add_argument(
197        '-f',
198        '--file',
199        default='./simcard_list.json',
200        help='json file path',
201        type=str)
202    group = parser.add_mutually_exclusive_group()
203    group.add_argument(
204        '-a',
205        '--append',
206        help='(default) Append to the list of SIM entries',
207        action='store_true')
208    group.add_argument(
209        '-p',
210        '--prune',
211        help='Prune the list of SIM entries',
212        action='store_true')
213    group.add_argument(
214        '-d',
215        '--dump',
216        help='Dump a list of SIMs from devices',
217        action='store_true')
218
219    args = parser.parse_args()
220
221    if args.prune:
222        prune_sims(args.file)
223    elif args.dump:
224        dump_sims()
225    # implies either no arguments or a && !p
226    elif not args.prune and not args.dump:
227        add_sims(args.file)
228"""
229Usage Examples
230
231----------------------------------------------------------------
232p3 manage_sim.py -h
233usage: manage_sim.py [-h] [-f F] [-a | -p]
234
235Script to generate, augment and prune SIM list
236
237optional arguments:
238  -h, --help      show this help message and exit
239  -f F, --file F  name for json file
240  -a              append to the list of SIM entries
241  -d              dump a list of SIMs from all devices
242  -p              prune the list of SIM entries
243
244----------------------------------------------------------------
245p3 manage_sim.py -f ./simcard_list.json -p
246        OR
247p3 manage_sim.py -p
248
249Namespace(a=False, f='./simcard_list.json', p=True)
250add_sims: 8901260222780922759
251Please manually add a phone number for 8901260222780922759
252
253active phones: 1
254 ['8901260222780922759']
255Deleting the SIM entry:  89148000001280331488
256:
257:
258Deleting the SIM entry:  89014103277559059196
259
260----------------------------------------------------------------
261p3 manage_sim.py -f ./simcard_list.json -a
262        OR
263p3 manage_sim.py -a
264
265Namespace(a=True, f='./simcard_list.json', p=False)
266add_sims: 8901260222780922759
267Please manually add a phone number for 8901260222780922759
268
269----------------------------------------------------------------
270"""
271