blob: d526e2ff9a3fba6e707aa31fb275325a735bf395 [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
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010024import android.content.Context;
Hall Liud892bec2018-11-30 14:51:45 -080025import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010026import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070028import android.os.RemoteException;
Shuo Qian489d9282020-07-09 11:30:03 -070029import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070031import android.telephony.SubscriptionManager;
Michele Berionne38c1afa2020-12-28 20:23:16 +000032import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080033import android.telephony.emergency.EmergencyNumber;
Brad Ebinger24c29992019-12-05 13:03:21 -080034import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080035import android.text.TextUtils;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.util.Log;
37
38import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080039import com.android.internal.telephony.Phone;
40import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080041import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080042import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080043import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080044import com.android.modules.utils.BasicShellCommandHandler;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070045
46import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080047import java.util.ArrayList;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010048import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080049import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010050import java.util.Map;
51import java.util.TreeSet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052
53/**
54 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
55 * permission checks have been done before onCommand was called. Make sure any commands processed
56 * here also contain the appropriate permissions checks.
57 */
58
Hall Liua1548bd2019-12-24 14:14:12 -080059public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070060
61 private static final String LOG_TAG = "TelephonyShellCommand";
62 // Don't commit with this true.
63 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070064 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070065
66 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080067 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080068 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070069 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne38c1afa2020-12-28 20:23:16 +000070 private static final String RESTART_MODEM = "restart-modem";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010071 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080072 private static final String DATA_TEST_MODE = "data";
73 private static final String DATA_ENABLE = "enable";
74 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080075
Brad Ebinger999d3302020-11-25 14:31:39 -080076 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
77 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
78 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070079 private static final String IMS_ENABLE = "enable";
80 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070081 // Used to disable or enable processing of conference event package data from the network.
82 // This is handy for testing scenarios where CEP data does not exist on a network which does
83 // support CEP data.
84 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085
Hall Liud892bec2018-11-30 14:51:45 -080086 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080087 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080088
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010089 private static final String CC_GET_VALUE = "get-value";
90 private static final String CC_SET_VALUE = "set-value";
91 private static final String CC_CLEAR_VALUES = "clear-values";
92
Hui Wang0866fcc2020-10-12 12:14:23 -070093 private static final String GBA_SUBCOMMAND = "gba";
94 private static final String GBA_SET_SERVICE = "set-service";
95 private static final String GBA_GET_SERVICE = "get-service";
96 private static final String GBA_SET_RELEASE_TIME = "set-release";
97 private static final String GBA_GET_RELEASE_TIME = "get-release";
98
Hui Wang068ab862020-10-31 05:12:53 +000099 private static final String SINGLE_REGISTATION_CONFIG = "src";
100 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
101 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
102 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
103 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
104
Tyler Gunn92479152021-01-20 16:30:10 -0800105 private static final String D2D_SUBCOMMAND = "d2d";
106 private static final String D2D_SEND = "send";
107
James.cf Linbcdf8b32021-01-14 16:44:13 +0800108 private static final String RCS_UCE_COMMAND = "uce";
109 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
110
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700111 // Take advantage of existing methods that already contain permissions checks when possible.
112 private final ITelephony mInterface;
113
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100114 private SubscriptionManager mSubscriptionManager;
115 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700116 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100117
118 private enum CcType {
119 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
120 STRING_ARRAY, UNKNOWN
121 }
122
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100123 private class CcOptionParseResult {
124 public int mSubId;
125 public boolean mPersistent;
126 }
127
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100128 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
129 // keys by looking at the end of the string which usually tells the type.
130 // For instance: "xxxx_string", "xxxx_string_array", etc.
131 // The carrier config keys in this map does not follow this convention. It is therefore not
132 // possible to infer the type for these keys by looking at the string.
133 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
134 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
135 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
136 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
137 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
138 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
139 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
140 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
141 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
142 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
143 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
145 CcType.STRING);
146 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
147 CcType.STRING_ARRAY);
148 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
149 CcType.STRING_ARRAY);
150 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
151 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
152 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
153 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
154 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
155 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
156 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
157 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
158 }
159 };
160
161 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700162 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100163 mCarrierConfigManager =
164 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
165 mSubscriptionManager = (SubscriptionManager)
166 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700167 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700168 }
169
170 @Override
171 public int onCommand(String cmd) {
172 if (cmd == null) {
173 return handleDefaultCommands(null);
174 }
175
176 switch (cmd) {
177 case IMS_SUBCOMMAND: {
178 return handleImsCommand();
179 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800180 case RCS_UCE_COMMAND:
181 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800182 case NUMBER_VERIFICATION_SUBCOMMAND:
183 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800184 case EMERGENCY_NUMBER_TEST_MODE:
185 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100186 case CARRIER_CONFIG_SUBCOMMAND: {
187 return handleCcCommand();
188 }
Shuo Qianf5125122019-12-16 17:03:07 -0800189 case DATA_TEST_MODE:
190 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700191 case END_BLOCK_SUPPRESSION:
192 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700193 case GBA_SUBCOMMAND:
194 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800195 case D2D_SUBCOMMAND:
196 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000197 case SINGLE_REGISTATION_CONFIG:
198 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000199 case RESTART_MODEM:
200 return handleRestartModemCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700201 default: {
202 return handleDefaultCommands(cmd);
203 }
204 }
205 }
206
207 @Override
208 public void onHelp() {
209 PrintWriter pw = getOutPrintWriter();
210 pw.println("Telephony Commands:");
211 pw.println(" help");
212 pw.println(" Print this help text.");
213 pw.println(" ims");
214 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800215 pw.println(" uce");
216 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800217 pw.println(" emergency-number-test-mode");
218 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700219 pw.println(" end-block-suppression");
220 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800221 pw.println(" data");
222 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100223 pw.println(" cc");
224 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700225 pw.println(" gba");
226 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000227 pw.println(" src");
228 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000229 pw.println(" restart-modem");
230 pw.println(" Restart modem command.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700231 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800232 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800233 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700234 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800235 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100236 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700237 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000238 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800239 onHelpD2D();
240 }
241
242 private void onHelpD2D() {
243 PrintWriter pw = getOutPrintWriter();
244 pw.println("D2D Comms Commands:");
245 pw.println(" d2d send TYPE VALUE");
246 pw.println(" Sends a D2D message of specified type and value.");
247 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
248 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
249 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
250 MESSAGE_CALL_AUDIO_CODEC));
251 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
252 + Communicator.messageToString(
253 MESSAGE_DEVICE_BATTERY_STATE));
254 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
255 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700256 }
257
258 private void onHelpIms() {
259 PrintWriter pw = getOutPrintWriter();
260 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800261 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700262 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
263 pw.println(" ImsService. Options are:");
264 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
265 pw.println(" is specified, it will choose the default voice SIM slot.");
266 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
267 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800268 pw.println(" -f: Set the feature that this override if for, if no option is");
269 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700270 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
271 pw.println(" Gets the package name of the currently defined ImsService.");
272 pw.println(" Options are:");
273 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
274 pw.println(" is specified, it will choose the default voice SIM slot.");
275 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000276 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800277 pw.println(" -f: The feature type that the query will be requested for. If none is");
278 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800279 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
280 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
281 pw.println(" configuration overrides. Options are:");
282 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
283 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700284 pw.println(" ims enable [-s SLOT_ID]");
285 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
286 pw.println(" if none is specified.");
287 pw.println(" ims disable [-s SLOT_ID]");
288 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
289 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700290 pw.println(" ims conference-event-package [enable/disable]");
291 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700292 }
293
James.cf Linbcdf8b32021-01-14 16:44:13 +0800294 private void onHelpUce() {
295 PrintWriter pw = getOutPrintWriter();
296 pw.println("User Capability Exchange Commands:");
297 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
298 pw.println(" Remove the EAB contacts from the EAB database.");
299 pw.println(" Options are:");
300 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
301 pw.println(" is specified, it will choose the default voice SIM slot.");
302 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
303 }
304
Hall Liud892bec2018-11-30 14:51:45 -0800305 private void onHelpNumberVerification() {
306 PrintWriter pw = getOutPrintWriter();
307 pw.println("Number verification commands");
308 pw.println(" numverify override-package PACKAGE_NAME;");
309 pw.println(" Set the authorized package for number verification.");
310 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800311 pw.println(" numverify fake-call NUMBER;");
312 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
313 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800314 }
315
Shuo Qianf5125122019-12-16 17:03:07 -0800316 private void onHelpDataTestMode() {
317 PrintWriter pw = getOutPrintWriter();
318 pw.println("Mobile Data Test Mode Commands:");
319 pw.println(" data enable: enable mobile data connectivity");
320 pw.println(" data disable: disable mobile data connectivity");
321 }
322
sqian9d4df8b2019-01-15 18:32:07 -0800323 private void onHelpEmergencyNumber() {
324 PrintWriter pw = getOutPrintWriter();
325 pw.println("Emergency Number Test Mode Commands:");
326 pw.println(" emergency-number-test-mode ");
327 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
328 + " the test mode");
329 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700330 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800331 pw.println(" -c: clear the emergency number list in the test mode.");
332 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700333 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800334 pw.println(" -p: get the full emergency number list in the test mode.");
335 }
336
Shuo Qian489d9282020-07-09 11:30:03 -0700337 private void onHelpEndBlockSupperssion() {
338 PrintWriter pw = getOutPrintWriter();
339 pw.println("End Block Suppression command:");
340 pw.println(" end-block-suppression: disable suppressing blocking by contact");
341 pw.println(" with emergency services.");
342 }
343
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100344 private void onHelpCc() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("Carrier Config Commands:");
347 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
348 pw.println(" Print carrier config values.");
349 pw.println(" Options are:");
350 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
351 pw.println(" is specified, it will choose the default voice SIM slot.");
352 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
353 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100354 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100355 pw.println(" Set carrier config KEY to NEW_VALUE.");
356 pw.println(" Options are:");
357 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
358 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100359 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100360 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
361 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
362 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
363 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
364 pw.println(" cc clear-values [-s SLOT_ID]");
365 pw.println(" Clear all carrier override values that has previously been set");
366 pw.println(" with set-value");
367 pw.println(" Options are:");
368 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
369 pw.println(" is specified, it will choose the default voice SIM slot.");
370 }
371
Hui Wang0866fcc2020-10-12 12:14:23 -0700372 private void onHelpGba() {
373 PrintWriter pw = getOutPrintWriter();
374 pw.println("Gba Commands:");
375 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
376 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
377 pw.println(" Options are:");
378 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
379 pw.println(" is specified, it will choose the default voice SIM slot.");
380 pw.println(" gba get-service [-s SLOT_ID]");
381 pw.println(" Gets the package name of the currently defined GbaService.");
382 pw.println(" Options are:");
383 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
384 pw.println(" is specified, it will choose the default voice SIM slot.");
385 pw.println(" gba set-release [-s SLOT_ID] n");
386 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
387 pw.println(" Do not release/unbind if n is -1.");
388 pw.println(" Options are:");
389 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
390 pw.println(" is specified, it will choose the default voice SIM slot.");
391 pw.println(" gba get-release [-s SLOT_ID]");
392 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
393 pw.println(" Options are:");
394 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
395 pw.println(" is specified, it will choose the default voice SIM slot.");
396 }
397
Hui Wang068ab862020-10-31 05:12:53 +0000398 private void onHelpSrc() {
399 PrintWriter pw = getOutPrintWriter();
400 pw.println("RCS VoLTE Single Registration Config Commands:");
401 pw.println(" src set-device-enabled true|false|null");
402 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
403 pw.println(" The value could be true, false, or null(undefined).");
404 pw.println(" src get-device-enabled");
405 pw.println(" Gets the device config for RCS VoLTE single registration.");
406 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
407 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
408 pw.println(" The value could be true, false, or null(undefined).");
409 pw.println(" Options are:");
410 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
411 pw.println(" is specified, it will choose the default voice SIM slot.");
412 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
413 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
414 pw.println(" Options are:");
415 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
416 pw.println(" is specified, it will choose the default voice SIM slot.");
417 }
418
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700419 private int handleImsCommand() {
420 String arg = getNextArg();
421 if (arg == null) {
422 onHelpIms();
423 return 0;
424 }
425
426 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800427 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700428 return handleImsSetServiceCommand();
429 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800430 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700431 return handleImsGetServiceCommand();
432 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800433 case IMS_CLEAR_SERVICE_OVERRIDE: {
434 return handleImsClearCarrierServiceCommand();
435 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700436 case IMS_ENABLE: {
437 return handleEnableIms();
438 }
439 case IMS_DISABLE: {
440 return handleDisableIms();
441 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700442 case IMS_CEP: {
443 return handleCepChange();
444 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700445 }
446
447 return -1;
448 }
449
Shuo Qianf5125122019-12-16 17:03:07 -0800450 private int handleDataTestModeCommand() {
451 PrintWriter errPw = getErrPrintWriter();
452 String arg = getNextArgRequired();
453 if (arg == null) {
454 onHelpDataTestMode();
455 return 0;
456 }
457 switch (arg) {
458 case DATA_ENABLE: {
459 try {
460 mInterface.enableDataConnectivity();
461 } catch (RemoteException ex) {
462 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
463 errPw.println("Exception: " + ex.getMessage());
464 return -1;
465 }
466 break;
467 }
468 case DATA_DISABLE: {
469 try {
470 mInterface.disableDataConnectivity();
471 } catch (RemoteException ex) {
472 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
473 errPw.println("Exception: " + ex.getMessage());
474 return -1;
475 }
476 break;
477 }
478 default:
479 onHelpDataTestMode();
480 break;
481 }
482 return 0;
483 }
484
sqian9d4df8b2019-01-15 18:32:07 -0800485 private int handleEmergencyNumberTestModeCommand() {
486 PrintWriter errPw = getErrPrintWriter();
487 String opt = getNextOption();
488 if (opt == null) {
489 onHelpEmergencyNumber();
490 return 0;
491 }
492
493 switch (opt) {
494 case "-a": {
495 String emergencyNumberCmd = getNextArgRequired();
496 if (emergencyNumberCmd == null
497 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700498 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800499 + " to be specified after -a in the command ");
500 return -1;
501 }
502 try {
503 mInterface.updateEmergencyNumberListTestMode(
504 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
505 new EmergencyNumber(emergencyNumberCmd, "", "",
506 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
507 new ArrayList<String>(),
508 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
509 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
510 } catch (RemoteException ex) {
511 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
512 + ", error " + ex.getMessage());
513 errPw.println("Exception: " + ex.getMessage());
514 return -1;
515 }
516 break;
517 }
518 case "-c": {
519 try {
520 mInterface.updateEmergencyNumberListTestMode(
521 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
522 } catch (RemoteException ex) {
523 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
524 errPw.println("Exception: " + ex.getMessage());
525 return -1;
526 }
527 break;
528 }
529 case "-r": {
530 String emergencyNumberCmd = getNextArgRequired();
531 if (emergencyNumberCmd == null
532 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700533 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800534 + " to be specified after -r in the command ");
535 return -1;
536 }
537 try {
538 mInterface.updateEmergencyNumberListTestMode(
539 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
540 new EmergencyNumber(emergencyNumberCmd, "", "",
541 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
542 new ArrayList<String>(),
543 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
544 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
545 } catch (RemoteException ex) {
546 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
547 + ", error " + ex.getMessage());
548 errPw.println("Exception: " + ex.getMessage());
549 return -1;
550 }
551 break;
552 }
553 case "-p": {
554 try {
555 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
556 } catch (RemoteException ex) {
557 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
558 errPw.println("Exception: " + ex.getMessage());
559 return -1;
560 }
561 break;
562 }
563 default:
564 onHelpEmergencyNumber();
565 break;
566 }
567 return 0;
568 }
569
Hall Liud892bec2018-11-30 14:51:45 -0800570 private int handleNumberVerificationCommand() {
571 String arg = getNextArg();
572 if (arg == null) {
573 onHelpNumberVerification();
574 return 0;
575 }
576
Hall Liuca5af3a2018-12-04 16:58:23 -0800577 if (!checkShellUid()) {
578 return -1;
579 }
580
Hall Liud892bec2018-11-30 14:51:45 -0800581 switch (arg) {
582 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800583 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
584 return 0;
585 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800586 case NUMBER_VERIFICATION_FAKE_CALL: {
587 boolean val = NumberVerificationManager.getInstance()
588 .checkIncomingCall(getNextArg());
589 getOutPrintWriter().println(val ? "1" : "0");
590 return 0;
591 }
Hall Liud892bec2018-11-30 14:51:45 -0800592 }
593
594 return -1;
595 }
596
Tyler Gunn92479152021-01-20 16:30:10 -0800597 private int handleD2dCommand() {
598 String arg = getNextArg();
599 if (arg == null) {
600 onHelpD2D();
601 return 0;
602 }
603
604 switch (arg) {
605 case D2D_SEND: {
606 return handleD2dSendCommand();
607 }
608 }
609
610 return -1;
611 }
612
613 private int handleD2dSendCommand() {
614 PrintWriter errPw = getErrPrintWriter();
615 String opt;
616 int messageType = -1;
617 int messageValue = -1;
618
619
620 String arg = getNextArg();
621 if (arg == null) {
622 onHelpD2D();
623 return 0;
624 }
625 try {
626 messageType = Integer.parseInt(arg);
627 } catch (NumberFormatException e) {
628 errPw.println("message type must be a valid integer");
629 return -1;
630 }
631
632 arg = getNextArg();
633 if (arg == null) {
634 onHelpD2D();
635 return 0;
636 }
637 try {
638 messageValue = Integer.parseInt(arg);
639 } catch (NumberFormatException e) {
640 errPw.println("message value must be a valid integer");
641 return -1;
642 }
643
644 try {
645 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
646 } catch (RemoteException e) {
647 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
648 errPw.println("Exception: " + e.getMessage());
649 return -1;
650 }
651
652 return 0;
653 }
654
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700655 // ims set-ims-service
656 private int handleImsSetServiceCommand() {
657 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700658 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700659 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800660 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700661
662 String opt;
663 while ((opt = getNextOption()) != null) {
664 switch (opt) {
665 case "-s": {
666 try {
667 slotId = Integer.parseInt(getNextArgRequired());
668 } catch (NumberFormatException e) {
669 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
670 return -1;
671 }
672 break;
673 }
674 case "-c": {
675 isCarrierService = true;
676 break;
677 }
678 case "-d": {
679 isCarrierService = false;
680 break;
681 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800682 case "-f": {
683 String featureString = getNextArgRequired();
684 String[] features = featureString.split(",");
685 for (int i = 0; i < features.length; i++) {
686 try {
687 Integer result = Integer.parseInt(features[i]);
688 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
689 || result >= ImsFeature.FEATURE_MAX) {
690 errPw.println("ims set-ims-service -f " + result
691 + " is an invalid feature.");
692 return -1;
693 }
694 featuresList.add(result);
695 } catch (NumberFormatException e) {
696 errPw.println("ims set-ims-service -f tried to parse " + features[i]
697 + " as an integer.");
698 return -1;
699 }
700 }
701 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700702 }
703 }
704 // Mandatory param, either -c or -d
705 if (isCarrierService == null) {
706 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
707 return -1;
708 }
709
710 String packageName = getNextArg();
711
712 try {
713 if (packageName == null) {
714 packageName = "";
715 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800716 int[] featureArray = new int[featuresList.size()];
717 for (int i = 0; i < featuresList.size(); i++) {
718 featureArray[i] = featuresList.get(i);
719 }
720 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
721 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700722 if (VDBG) {
723 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800724 + (isCarrierService ? "-c " : "-d ")
725 + "-f " + featuresList + " "
726 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700727 }
728 getOutPrintWriter().println(result);
729 } catch (RemoteException e) {
730 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800731 + (isCarrierService ? "-c " : "-d ")
732 + "-f " + featuresList + " "
733 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700734 errPw.println("Exception: " + e.getMessage());
735 return -1;
736 }
737 return 0;
738 }
739
Brad Ebinger999d3302020-11-25 14:31:39 -0800740 // ims clear-ims-service-override
741 private int handleImsClearCarrierServiceCommand() {
742 PrintWriter errPw = getErrPrintWriter();
743 int slotId = getDefaultSlot();
744
745 String opt;
746 while ((opt = getNextOption()) != null) {
747 switch (opt) {
748 case "-s": {
749 try {
750 slotId = Integer.parseInt(getNextArgRequired());
751 } catch (NumberFormatException e) {
752 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
753 return -1;
754 }
755 break;
756 }
757 }
758 }
759
760 try {
761 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
762 if (VDBG) {
763 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
764 + ", result=" + result);
765 }
766 getOutPrintWriter().println(result);
767 } catch (RemoteException e) {
768 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
769 + ", error" + e.getMessage());
770 errPw.println("Exception: " + e.getMessage());
771 return -1;
772 }
773 return 0;
774 }
775
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700776 // ims get-ims-service
777 private int handleImsGetServiceCommand() {
778 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700779 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700780 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800781 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700782
783 String opt;
784 while ((opt = getNextOption()) != null) {
785 switch (opt) {
786 case "-s": {
787 try {
788 slotId = Integer.parseInt(getNextArgRequired());
789 } catch (NumberFormatException e) {
790 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
791 return -1;
792 }
793 break;
794 }
795 case "-c": {
796 isCarrierService = true;
797 break;
798 }
799 case "-d": {
800 isCarrierService = false;
801 break;
802 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800803 case "-f": {
804 try {
805 featureType = Integer.parseInt(getNextArg());
806 } catch (NumberFormatException e) {
807 errPw.println("ims get-ims-service -f requires valid integer as feature.");
808 return -1;
809 }
810 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
811 || featureType >= ImsFeature.FEATURE_MAX) {
812 errPw.println("ims get-ims-service -f invalid feature.");
813 return -1;
814 }
815 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700816 }
817 }
818 // Mandatory param, either -c or -d
819 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800820 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700821 return -1;
822 }
823
824 String result;
825 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800826 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700827 } catch (RemoteException e) {
828 return -1;
829 }
830 if (VDBG) {
831 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800832 + (isCarrierService ? "-c " : "-d ")
833 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
834 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700835 }
836 getOutPrintWriter().println(result);
837 return 0;
838 }
839
840 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700841 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700842 String opt;
843 while ((opt = getNextOption()) != null) {
844 switch (opt) {
845 case "-s": {
846 try {
847 slotId = Integer.parseInt(getNextArgRequired());
848 } catch (NumberFormatException e) {
849 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
850 return -1;
851 }
852 break;
853 }
854 }
855 }
856 try {
857 mInterface.enableIms(slotId);
858 } catch (RemoteException e) {
859 return -1;
860 }
861 if (VDBG) {
862 Log.v(LOG_TAG, "ims enable -s " + slotId);
863 }
864 return 0;
865 }
866
867 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700868 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700869 String opt;
870 while ((opt = getNextOption()) != null) {
871 switch (opt) {
872 case "-s": {
873 try {
874 slotId = Integer.parseInt(getNextArgRequired());
875 } catch (NumberFormatException e) {
876 getErrPrintWriter().println(
877 "ims disable requires an integer as a SLOT_ID.");
878 return -1;
879 }
880 break;
881 }
882 }
883 }
884 try {
885 mInterface.disableIms(slotId);
886 } catch (RemoteException e) {
887 return -1;
888 }
889 if (VDBG) {
890 Log.v(LOG_TAG, "ims disable -s " + slotId);
891 }
892 return 0;
893 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700894
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700895 private int handleCepChange() {
896 Log.i(LOG_TAG, "handleCepChange");
897 String opt = getNextArg();
898 if (opt == null) {
899 return -1;
900 }
901 boolean isCepEnabled = opt.equals("enable");
902
903 try {
904 mInterface.setCepEnabled(isCepEnabled);
905 } catch (RemoteException e) {
906 return -1;
907 }
908 return 0;
909 }
910
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700911 private int getDefaultSlot() {
912 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
913 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
914 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
915 // If there is no default, default to slot 0.
916 slotId = DEFAULT_PHONE_ID;
917 }
918 return slotId;
919 }
sqian2fff4a32018-11-05 14:18:37 -0800920
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100921 // Parse options related to Carrier Config Commands.
922 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100923 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100924 CcOptionParseResult result = new CcOptionParseResult();
925 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
926 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100927
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100928 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100929 while ((opt = getNextOption()) != null) {
930 switch (opt) {
931 case "-s": {
932 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100933 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
934 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
935 errPw.println(tag + "No valid subscription found.");
936 return null;
937 }
938
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100939 } catch (IllegalArgumentException e) {
940 // Missing slot id
941 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100942 return null;
943 }
944 break;
945 }
946 case "-p": {
947 if (allowOptionPersistent) {
948 result.mPersistent = true;
949 } else {
950 errPw.println(tag + "Unexpected option " + opt);
951 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100952 }
953 break;
954 }
955 default: {
956 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100957 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100958 }
959 }
960 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100961 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100962 }
963
964 private int slotStringToSubId(String tag, String slotString) {
965 int slotId = -1;
966 try {
967 slotId = Integer.parseInt(slotString);
968 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800969 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
970 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
971 }
972
973 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100974 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
975 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
976 }
977
Qiong Liuf25799b2020-09-10 10:13:46 +0800978 Phone phone = PhoneFactory.getPhone(slotId);
979 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100980 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
981 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
982 }
Qiong Liuf25799b2020-09-10 10:13:46 +0800983 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100984 }
985
Hall Liud892bec2018-11-30 14:51:45 -0800986 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -0800987 // adb can run as root or as shell, depending on whether the device is rooted.
988 return Binder.getCallingUid() == Process.SHELL_UID
989 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -0800990 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100991
992 private int handleCcCommand() {
993 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
994 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -0800995 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100996 getErrPrintWriter().println("cc: Permission denied.");
997 return -1;
998 }
999
1000 String arg = getNextArg();
1001 if (arg == null) {
1002 onHelpCc();
1003 return 0;
1004 }
1005
1006 switch (arg) {
1007 case CC_GET_VALUE: {
1008 return handleCcGetValue();
1009 }
1010 case CC_SET_VALUE: {
1011 return handleCcSetValue();
1012 }
1013 case CC_CLEAR_VALUES: {
1014 return handleCcClearValues();
1015 }
1016 default: {
1017 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1018 }
1019 }
1020 return -1;
1021 }
1022
1023 // cc get-value
1024 private int handleCcGetValue() {
1025 PrintWriter errPw = getErrPrintWriter();
1026 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1027 String key = null;
1028
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001029 // Parse all options
1030 CcOptionParseResult options = parseCcOptions(tag, false);
1031 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001032 return -1;
1033 }
1034
1035 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001036 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001037 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001038 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001039 return -1;
1040 }
1041
1042 // Get the key.
1043 key = getNextArg();
1044 if (key != null) {
1045 // A key was provided. Verify if it is a valid key
1046 if (!bundle.containsKey(key)) {
1047 errPw.println(tag + key + " is not a valid key.");
1048 return -1;
1049 }
1050
1051 // Print the carrier config value for key.
1052 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1053 } else {
1054 // No key provided. Show all values.
1055 // Iterate over a sorted list of all carrier config keys and print them.
1056 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1057 for (String k : sortedSet) {
1058 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1059 }
1060 }
1061 return 0;
1062 }
1063
1064 // cc set-value
1065 private int handleCcSetValue() {
1066 PrintWriter errPw = getErrPrintWriter();
1067 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1068
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001069 // Parse all options
1070 CcOptionParseResult options = parseCcOptions(tag, true);
1071 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001072 return -1;
1073 }
1074
1075 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001076 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001077 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001078 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001079 return -1;
1080 }
1081
1082 // Get the key.
1083 String key = getNextArg();
1084 if (key == null || key.equals("")) {
1085 errPw.println(tag + "KEY is missing");
1086 return -1;
1087 }
1088
1089 // Verify if the key is valid
1090 if (!originalValues.containsKey(key)) {
1091 errPw.println(tag + key + " is not a valid key.");
1092 return -1;
1093 }
1094
1095 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1096 ArrayList<String> valueList = new ArrayList<String>();
1097 while (peekNextArg() != null) {
1098 valueList.add(getNextArg());
1099 }
1100
1101 // Find the type of the carrier config value
1102 CcType type = getType(tag, key, originalValues);
1103 if (type == CcType.UNKNOWN) {
1104 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1105 return -1;
1106 }
1107
1108 // Create an override bundle containing the key and value that should be overriden.
1109 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1110 if (overrideBundle == null) {
1111 return -1;
1112 }
1113
1114 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001115 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001116
1117 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001118 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001119 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001120 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001121 return -1;
1122 }
1123
1124 // Print the original and new value.
1125 String originalValueString = ccValueToString(key, type, originalValues);
1126 String newValueString = ccValueToString(key, type, newValues);
1127 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1128 getOutPrintWriter().println("New value: \n" + newValueString);
1129
1130 return 0;
1131 }
1132
1133 // cc clear-values
1134 private int handleCcClearValues() {
1135 PrintWriter errPw = getErrPrintWriter();
1136 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1137
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001138 // Parse all options
1139 CcOptionParseResult options = parseCcOptions(tag, false);
1140 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001141 return -1;
1142 }
1143
1144 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001145 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001146 getOutPrintWriter()
1147 .println("All previously set carrier config override values has been cleared");
1148 return 0;
1149 }
1150
1151 private CcType getType(String tag, String key, PersistableBundle bundle) {
1152 // Find the type by checking the type of the current value stored in the bundle.
1153 Object value = bundle.get(key);
1154
1155 if (CC_TYPE_MAP.containsKey(key)) {
1156 return CC_TYPE_MAP.get(key);
1157 } else if (value != null) {
1158 if (value instanceof Boolean) {
1159 return CcType.BOOLEAN;
1160 } else if (value instanceof Double) {
1161 return CcType.DOUBLE;
1162 } else if (value instanceof double[]) {
1163 return CcType.DOUBLE_ARRAY;
1164 } else if (value instanceof Integer) {
1165 return CcType.INT;
1166 } else if (value instanceof int[]) {
1167 return CcType.INT_ARRAY;
1168 } else if (value instanceof Long) {
1169 return CcType.LONG;
1170 } else if (value instanceof long[]) {
1171 return CcType.LONG_ARRAY;
1172 } else if (value instanceof String) {
1173 return CcType.STRING;
1174 } else if (value instanceof String[]) {
1175 return CcType.STRING_ARRAY;
1176 }
1177 } else {
1178 // Current value was null and can therefore not be used in order to find the type.
1179 // Check the name of the key to infer the type. This check is not needed for primitive
1180 // data types (boolean, double, int and long), since they can not be null.
1181 if (key.endsWith("double_array")) {
1182 return CcType.DOUBLE_ARRAY;
1183 }
1184 if (key.endsWith("int_array")) {
1185 return CcType.INT_ARRAY;
1186 }
1187 if (key.endsWith("long_array")) {
1188 return CcType.LONG_ARRAY;
1189 }
1190 if (key.endsWith("string")) {
1191 return CcType.STRING;
1192 }
1193 if (key.endsWith("string_array") || key.endsWith("strings")) {
1194 return CcType.STRING_ARRAY;
1195 }
1196 }
1197
1198 // Not possible to infer the type by looking at the current value or the key.
1199 PrintWriter errPw = getErrPrintWriter();
1200 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1201 return CcType.UNKNOWN;
1202 }
1203
1204 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1205 String result;
1206 StringBuilder valueString = new StringBuilder();
1207 String typeString = type.toString();
1208 Object value = bundle.get(key);
1209
1210 if (value == null) {
1211 valueString.append("null");
1212 } else {
1213 switch (type) {
1214 case DOUBLE_ARRAY: {
1215 // Format the string representation of the int array as value1 value2......
1216 double[] valueArray = (double[]) value;
1217 for (int i = 0; i < valueArray.length; i++) {
1218 if (i != 0) {
1219 valueString.append(" ");
1220 }
1221 valueString.append(valueArray[i]);
1222 }
1223 break;
1224 }
1225 case INT_ARRAY: {
1226 // Format the string representation of the int array as value1 value2......
1227 int[] valueArray = (int[]) value;
1228 for (int i = 0; i < valueArray.length; i++) {
1229 if (i != 0) {
1230 valueString.append(" ");
1231 }
1232 valueString.append(valueArray[i]);
1233 }
1234 break;
1235 }
1236 case LONG_ARRAY: {
1237 // Format the string representation of the int array as value1 value2......
1238 long[] valueArray = (long[]) value;
1239 for (int i = 0; i < valueArray.length; i++) {
1240 if (i != 0) {
1241 valueString.append(" ");
1242 }
1243 valueString.append(valueArray[i]);
1244 }
1245 break;
1246 }
1247 case STRING: {
1248 valueString.append("\"" + value.toString() + "\"");
1249 break;
1250 }
1251 case STRING_ARRAY: {
1252 // Format the string representation of the string array as "value1" "value2"....
1253 String[] valueArray = (String[]) value;
1254 for (int i = 0; i < valueArray.length; i++) {
1255 if (i != 0) {
1256 valueString.append(" ");
1257 }
1258 if (valueArray[i] != null) {
1259 valueString.append("\"" + valueArray[i] + "\"");
1260 } else {
1261 valueString.append("null");
1262 }
1263 }
1264 break;
1265 }
1266 default: {
1267 valueString.append(value.toString());
1268 }
1269 }
1270 }
1271 return String.format("%-70s %-15s %s", key, typeString, valueString);
1272 }
1273
1274 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1275 ArrayList<String> valueList) {
1276 PrintWriter errPw = getErrPrintWriter();
1277 PersistableBundle bundle = new PersistableBundle();
1278
1279 // First verify that a valid number of values has been provided for the type.
1280 switch (type) {
1281 case BOOLEAN:
1282 case DOUBLE:
1283 case INT:
1284 case LONG: {
1285 if (valueList.size() != 1) {
1286 errPw.println(tag + "Expected 1 value for type " + type
1287 + ". Found: " + valueList.size());
1288 return null;
1289 }
1290 break;
1291 }
1292 case STRING: {
1293 if (valueList.size() > 1) {
1294 errPw.println(tag + "Expected 0 or 1 values for type " + type
1295 + ". Found: " + valueList.size());
1296 return null;
1297 }
1298 break;
1299 }
1300 }
1301
1302 // Parse the value according to type and add it to the Bundle.
1303 switch (type) {
1304 case BOOLEAN: {
1305 if ("true".equalsIgnoreCase(valueList.get(0))) {
1306 bundle.putBoolean(key, true);
1307 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1308 bundle.putBoolean(key, false);
1309 } else {
1310 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1311 return null;
1312 }
1313 break;
1314 }
1315 case DOUBLE: {
1316 try {
1317 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1318 } catch (NumberFormatException nfe) {
1319 // Not a valid double
1320 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1321 return null;
1322 }
1323 break;
1324 }
1325 case DOUBLE_ARRAY: {
1326 double[] valueDoubleArray = null;
1327 if (valueList.size() > 0) {
1328 valueDoubleArray = new double[valueList.size()];
1329 for (int i = 0; i < valueList.size(); i++) {
1330 try {
1331 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1332 } catch (NumberFormatException nfe) {
1333 // Not a valid double
1334 errPw.println(
1335 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1336 return null;
1337 }
1338 }
1339 }
1340 bundle.putDoubleArray(key, valueDoubleArray);
1341 break;
1342 }
1343 case INT: {
1344 try {
1345 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1346 } catch (NumberFormatException nfe) {
1347 // Not a valid integer
1348 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1349 return null;
1350 }
1351 break;
1352 }
1353 case INT_ARRAY: {
1354 int[] valueIntArray = null;
1355 if (valueList.size() > 0) {
1356 valueIntArray = new int[valueList.size()];
1357 for (int i = 0; i < valueList.size(); i++) {
1358 try {
1359 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1360 } catch (NumberFormatException nfe) {
1361 // Not a valid integer
1362 errPw.println(tag
1363 + "Unable to parse " + valueList.get(i) + " as an integer.");
1364 return null;
1365 }
1366 }
1367 }
1368 bundle.putIntArray(key, valueIntArray);
1369 break;
1370 }
1371 case LONG: {
1372 try {
1373 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1374 } catch (NumberFormatException nfe) {
1375 // Not a valid long
1376 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1377 return null;
1378 }
1379 break;
1380 }
1381 case LONG_ARRAY: {
1382 long[] valueLongArray = null;
1383 if (valueList.size() > 0) {
1384 valueLongArray = new long[valueList.size()];
1385 for (int i = 0; i < valueList.size(); i++) {
1386 try {
1387 valueLongArray[i] = Long.parseLong(valueList.get(i));
1388 } catch (NumberFormatException nfe) {
1389 // Not a valid long
1390 errPw.println(
1391 tag + "Unable to parse " + valueList.get(i) + " as a long");
1392 return null;
1393 }
1394 }
1395 }
1396 bundle.putLongArray(key, valueLongArray);
1397 break;
1398 }
1399 case STRING: {
1400 String value = null;
1401 if (valueList.size() > 0) {
1402 value = valueList.get(0);
1403 }
1404 bundle.putString(key, value);
1405 break;
1406 }
1407 case STRING_ARRAY: {
1408 String[] valueStringArray = null;
1409 if (valueList.size() > 0) {
1410 valueStringArray = new String[valueList.size()];
1411 valueList.toArray(valueStringArray);
1412 }
1413 bundle.putStringArray(key, valueStringArray);
1414 break;
1415 }
1416 }
1417 return bundle;
1418 }
Shuo Qian489d9282020-07-09 11:30:03 -07001419
1420 private int handleEndBlockSuppressionCommand() {
1421 if (!checkShellUid()) {
1422 return -1;
1423 }
1424
1425 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1426 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1427 }
1428 return 0;
1429 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001430
Michele Berionne38c1afa2020-12-28 20:23:16 +00001431 private int handleRestartModemCommand() {
1432 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1433 // non user build.
1434 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1435 getErrPrintWriter().println("RestartModem: Permission denied.");
1436 return -1;
1437 }
1438
1439 boolean result = TelephonyManager.getDefault().rebootRadio();
1440 getOutPrintWriter().println(result);
1441
1442 return result ? 0 : -1;
1443 }
1444
Hui Wang0866fcc2020-10-12 12:14:23 -07001445 private int handleGbaCommand() {
1446 String arg = getNextArg();
1447 if (arg == null) {
1448 onHelpGba();
1449 return 0;
1450 }
1451
1452 switch (arg) {
1453 case GBA_SET_SERVICE: {
1454 return handleGbaSetServiceCommand();
1455 }
1456 case GBA_GET_SERVICE: {
1457 return handleGbaGetServiceCommand();
1458 }
1459 case GBA_SET_RELEASE_TIME: {
1460 return handleGbaSetReleaseCommand();
1461 }
1462 case GBA_GET_RELEASE_TIME: {
1463 return handleGbaGetReleaseCommand();
1464 }
1465 }
1466
1467 return -1;
1468 }
1469
1470 private int getSubId(String cmd) {
1471 int slotId = getDefaultSlot();
1472 String opt = getNextOption();
1473 if (opt != null && opt.equals("-s")) {
1474 try {
1475 slotId = Integer.parseInt(getNextArgRequired());
1476 } catch (NumberFormatException e) {
1477 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1478 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1479 }
1480 }
1481 int[] subIds = SubscriptionManager.getSubId(slotId);
1482 return subIds[0];
1483 }
1484
1485 private int handleGbaSetServiceCommand() {
1486 int subId = getSubId("gba set-service");
1487 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1488 return -1;
1489 }
1490
1491 String packageName = getNextArg();
1492 try {
1493 if (packageName == null) {
1494 packageName = "";
1495 }
1496 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1497 if (VDBG) {
1498 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1499 + packageName + ", result=" + result);
1500 }
1501 getOutPrintWriter().println(result);
1502 } catch (RemoteException e) {
1503 Log.w(LOG_TAG, "gba set-service " + subId + " "
1504 + packageName + ", error" + e.getMessage());
1505 getErrPrintWriter().println("Exception: " + e.getMessage());
1506 return -1;
1507 }
1508 return 0;
1509 }
1510
1511 private int handleGbaGetServiceCommand() {
1512 String result;
1513
1514 int subId = getSubId("gba get-service");
1515 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1516 return -1;
1517 }
1518
1519 try {
1520 result = mInterface.getBoundGbaService(subId);
1521 } catch (RemoteException e) {
1522 return -1;
1523 }
1524 if (VDBG) {
1525 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1526 }
1527 getOutPrintWriter().println(result);
1528 return 0;
1529 }
1530
1531 private int handleGbaSetReleaseCommand() {
1532 //the release time value could be -1
1533 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1534 : SubscriptionManager.getDefaultSubscriptionId();
1535 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1536 return -1;
1537 }
1538
1539 String intervalStr = getNextArg();
1540 if (intervalStr == null) {
1541 return -1;
1542 }
1543
1544 try {
1545 int interval = Integer.parseInt(intervalStr);
1546 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1547 if (VDBG) {
1548 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1549 + intervalStr + ", result=" + result);
1550 }
1551 getOutPrintWriter().println(result);
1552 } catch (NumberFormatException | RemoteException e) {
1553 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1554 + intervalStr + ", error" + e.getMessage());
1555 getErrPrintWriter().println("Exception: " + e.getMessage());
1556 return -1;
1557 }
1558 return 0;
1559 }
1560
1561 private int handleGbaGetReleaseCommand() {
1562 int subId = getSubId("gba get-release");
1563 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1564 return -1;
1565 }
1566
1567 int result = 0;
1568 try {
1569 result = mInterface.getGbaReleaseTime(subId);
1570 } catch (RemoteException e) {
1571 return -1;
1572 }
1573 if (VDBG) {
1574 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1575 }
1576 getOutPrintWriter().println(result);
1577 return 0;
1578 }
Hui Wang068ab862020-10-31 05:12:53 +00001579
1580 private int handleSingleRegistrationConfigCommand() {
1581 String arg = getNextArg();
1582 if (arg == null) {
1583 onHelpSrc();
1584 return 0;
1585 }
1586
1587 switch (arg) {
1588 case SRC_SET_DEVICE_ENABLED: {
1589 return handleSrcSetDeviceEnabledCommand();
1590 }
1591 case SRC_GET_DEVICE_ENABLED: {
1592 return handleSrcGetDeviceEnabledCommand();
1593 }
1594 case SRC_SET_CARRIER_ENABLED: {
1595 return handleSrcSetCarrierEnabledCommand();
1596 }
1597 case SRC_GET_CARRIER_ENABLED: {
1598 return handleSrcGetCarrierEnabledCommand();
1599 }
1600 }
1601
1602 return -1;
1603 }
1604
James.cf Linbcdf8b32021-01-14 16:44:13 +08001605 private int handleRcsUceCommand() {
1606 String arg = getNextArg();
1607 if (arg == null) {
1608 Log.w(LOG_TAG, "cannot get uce parameter");
1609 return -1;
1610 }
1611
1612 switch (arg) {
1613 case UCE_REMOVE_EAB_CONTACT:
1614 return handleRemovingEabContactCommand();
1615 }
1616 return -1;
1617 }
1618
1619 private int handleRemovingEabContactCommand() {
1620 int subId = getSubId("uce remove-eab-contact");
1621 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1622 return -1;
1623 }
1624
1625 String phoneNumber = getNextArgRequired();
1626 if (TextUtils.isEmpty(phoneNumber)) {
1627 return -1;
1628 }
1629 int result = 0;
1630 try {
1631 result = mInterface.removeContactFromEab(subId, phoneNumber);
1632 } catch (RemoteException e) {
1633 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1634 getErrPrintWriter().println("Exception: " + e.getMessage());
1635 return -1;
1636 }
1637
1638 if (VDBG) {
1639 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1640 }
1641 return result;
1642 }
1643
Hui Wang068ab862020-10-31 05:12:53 +00001644 private int handleSrcSetDeviceEnabledCommand() {
1645 String enabledStr = getNextArg();
1646 if (enabledStr == null) {
1647 return -1;
1648 }
1649
1650 try {
1651 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1652 if (VDBG) {
1653 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1654 }
1655 getOutPrintWriter().println("Done");
1656 } catch (NumberFormatException | RemoteException e) {
1657 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1658 getErrPrintWriter().println("Exception: " + e.getMessage());
1659 return -1;
1660 }
1661 return 0;
1662 }
1663
1664 private int handleSrcGetDeviceEnabledCommand() {
1665 boolean result = false;
1666 try {
1667 result = mInterface.getDeviceSingleRegistrationEnabled();
1668 } catch (RemoteException e) {
1669 return -1;
1670 }
1671 if (VDBG) {
1672 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1673 }
1674 getOutPrintWriter().println(result);
1675 return 0;
1676 }
1677
1678 private int handleSrcSetCarrierEnabledCommand() {
1679 //the release time value could be -1
1680 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1681 : SubscriptionManager.getDefaultSubscriptionId();
1682 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1683 return -1;
1684 }
1685
1686 String enabledStr = getNextArg();
1687 if (enabledStr == null) {
1688 return -1;
1689 }
1690
1691 try {
1692 boolean result =
1693 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1694 if (VDBG) {
1695 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1696 + enabledStr + ", result=" + result);
1697 }
1698 getOutPrintWriter().println(result);
1699 } catch (NumberFormatException | RemoteException e) {
1700 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1701 + enabledStr + ", error" + e.getMessage());
1702 getErrPrintWriter().println("Exception: " + e.getMessage());
1703 return -1;
1704 }
1705 return 0;
1706 }
1707
1708 private int handleSrcGetCarrierEnabledCommand() {
1709 int subId = getSubId("src get-carrier-enabled");
1710 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1711 return -1;
1712 }
1713
1714 boolean result = false;
1715 try {
1716 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1717 } catch (RemoteException e) {
1718 return -1;
1719 }
1720 if (VDBG) {
1721 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1722 }
1723 getOutPrintWriter().println(result);
1724 return 0;
1725 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001726}