blob: ed719b6ce18d59c42e1330042e7ad95099168abc [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010019import android.content.Context;
Hall Liud892bec2018-11-30 14:51:45 -080020import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010021import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080022import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070023import android.os.RemoteException;
Shuo Qian489d9282020-07-09 11:30:03 -070024import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070026import android.telephony.SubscriptionManager;
sqian9d4df8b2019-01-15 18:32:07 -080027import android.telephony.emergency.EmergencyNumber;
Brad Ebinger24c29992019-12-05 13:03:21 -080028import android.telephony.ims.feature.ImsFeature;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070029import android.util.Log;
30
31import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080032import com.android.internal.telephony.Phone;
33import com.android.internal.telephony.PhoneFactory;
sqian9d4df8b2019-01-15 18:32:07 -080034import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080035import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080036import com.android.modules.utils.BasicShellCommandHandler;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070037
38import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080039import java.util.ArrayList;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010040import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080041import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010042import java.util.Map;
43import java.util.TreeSet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070044
45/**
46 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
47 * permission checks have been done before onCommand was called. Make sure any commands processed
48 * here also contain the appropriate permissions checks.
49 */
50
Hall Liua1548bd2019-12-24 14:14:12 -080051public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052
53 private static final String LOG_TAG = "TelephonyShellCommand";
54 // Don't commit with this true.
55 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070056 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070057
58 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080059 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080060 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070061 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010062 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080063 private static final String DATA_TEST_MODE = "data";
64 private static final String DATA_ENABLE = "enable";
65 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080066
Brad Ebinger999d3302020-11-25 14:31:39 -080067 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
68 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
69 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070 private static final String IMS_ENABLE = "enable";
71 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070072 // Used to disable or enable processing of conference event package data from the network.
73 // This is handy for testing scenarios where CEP data does not exist on a network which does
74 // support CEP data.
75 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070076
Hall Liud892bec2018-11-30 14:51:45 -080077 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080078 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080079
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010080 private static final String CC_GET_VALUE = "get-value";
81 private static final String CC_SET_VALUE = "set-value";
82 private static final String CC_CLEAR_VALUES = "clear-values";
83
Hui Wang641e81c2020-10-12 12:14:23 -070084 private static final String GBA_SUBCOMMAND = "gba";
85 private static final String GBA_SET_SERVICE = "set-service";
86 private static final String GBA_GET_SERVICE = "get-service";
87 private static final String GBA_SET_RELEASE_TIME = "set-release";
88 private static final String GBA_GET_RELEASE_TIME = "get-release";
89
Hui Wang761a6682020-10-31 05:12:53 +000090 private static final String SINGLE_REGISTATION_CONFIG = "src";
91 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
92 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
93 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
94 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
95
Brad Ebinger4dc095a2018-04-03 15:17:52 -070096 // Take advantage of existing methods that already contain permissions checks when possible.
97 private final ITelephony mInterface;
98
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010099 private SubscriptionManager mSubscriptionManager;
100 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700101 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100102
103 private enum CcType {
104 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
105 STRING_ARRAY, UNKNOWN
106 }
107
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100108 private class CcOptionParseResult {
109 public int mSubId;
110 public boolean mPersistent;
111 }
112
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100113 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
114 // keys by looking at the end of the string which usually tells the type.
115 // For instance: "xxxx_string", "xxxx_string_array", etc.
116 // The carrier config keys in this map does not follow this convention. It is therefore not
117 // possible to infer the type for these keys by looking at the string.
118 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
119 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
120 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
121 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
122 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
123 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
124 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
125 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
126 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
127 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
128 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
129 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
130 CcType.STRING);
131 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
132 CcType.STRING_ARRAY);
133 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
134 CcType.STRING_ARRAY);
135 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
136 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
137 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
138 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
139 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
140 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
141 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
142 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
143 }
144 };
145
146 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700147 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100148 mCarrierConfigManager =
149 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
150 mSubscriptionManager = (SubscriptionManager)
151 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700152 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700153 }
154
155 @Override
156 public int onCommand(String cmd) {
157 if (cmd == null) {
158 return handleDefaultCommands(null);
159 }
160
161 switch (cmd) {
162 case IMS_SUBCOMMAND: {
163 return handleImsCommand();
164 }
Hall Liud892bec2018-11-30 14:51:45 -0800165 case NUMBER_VERIFICATION_SUBCOMMAND:
166 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800167 case EMERGENCY_NUMBER_TEST_MODE:
168 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100169 case CARRIER_CONFIG_SUBCOMMAND: {
170 return handleCcCommand();
171 }
Shuo Qianf5125122019-12-16 17:03:07 -0800172 case DATA_TEST_MODE:
173 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700174 case END_BLOCK_SUPPRESSION:
175 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700176 case GBA_SUBCOMMAND:
177 return handleGbaCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000178 case SINGLE_REGISTATION_CONFIG:
179 return handleSingleRegistrationConfigCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700180 default: {
181 return handleDefaultCommands(cmd);
182 }
183 }
184 }
185
186 @Override
187 public void onHelp() {
188 PrintWriter pw = getOutPrintWriter();
189 pw.println("Telephony Commands:");
190 pw.println(" help");
191 pw.println(" Print this help text.");
192 pw.println(" ims");
193 pw.println(" IMS Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800194 pw.println(" emergency-number-test-mode");
195 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700196 pw.println(" end-block-suppression");
197 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800198 pw.println(" data");
199 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100200 pw.println(" cc");
201 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700202 pw.println(" gba");
203 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000204 pw.println(" src");
205 pw.println(" RCS VoLTE Single Registration Config Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700206 onHelpIms();
sqian9d4df8b2019-01-15 18:32:07 -0800207 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700208 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800209 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100210 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700211 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000212 onHelpSrc();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700213 }
214
215 private void onHelpIms() {
216 PrintWriter pw = getOutPrintWriter();
217 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800218 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700219 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
220 pw.println(" ImsService. Options are:");
221 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
222 pw.println(" is specified, it will choose the default voice SIM slot.");
223 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
224 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800225 pw.println(" -f: Set the feature that this override if for, if no option is");
226 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700227 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
228 pw.println(" Gets the package name of the currently defined ImsService.");
229 pw.println(" Options are:");
230 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
231 pw.println(" is specified, it will choose the default voice SIM slot.");
232 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000233 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800234 pw.println(" -f: The feature type that the query will be requested for. If none is");
235 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800236 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
237 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
238 pw.println(" configuration overrides. Options are:");
239 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
240 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700241 pw.println(" ims enable [-s SLOT_ID]");
242 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
243 pw.println(" if none is specified.");
244 pw.println(" ims disable [-s SLOT_ID]");
245 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
246 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700247 pw.println(" ims conference-event-package [enable/disable]");
248 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700249 }
250
Hall Liud892bec2018-11-30 14:51:45 -0800251 private void onHelpNumberVerification() {
252 PrintWriter pw = getOutPrintWriter();
253 pw.println("Number verification commands");
254 pw.println(" numverify override-package PACKAGE_NAME;");
255 pw.println(" Set the authorized package for number verification.");
256 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800257 pw.println(" numverify fake-call NUMBER;");
258 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
259 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800260 }
261
Shuo Qianf5125122019-12-16 17:03:07 -0800262 private void onHelpDataTestMode() {
263 PrintWriter pw = getOutPrintWriter();
264 pw.println("Mobile Data Test Mode Commands:");
265 pw.println(" data enable: enable mobile data connectivity");
266 pw.println(" data disable: disable mobile data connectivity");
267 }
268
sqian9d4df8b2019-01-15 18:32:07 -0800269 private void onHelpEmergencyNumber() {
270 PrintWriter pw = getOutPrintWriter();
271 pw.println("Emergency Number Test Mode Commands:");
272 pw.println(" emergency-number-test-mode ");
273 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
274 + " the test mode");
275 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700276 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800277 pw.println(" -c: clear the emergency number list in the test mode.");
278 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700279 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800280 pw.println(" -p: get the full emergency number list in the test mode.");
281 }
282
Shuo Qian489d9282020-07-09 11:30:03 -0700283 private void onHelpEndBlockSupperssion() {
284 PrintWriter pw = getOutPrintWriter();
285 pw.println("End Block Suppression command:");
286 pw.println(" end-block-suppression: disable suppressing blocking by contact");
287 pw.println(" with emergency services.");
288 }
289
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100290 private void onHelpCc() {
291 PrintWriter pw = getOutPrintWriter();
292 pw.println("Carrier Config Commands:");
293 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
294 pw.println(" Print carrier config values.");
295 pw.println(" Options are:");
296 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
297 pw.println(" is specified, it will choose the default voice SIM slot.");
298 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
299 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100300 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100301 pw.println(" Set carrier config KEY to NEW_VALUE.");
302 pw.println(" Options are:");
303 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
304 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100305 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100306 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
307 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
308 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
309 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
310 pw.println(" cc clear-values [-s SLOT_ID]");
311 pw.println(" Clear all carrier override values that has previously been set");
312 pw.println(" with set-value");
313 pw.println(" Options are:");
314 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
315 pw.println(" is specified, it will choose the default voice SIM slot.");
316 }
317
Hui Wang641e81c2020-10-12 12:14:23 -0700318 private void onHelpGba() {
319 PrintWriter pw = getOutPrintWriter();
320 pw.println("Gba Commands:");
321 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
322 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
323 pw.println(" Options are:");
324 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
325 pw.println(" is specified, it will choose the default voice SIM slot.");
326 pw.println(" gba get-service [-s SLOT_ID]");
327 pw.println(" Gets the package name of the currently defined GbaService.");
328 pw.println(" Options are:");
329 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
330 pw.println(" is specified, it will choose the default voice SIM slot.");
331 pw.println(" gba set-release [-s SLOT_ID] n");
332 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
333 pw.println(" Do not release/unbind if n is -1.");
334 pw.println(" Options are:");
335 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
336 pw.println(" is specified, it will choose the default voice SIM slot.");
337 pw.println(" gba get-release [-s SLOT_ID]");
338 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
339 pw.println(" Options are:");
340 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
341 pw.println(" is specified, it will choose the default voice SIM slot.");
342 }
343
Hui Wang761a6682020-10-31 05:12:53 +0000344 private void onHelpSrc() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("RCS VoLTE Single Registration Config Commands:");
347 pw.println(" src set-device-enabled true|false|null");
348 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
349 pw.println(" The value could be true, false, or null(undefined).");
350 pw.println(" src get-device-enabled");
351 pw.println(" Gets the device config for RCS VoLTE single registration.");
352 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
353 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
354 pw.println(" The value could be true, false, or null(undefined).");
355 pw.println(" Options are:");
356 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
357 pw.println(" is specified, it will choose the default voice SIM slot.");
358 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
359 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
360 pw.println(" Options are:");
361 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
362 pw.println(" is specified, it will choose the default voice SIM slot.");
363 }
364
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700365 private int handleImsCommand() {
366 String arg = getNextArg();
367 if (arg == null) {
368 onHelpIms();
369 return 0;
370 }
371
372 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800373 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700374 return handleImsSetServiceCommand();
375 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800376 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700377 return handleImsGetServiceCommand();
378 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800379 case IMS_CLEAR_SERVICE_OVERRIDE: {
380 return handleImsClearCarrierServiceCommand();
381 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700382 case IMS_ENABLE: {
383 return handleEnableIms();
384 }
385 case IMS_DISABLE: {
386 return handleDisableIms();
387 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700388 case IMS_CEP: {
389 return handleCepChange();
390 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700391 }
392
393 return -1;
394 }
395
Shuo Qianf5125122019-12-16 17:03:07 -0800396 private int handleDataTestModeCommand() {
397 PrintWriter errPw = getErrPrintWriter();
398 String arg = getNextArgRequired();
399 if (arg == null) {
400 onHelpDataTestMode();
401 return 0;
402 }
403 switch (arg) {
404 case DATA_ENABLE: {
405 try {
406 mInterface.enableDataConnectivity();
407 } catch (RemoteException ex) {
408 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
409 errPw.println("Exception: " + ex.getMessage());
410 return -1;
411 }
412 break;
413 }
414 case DATA_DISABLE: {
415 try {
416 mInterface.disableDataConnectivity();
417 } catch (RemoteException ex) {
418 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
419 errPw.println("Exception: " + ex.getMessage());
420 return -1;
421 }
422 break;
423 }
424 default:
425 onHelpDataTestMode();
426 break;
427 }
428 return 0;
429 }
430
sqian9d4df8b2019-01-15 18:32:07 -0800431 private int handleEmergencyNumberTestModeCommand() {
432 PrintWriter errPw = getErrPrintWriter();
433 String opt = getNextOption();
434 if (opt == null) {
435 onHelpEmergencyNumber();
436 return 0;
437 }
438
439 switch (opt) {
440 case "-a": {
441 String emergencyNumberCmd = getNextArgRequired();
442 if (emergencyNumberCmd == null
443 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700444 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800445 + " to be specified after -a in the command ");
446 return -1;
447 }
448 try {
449 mInterface.updateEmergencyNumberListTestMode(
450 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
451 new EmergencyNumber(emergencyNumberCmd, "", "",
452 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
453 new ArrayList<String>(),
454 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
455 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
456 } catch (RemoteException ex) {
457 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
458 + ", error " + ex.getMessage());
459 errPw.println("Exception: " + ex.getMessage());
460 return -1;
461 }
462 break;
463 }
464 case "-c": {
465 try {
466 mInterface.updateEmergencyNumberListTestMode(
467 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
468 } catch (RemoteException ex) {
469 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
470 errPw.println("Exception: " + ex.getMessage());
471 return -1;
472 }
473 break;
474 }
475 case "-r": {
476 String emergencyNumberCmd = getNextArgRequired();
477 if (emergencyNumberCmd == null
478 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700479 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800480 + " to be specified after -r in the command ");
481 return -1;
482 }
483 try {
484 mInterface.updateEmergencyNumberListTestMode(
485 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
486 new EmergencyNumber(emergencyNumberCmd, "", "",
487 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
488 new ArrayList<String>(),
489 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
490 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
491 } catch (RemoteException ex) {
492 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
493 + ", error " + ex.getMessage());
494 errPw.println("Exception: " + ex.getMessage());
495 return -1;
496 }
497 break;
498 }
499 case "-p": {
500 try {
501 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
502 } catch (RemoteException ex) {
503 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
504 errPw.println("Exception: " + ex.getMessage());
505 return -1;
506 }
507 break;
508 }
509 default:
510 onHelpEmergencyNumber();
511 break;
512 }
513 return 0;
514 }
515
Hall Liud892bec2018-11-30 14:51:45 -0800516 private int handleNumberVerificationCommand() {
517 String arg = getNextArg();
518 if (arg == null) {
519 onHelpNumberVerification();
520 return 0;
521 }
522
Hall Liuca5af3a2018-12-04 16:58:23 -0800523 if (!checkShellUid()) {
524 return -1;
525 }
526
Hall Liud892bec2018-11-30 14:51:45 -0800527 switch (arg) {
528 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800529 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
530 return 0;
531 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800532 case NUMBER_VERIFICATION_FAKE_CALL: {
533 boolean val = NumberVerificationManager.getInstance()
534 .checkIncomingCall(getNextArg());
535 getOutPrintWriter().println(val ? "1" : "0");
536 return 0;
537 }
Hall Liud892bec2018-11-30 14:51:45 -0800538 }
539
540 return -1;
541 }
542
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700543 // ims set-ims-service
544 private int handleImsSetServiceCommand() {
545 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700546 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700547 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800548 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700549
550 String opt;
551 while ((opt = getNextOption()) != null) {
552 switch (opt) {
553 case "-s": {
554 try {
555 slotId = Integer.parseInt(getNextArgRequired());
556 } catch (NumberFormatException e) {
557 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
558 return -1;
559 }
560 break;
561 }
562 case "-c": {
563 isCarrierService = true;
564 break;
565 }
566 case "-d": {
567 isCarrierService = false;
568 break;
569 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800570 case "-f": {
571 String featureString = getNextArgRequired();
572 String[] features = featureString.split(",");
573 for (int i = 0; i < features.length; i++) {
574 try {
575 Integer result = Integer.parseInt(features[i]);
576 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
577 || result >= ImsFeature.FEATURE_MAX) {
578 errPw.println("ims set-ims-service -f " + result
579 + " is an invalid feature.");
580 return -1;
581 }
582 featuresList.add(result);
583 } catch (NumberFormatException e) {
584 errPw.println("ims set-ims-service -f tried to parse " + features[i]
585 + " as an integer.");
586 return -1;
587 }
588 }
589 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700590 }
591 }
592 // Mandatory param, either -c or -d
593 if (isCarrierService == null) {
594 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
595 return -1;
596 }
597
598 String packageName = getNextArg();
599
600 try {
601 if (packageName == null) {
602 packageName = "";
603 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800604 int[] featureArray = new int[featuresList.size()];
605 for (int i = 0; i < featuresList.size(); i++) {
606 featureArray[i] = featuresList.get(i);
607 }
608 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
609 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700610 if (VDBG) {
611 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800612 + (isCarrierService ? "-c " : "-d ")
613 + "-f " + featuresList + " "
614 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700615 }
616 getOutPrintWriter().println(result);
617 } catch (RemoteException e) {
618 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800619 + (isCarrierService ? "-c " : "-d ")
620 + "-f " + featuresList + " "
621 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700622 errPw.println("Exception: " + e.getMessage());
623 return -1;
624 }
625 return 0;
626 }
627
Brad Ebinger999d3302020-11-25 14:31:39 -0800628 // ims clear-ims-service-override
629 private int handleImsClearCarrierServiceCommand() {
630 PrintWriter errPw = getErrPrintWriter();
631 int slotId = getDefaultSlot();
632
633 String opt;
634 while ((opt = getNextOption()) != null) {
635 switch (opt) {
636 case "-s": {
637 try {
638 slotId = Integer.parseInt(getNextArgRequired());
639 } catch (NumberFormatException e) {
640 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
641 return -1;
642 }
643 break;
644 }
645 }
646 }
647
648 try {
649 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
650 if (VDBG) {
651 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
652 + ", result=" + result);
653 }
654 getOutPrintWriter().println(result);
655 } catch (RemoteException e) {
656 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
657 + ", error" + e.getMessage());
658 errPw.println("Exception: " + e.getMessage());
659 return -1;
660 }
661 return 0;
662 }
663
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700664 // ims get-ims-service
665 private int handleImsGetServiceCommand() {
666 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700667 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700668 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800669 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700670
671 String opt;
672 while ((opt = getNextOption()) != null) {
673 switch (opt) {
674 case "-s": {
675 try {
676 slotId = Integer.parseInt(getNextArgRequired());
677 } catch (NumberFormatException e) {
678 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
679 return -1;
680 }
681 break;
682 }
683 case "-c": {
684 isCarrierService = true;
685 break;
686 }
687 case "-d": {
688 isCarrierService = false;
689 break;
690 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800691 case "-f": {
692 try {
693 featureType = Integer.parseInt(getNextArg());
694 } catch (NumberFormatException e) {
695 errPw.println("ims get-ims-service -f requires valid integer as feature.");
696 return -1;
697 }
698 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
699 || featureType >= ImsFeature.FEATURE_MAX) {
700 errPw.println("ims get-ims-service -f invalid feature.");
701 return -1;
702 }
703 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700704 }
705 }
706 // Mandatory param, either -c or -d
707 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800708 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700709 return -1;
710 }
711
712 String result;
713 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800714 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700715 } catch (RemoteException e) {
716 return -1;
717 }
718 if (VDBG) {
719 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800720 + (isCarrierService ? "-c " : "-d ")
721 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
722 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700723 }
724 getOutPrintWriter().println(result);
725 return 0;
726 }
727
728 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700729 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700730 String opt;
731 while ((opt = getNextOption()) != null) {
732 switch (opt) {
733 case "-s": {
734 try {
735 slotId = Integer.parseInt(getNextArgRequired());
736 } catch (NumberFormatException e) {
737 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
738 return -1;
739 }
740 break;
741 }
742 }
743 }
744 try {
745 mInterface.enableIms(slotId);
746 } catch (RemoteException e) {
747 return -1;
748 }
749 if (VDBG) {
750 Log.v(LOG_TAG, "ims enable -s " + slotId);
751 }
752 return 0;
753 }
754
755 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700756 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700757 String opt;
758 while ((opt = getNextOption()) != null) {
759 switch (opt) {
760 case "-s": {
761 try {
762 slotId = Integer.parseInt(getNextArgRequired());
763 } catch (NumberFormatException e) {
764 getErrPrintWriter().println(
765 "ims disable requires an integer as a SLOT_ID.");
766 return -1;
767 }
768 break;
769 }
770 }
771 }
772 try {
773 mInterface.disableIms(slotId);
774 } catch (RemoteException e) {
775 return -1;
776 }
777 if (VDBG) {
778 Log.v(LOG_TAG, "ims disable -s " + slotId);
779 }
780 return 0;
781 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700782
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700783 private int handleCepChange() {
784 Log.i(LOG_TAG, "handleCepChange");
785 String opt = getNextArg();
786 if (opt == null) {
787 return -1;
788 }
789 boolean isCepEnabled = opt.equals("enable");
790
791 try {
792 mInterface.setCepEnabled(isCepEnabled);
793 } catch (RemoteException e) {
794 return -1;
795 }
796 return 0;
797 }
798
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700799 private int getDefaultSlot() {
800 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
801 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
802 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
803 // If there is no default, default to slot 0.
804 slotId = DEFAULT_PHONE_ID;
805 }
806 return slotId;
807 }
sqian2fff4a32018-11-05 14:18:37 -0800808
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100809 // Parse options related to Carrier Config Commands.
810 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100811 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100812 CcOptionParseResult result = new CcOptionParseResult();
813 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
814 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100815
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100816 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100817 while ((opt = getNextOption()) != null) {
818 switch (opt) {
819 case "-s": {
820 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100821 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
822 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
823 errPw.println(tag + "No valid subscription found.");
824 return null;
825 }
826
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100827 } catch (IllegalArgumentException e) {
828 // Missing slot id
829 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100830 return null;
831 }
832 break;
833 }
834 case "-p": {
835 if (allowOptionPersistent) {
836 result.mPersistent = true;
837 } else {
838 errPw.println(tag + "Unexpected option " + opt);
839 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100840 }
841 break;
842 }
843 default: {
844 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100845 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100846 }
847 }
848 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100849 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100850 }
851
852 private int slotStringToSubId(String tag, String slotString) {
853 int slotId = -1;
854 try {
855 slotId = Integer.parseInt(slotString);
856 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800857 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
858 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
859 }
860
861 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100862 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
863 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
864 }
865
Qiong Liuf25799b2020-09-10 10:13:46 +0800866 Phone phone = PhoneFactory.getPhone(slotId);
867 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100868 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
869 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
870 }
Qiong Liuf25799b2020-09-10 10:13:46 +0800871 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100872 }
873
Hall Liud892bec2018-11-30 14:51:45 -0800874 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -0800875 // adb can run as root or as shell, depending on whether the device is rooted.
876 return Binder.getCallingUid() == Process.SHELL_UID
877 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -0800878 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100879
880 private int handleCcCommand() {
881 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
882 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -0800883 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100884 getErrPrintWriter().println("cc: Permission denied.");
885 return -1;
886 }
887
888 String arg = getNextArg();
889 if (arg == null) {
890 onHelpCc();
891 return 0;
892 }
893
894 switch (arg) {
895 case CC_GET_VALUE: {
896 return handleCcGetValue();
897 }
898 case CC_SET_VALUE: {
899 return handleCcSetValue();
900 }
901 case CC_CLEAR_VALUES: {
902 return handleCcClearValues();
903 }
904 default: {
905 getErrPrintWriter().println("cc: Unknown argument: " + arg);
906 }
907 }
908 return -1;
909 }
910
911 // cc get-value
912 private int handleCcGetValue() {
913 PrintWriter errPw = getErrPrintWriter();
914 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
915 String key = null;
916
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100917 // Parse all options
918 CcOptionParseResult options = parseCcOptions(tag, false);
919 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100920 return -1;
921 }
922
923 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100924 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100925 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100926 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100927 return -1;
928 }
929
930 // Get the key.
931 key = getNextArg();
932 if (key != null) {
933 // A key was provided. Verify if it is a valid key
934 if (!bundle.containsKey(key)) {
935 errPw.println(tag + key + " is not a valid key.");
936 return -1;
937 }
938
939 // Print the carrier config value for key.
940 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
941 } else {
942 // No key provided. Show all values.
943 // Iterate over a sorted list of all carrier config keys and print them.
944 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
945 for (String k : sortedSet) {
946 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
947 }
948 }
949 return 0;
950 }
951
952 // cc set-value
953 private int handleCcSetValue() {
954 PrintWriter errPw = getErrPrintWriter();
955 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
956
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100957 // Parse all options
958 CcOptionParseResult options = parseCcOptions(tag, true);
959 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100960 return -1;
961 }
962
963 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100964 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100965 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100966 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100967 return -1;
968 }
969
970 // Get the key.
971 String key = getNextArg();
972 if (key == null || key.equals("")) {
973 errPw.println(tag + "KEY is missing");
974 return -1;
975 }
976
977 // Verify if the key is valid
978 if (!originalValues.containsKey(key)) {
979 errPw.println(tag + key + " is not a valid key.");
980 return -1;
981 }
982
983 // Remaining arguments is a list of new values. Add them all into an ArrayList.
984 ArrayList<String> valueList = new ArrayList<String>();
985 while (peekNextArg() != null) {
986 valueList.add(getNextArg());
987 }
988
989 // Find the type of the carrier config value
990 CcType type = getType(tag, key, originalValues);
991 if (type == CcType.UNKNOWN) {
992 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
993 return -1;
994 }
995
996 // Create an override bundle containing the key and value that should be overriden.
997 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
998 if (overrideBundle == null) {
999 return -1;
1000 }
1001
1002 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001003 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001004
1005 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001006 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001007 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001008 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001009 return -1;
1010 }
1011
1012 // Print the original and new value.
1013 String originalValueString = ccValueToString(key, type, originalValues);
1014 String newValueString = ccValueToString(key, type, newValues);
1015 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1016 getOutPrintWriter().println("New value: \n" + newValueString);
1017
1018 return 0;
1019 }
1020
1021 // cc clear-values
1022 private int handleCcClearValues() {
1023 PrintWriter errPw = getErrPrintWriter();
1024 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1025
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001026 // Parse all options
1027 CcOptionParseResult options = parseCcOptions(tag, false);
1028 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001029 return -1;
1030 }
1031
1032 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001033 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001034 getOutPrintWriter()
1035 .println("All previously set carrier config override values has been cleared");
1036 return 0;
1037 }
1038
1039 private CcType getType(String tag, String key, PersistableBundle bundle) {
1040 // Find the type by checking the type of the current value stored in the bundle.
1041 Object value = bundle.get(key);
1042
1043 if (CC_TYPE_MAP.containsKey(key)) {
1044 return CC_TYPE_MAP.get(key);
1045 } else if (value != null) {
1046 if (value instanceof Boolean) {
1047 return CcType.BOOLEAN;
1048 } else if (value instanceof Double) {
1049 return CcType.DOUBLE;
1050 } else if (value instanceof double[]) {
1051 return CcType.DOUBLE_ARRAY;
1052 } else if (value instanceof Integer) {
1053 return CcType.INT;
1054 } else if (value instanceof int[]) {
1055 return CcType.INT_ARRAY;
1056 } else if (value instanceof Long) {
1057 return CcType.LONG;
1058 } else if (value instanceof long[]) {
1059 return CcType.LONG_ARRAY;
1060 } else if (value instanceof String) {
1061 return CcType.STRING;
1062 } else if (value instanceof String[]) {
1063 return CcType.STRING_ARRAY;
1064 }
1065 } else {
1066 // Current value was null and can therefore not be used in order to find the type.
1067 // Check the name of the key to infer the type. This check is not needed for primitive
1068 // data types (boolean, double, int and long), since they can not be null.
1069 if (key.endsWith("double_array")) {
1070 return CcType.DOUBLE_ARRAY;
1071 }
1072 if (key.endsWith("int_array")) {
1073 return CcType.INT_ARRAY;
1074 }
1075 if (key.endsWith("long_array")) {
1076 return CcType.LONG_ARRAY;
1077 }
1078 if (key.endsWith("string")) {
1079 return CcType.STRING;
1080 }
1081 if (key.endsWith("string_array") || key.endsWith("strings")) {
1082 return CcType.STRING_ARRAY;
1083 }
1084 }
1085
1086 // Not possible to infer the type by looking at the current value or the key.
1087 PrintWriter errPw = getErrPrintWriter();
1088 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1089 return CcType.UNKNOWN;
1090 }
1091
1092 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1093 String result;
1094 StringBuilder valueString = new StringBuilder();
1095 String typeString = type.toString();
1096 Object value = bundle.get(key);
1097
1098 if (value == null) {
1099 valueString.append("null");
1100 } else {
1101 switch (type) {
1102 case DOUBLE_ARRAY: {
1103 // Format the string representation of the int array as value1 value2......
1104 double[] valueArray = (double[]) value;
1105 for (int i = 0; i < valueArray.length; i++) {
1106 if (i != 0) {
1107 valueString.append(" ");
1108 }
1109 valueString.append(valueArray[i]);
1110 }
1111 break;
1112 }
1113 case INT_ARRAY: {
1114 // Format the string representation of the int array as value1 value2......
1115 int[] valueArray = (int[]) value;
1116 for (int i = 0; i < valueArray.length; i++) {
1117 if (i != 0) {
1118 valueString.append(" ");
1119 }
1120 valueString.append(valueArray[i]);
1121 }
1122 break;
1123 }
1124 case LONG_ARRAY: {
1125 // Format the string representation of the int array as value1 value2......
1126 long[] valueArray = (long[]) value;
1127 for (int i = 0; i < valueArray.length; i++) {
1128 if (i != 0) {
1129 valueString.append(" ");
1130 }
1131 valueString.append(valueArray[i]);
1132 }
1133 break;
1134 }
1135 case STRING: {
1136 valueString.append("\"" + value.toString() + "\"");
1137 break;
1138 }
1139 case STRING_ARRAY: {
1140 // Format the string representation of the string array as "value1" "value2"....
1141 String[] valueArray = (String[]) value;
1142 for (int i = 0; i < valueArray.length; i++) {
1143 if (i != 0) {
1144 valueString.append(" ");
1145 }
1146 if (valueArray[i] != null) {
1147 valueString.append("\"" + valueArray[i] + "\"");
1148 } else {
1149 valueString.append("null");
1150 }
1151 }
1152 break;
1153 }
1154 default: {
1155 valueString.append(value.toString());
1156 }
1157 }
1158 }
1159 return String.format("%-70s %-15s %s", key, typeString, valueString);
1160 }
1161
1162 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1163 ArrayList<String> valueList) {
1164 PrintWriter errPw = getErrPrintWriter();
1165 PersistableBundle bundle = new PersistableBundle();
1166
1167 // First verify that a valid number of values has been provided for the type.
1168 switch (type) {
1169 case BOOLEAN:
1170 case DOUBLE:
1171 case INT:
1172 case LONG: {
1173 if (valueList.size() != 1) {
1174 errPw.println(tag + "Expected 1 value for type " + type
1175 + ". Found: " + valueList.size());
1176 return null;
1177 }
1178 break;
1179 }
1180 case STRING: {
1181 if (valueList.size() > 1) {
1182 errPw.println(tag + "Expected 0 or 1 values for type " + type
1183 + ". Found: " + valueList.size());
1184 return null;
1185 }
1186 break;
1187 }
1188 }
1189
1190 // Parse the value according to type and add it to the Bundle.
1191 switch (type) {
1192 case BOOLEAN: {
1193 if ("true".equalsIgnoreCase(valueList.get(0))) {
1194 bundle.putBoolean(key, true);
1195 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1196 bundle.putBoolean(key, false);
1197 } else {
1198 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1199 return null;
1200 }
1201 break;
1202 }
1203 case DOUBLE: {
1204 try {
1205 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1206 } catch (NumberFormatException nfe) {
1207 // Not a valid double
1208 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1209 return null;
1210 }
1211 break;
1212 }
1213 case DOUBLE_ARRAY: {
1214 double[] valueDoubleArray = null;
1215 if (valueList.size() > 0) {
1216 valueDoubleArray = new double[valueList.size()];
1217 for (int i = 0; i < valueList.size(); i++) {
1218 try {
1219 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1220 } catch (NumberFormatException nfe) {
1221 // Not a valid double
1222 errPw.println(
1223 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1224 return null;
1225 }
1226 }
1227 }
1228 bundle.putDoubleArray(key, valueDoubleArray);
1229 break;
1230 }
1231 case INT: {
1232 try {
1233 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1234 } catch (NumberFormatException nfe) {
1235 // Not a valid integer
1236 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1237 return null;
1238 }
1239 break;
1240 }
1241 case INT_ARRAY: {
1242 int[] valueIntArray = null;
1243 if (valueList.size() > 0) {
1244 valueIntArray = new int[valueList.size()];
1245 for (int i = 0; i < valueList.size(); i++) {
1246 try {
1247 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1248 } catch (NumberFormatException nfe) {
1249 // Not a valid integer
1250 errPw.println(tag
1251 + "Unable to parse " + valueList.get(i) + " as an integer.");
1252 return null;
1253 }
1254 }
1255 }
1256 bundle.putIntArray(key, valueIntArray);
1257 break;
1258 }
1259 case LONG: {
1260 try {
1261 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1262 } catch (NumberFormatException nfe) {
1263 // Not a valid long
1264 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1265 return null;
1266 }
1267 break;
1268 }
1269 case LONG_ARRAY: {
1270 long[] valueLongArray = null;
1271 if (valueList.size() > 0) {
1272 valueLongArray = new long[valueList.size()];
1273 for (int i = 0; i < valueList.size(); i++) {
1274 try {
1275 valueLongArray[i] = Long.parseLong(valueList.get(i));
1276 } catch (NumberFormatException nfe) {
1277 // Not a valid long
1278 errPw.println(
1279 tag + "Unable to parse " + valueList.get(i) + " as a long");
1280 return null;
1281 }
1282 }
1283 }
1284 bundle.putLongArray(key, valueLongArray);
1285 break;
1286 }
1287 case STRING: {
1288 String value = null;
1289 if (valueList.size() > 0) {
1290 value = valueList.get(0);
1291 }
1292 bundle.putString(key, value);
1293 break;
1294 }
1295 case STRING_ARRAY: {
1296 String[] valueStringArray = null;
1297 if (valueList.size() > 0) {
1298 valueStringArray = new String[valueList.size()];
1299 valueList.toArray(valueStringArray);
1300 }
1301 bundle.putStringArray(key, valueStringArray);
1302 break;
1303 }
1304 }
1305 return bundle;
1306 }
Shuo Qian489d9282020-07-09 11:30:03 -07001307
1308 private int handleEndBlockSuppressionCommand() {
1309 if (!checkShellUid()) {
1310 return -1;
1311 }
1312
1313 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1314 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1315 }
1316 return 0;
1317 }
Hui Wang641e81c2020-10-12 12:14:23 -07001318
1319 private int handleGbaCommand() {
1320 String arg = getNextArg();
1321 if (arg == null) {
1322 onHelpGba();
1323 return 0;
1324 }
1325
1326 switch (arg) {
1327 case GBA_SET_SERVICE: {
1328 return handleGbaSetServiceCommand();
1329 }
1330 case GBA_GET_SERVICE: {
1331 return handleGbaGetServiceCommand();
1332 }
1333 case GBA_SET_RELEASE_TIME: {
1334 return handleGbaSetReleaseCommand();
1335 }
1336 case GBA_GET_RELEASE_TIME: {
1337 return handleGbaGetReleaseCommand();
1338 }
1339 }
1340
1341 return -1;
1342 }
1343
1344 private int getSubId(String cmd) {
1345 int slotId = getDefaultSlot();
1346 String opt = getNextOption();
1347 if (opt != null && opt.equals("-s")) {
1348 try {
1349 slotId = Integer.parseInt(getNextArgRequired());
1350 } catch (NumberFormatException e) {
1351 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1352 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1353 }
1354 }
1355 int[] subIds = SubscriptionManager.getSubId(slotId);
1356 return subIds[0];
1357 }
1358
1359 private int handleGbaSetServiceCommand() {
1360 int subId = getSubId("gba set-service");
1361 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1362 return -1;
1363 }
1364
1365 String packageName = getNextArg();
1366 try {
1367 if (packageName == null) {
1368 packageName = "";
1369 }
1370 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1371 if (VDBG) {
1372 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1373 + packageName + ", result=" + result);
1374 }
1375 getOutPrintWriter().println(result);
1376 } catch (RemoteException e) {
1377 Log.w(LOG_TAG, "gba set-service " + subId + " "
1378 + packageName + ", error" + e.getMessage());
1379 getErrPrintWriter().println("Exception: " + e.getMessage());
1380 return -1;
1381 }
1382 return 0;
1383 }
1384
1385 private int handleGbaGetServiceCommand() {
1386 String result;
1387
1388 int subId = getSubId("gba get-service");
1389 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1390 return -1;
1391 }
1392
1393 try {
1394 result = mInterface.getBoundGbaService(subId);
1395 } catch (RemoteException e) {
1396 return -1;
1397 }
1398 if (VDBG) {
1399 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1400 }
1401 getOutPrintWriter().println(result);
1402 return 0;
1403 }
1404
1405 private int handleGbaSetReleaseCommand() {
1406 //the release time value could be -1
1407 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1408 : SubscriptionManager.getDefaultSubscriptionId();
1409 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1410 return -1;
1411 }
1412
1413 String intervalStr = getNextArg();
1414 if (intervalStr == null) {
1415 return -1;
1416 }
1417
1418 try {
1419 int interval = Integer.parseInt(intervalStr);
1420 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1421 if (VDBG) {
1422 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1423 + intervalStr + ", result=" + result);
1424 }
1425 getOutPrintWriter().println(result);
1426 } catch (NumberFormatException | RemoteException e) {
1427 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1428 + intervalStr + ", error" + e.getMessage());
1429 getErrPrintWriter().println("Exception: " + e.getMessage());
1430 return -1;
1431 }
1432 return 0;
1433 }
1434
1435 private int handleGbaGetReleaseCommand() {
1436 int subId = getSubId("gba get-release");
1437 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1438 return -1;
1439 }
1440
1441 int result = 0;
1442 try {
1443 result = mInterface.getGbaReleaseTime(subId);
1444 } catch (RemoteException e) {
1445 return -1;
1446 }
1447 if (VDBG) {
1448 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1449 }
1450 getOutPrintWriter().println(result);
1451 return 0;
1452 }
Hui Wang761a6682020-10-31 05:12:53 +00001453
1454 private int handleSingleRegistrationConfigCommand() {
1455 String arg = getNextArg();
1456 if (arg == null) {
1457 onHelpSrc();
1458 return 0;
1459 }
1460
1461 switch (arg) {
1462 case SRC_SET_DEVICE_ENABLED: {
1463 return handleSrcSetDeviceEnabledCommand();
1464 }
1465 case SRC_GET_DEVICE_ENABLED: {
1466 return handleSrcGetDeviceEnabledCommand();
1467 }
1468 case SRC_SET_CARRIER_ENABLED: {
1469 return handleSrcSetCarrierEnabledCommand();
1470 }
1471 case SRC_GET_CARRIER_ENABLED: {
1472 return handleSrcGetCarrierEnabledCommand();
1473 }
1474 }
1475
1476 return -1;
1477 }
1478
1479 private int handleSrcSetDeviceEnabledCommand() {
1480 String enabledStr = getNextArg();
1481 if (enabledStr == null) {
1482 return -1;
1483 }
1484
1485 try {
1486 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1487 if (VDBG) {
1488 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1489 }
1490 getOutPrintWriter().println("Done");
1491 } catch (NumberFormatException | RemoteException e) {
1492 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1493 getErrPrintWriter().println("Exception: " + e.getMessage());
1494 return -1;
1495 }
1496 return 0;
1497 }
1498
1499 private int handleSrcGetDeviceEnabledCommand() {
1500 boolean result = false;
1501 try {
1502 result = mInterface.getDeviceSingleRegistrationEnabled();
1503 } catch (RemoteException e) {
1504 return -1;
1505 }
1506 if (VDBG) {
1507 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1508 }
1509 getOutPrintWriter().println(result);
1510 return 0;
1511 }
1512
1513 private int handleSrcSetCarrierEnabledCommand() {
1514 //the release time value could be -1
1515 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1516 : SubscriptionManager.getDefaultSubscriptionId();
1517 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1518 return -1;
1519 }
1520
1521 String enabledStr = getNextArg();
1522 if (enabledStr == null) {
1523 return -1;
1524 }
1525
1526 try {
1527 boolean result =
1528 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1529 if (VDBG) {
1530 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1531 + enabledStr + ", result=" + result);
1532 }
1533 getOutPrintWriter().println(result);
1534 } catch (NumberFormatException | RemoteException e) {
1535 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1536 + enabledStr + ", error" + e.getMessage());
1537 getErrPrintWriter().println("Exception: " + e.getMessage());
1538 return -1;
1539 }
1540 return 0;
1541 }
1542
1543 private int handleSrcGetCarrierEnabledCommand() {
1544 int subId = getSubId("src get-carrier-enabled");
1545 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1546 return -1;
1547 }
1548
1549 boolean result = false;
1550 try {
1551 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1552 } catch (RemoteException e) {
1553 return -1;
1554 }
1555 if (VDBG) {
1556 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1557 }
1558 getOutPrintWriter().println(result);
1559 return 0;
1560 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001561}