blob: 8acfd1d208863e3c36ab2964c24defcac6951921 [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";
Michele Berionned9fbae52020-11-13 02:36:59 +000071 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080073 private static final String DATA_TEST_MODE = "data";
74 private static final String DATA_ENABLE = "enable";
75 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080076
Brad Ebinger999d3302020-11-25 14:31:39 -080077 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
78 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
79 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070080 private static final String IMS_ENABLE = "enable";
81 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070082 // Used to disable or enable processing of conference event package data from the network.
83 // This is handy for testing scenarios where CEP data does not exist on a network which does
84 // support CEP data.
85 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070086
Hall Liud892bec2018-11-30 14:51:45 -080087 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080088 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080089
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010090 private static final String CC_GET_VALUE = "get-value";
91 private static final String CC_SET_VALUE = "set-value";
92 private static final String CC_CLEAR_VALUES = "clear-values";
93
Hui Wang0866fcc2020-10-12 12:14:23 -070094 private static final String GBA_SUBCOMMAND = "gba";
95 private static final String GBA_SET_SERVICE = "set-service";
96 private static final String GBA_GET_SERVICE = "get-service";
97 private static final String GBA_SET_RELEASE_TIME = "set-release";
98 private static final String GBA_GET_RELEASE_TIME = "get-release";
99
Hui Wang068ab862020-10-31 05:12:53 +0000100 private static final String SINGLE_REGISTATION_CONFIG = "src";
101 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
102 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
103 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
104 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
105
Tyler Gunn92479152021-01-20 16:30:10 -0800106 private static final String D2D_SUBCOMMAND = "d2d";
107 private static final String D2D_SEND = "send";
108
James.cf Linbcdf8b32021-01-14 16:44:13 +0800109 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800110 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800111 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800112 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
113 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800114
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700115 // Take advantage of existing methods that already contain permissions checks when possible.
116 private final ITelephony mInterface;
117
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100118 private SubscriptionManager mSubscriptionManager;
119 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700120 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100121
122 private enum CcType {
123 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
124 STRING_ARRAY, UNKNOWN
125 }
126
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100127 private class CcOptionParseResult {
128 public int mSubId;
129 public boolean mPersistent;
130 }
131
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100132 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
133 // keys by looking at the end of the string which usually tells the type.
134 // For instance: "xxxx_string", "xxxx_string_array", etc.
135 // The carrier config keys in this map does not follow this convention. It is therefore not
136 // possible to infer the type for these keys by looking at the string.
137 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
138 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
139 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
140 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
141 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
142 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
143 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
149 CcType.STRING);
150 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
151 CcType.STRING_ARRAY);
152 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
153 CcType.STRING_ARRAY);
154 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
155 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
156 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
157 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
158 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
159 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
160 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
161 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
162 }
163 };
164
165 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700166 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100167 mCarrierConfigManager =
168 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
169 mSubscriptionManager = (SubscriptionManager)
170 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700171 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700172 }
173
174 @Override
175 public int onCommand(String cmd) {
176 if (cmd == null) {
177 return handleDefaultCommands(null);
178 }
179
180 switch (cmd) {
181 case IMS_SUBCOMMAND: {
182 return handleImsCommand();
183 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800184 case RCS_UCE_COMMAND:
185 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800186 case NUMBER_VERIFICATION_SUBCOMMAND:
187 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800188 case EMERGENCY_NUMBER_TEST_MODE:
189 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100190 case CARRIER_CONFIG_SUBCOMMAND: {
191 return handleCcCommand();
192 }
Shuo Qianf5125122019-12-16 17:03:07 -0800193 case DATA_TEST_MODE:
194 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700195 case END_BLOCK_SUPPRESSION:
196 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700197 case GBA_SUBCOMMAND:
198 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800199 case D2D_SUBCOMMAND:
200 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000201 case SINGLE_REGISTATION_CONFIG:
202 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000203 case RESTART_MODEM:
204 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000205 case UNATTENDED_REBOOT:
206 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700207 default: {
208 return handleDefaultCommands(cmd);
209 }
210 }
211 }
212
213 @Override
214 public void onHelp() {
215 PrintWriter pw = getOutPrintWriter();
216 pw.println("Telephony Commands:");
217 pw.println(" help");
218 pw.println(" Print this help text.");
219 pw.println(" ims");
220 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800221 pw.println(" uce");
222 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800223 pw.println(" emergency-number-test-mode");
224 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700225 pw.println(" end-block-suppression");
226 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800227 pw.println(" data");
228 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100229 pw.println(" cc");
230 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700231 pw.println(" gba");
232 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000233 pw.println(" src");
234 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000235 pw.println(" restart-modem");
236 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000237 pw.println(" unattended-reboot");
238 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700239 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800240 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800241 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700242 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800243 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100244 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700245 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000246 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800247 onHelpD2D();
248 }
249
250 private void onHelpD2D() {
251 PrintWriter pw = getOutPrintWriter();
252 pw.println("D2D Comms Commands:");
253 pw.println(" d2d send TYPE VALUE");
254 pw.println(" Sends a D2D message of specified type and value.");
255 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
256 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
257 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
258 MESSAGE_CALL_AUDIO_CODEC));
259 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
260 + Communicator.messageToString(
261 MESSAGE_DEVICE_BATTERY_STATE));
262 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
263 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700264 }
265
266 private void onHelpIms() {
267 PrintWriter pw = getOutPrintWriter();
268 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800269 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700270 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
271 pw.println(" ImsService. Options are:");
272 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
273 pw.println(" is specified, it will choose the default voice SIM slot.");
274 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
275 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800276 pw.println(" -f: Set the feature that this override if for, if no option is");
277 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700278 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
279 pw.println(" Gets the package name of the currently defined ImsService.");
280 pw.println(" Options are:");
281 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
282 pw.println(" is specified, it will choose the default voice SIM slot.");
283 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000284 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800285 pw.println(" -f: The feature type that the query will be requested for. If none is");
286 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800287 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
288 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
289 pw.println(" configuration overrides. Options are:");
290 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
291 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700292 pw.println(" ims enable [-s SLOT_ID]");
293 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
294 pw.println(" if none is specified.");
295 pw.println(" ims disable [-s SLOT_ID]");
296 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
297 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700298 pw.println(" ims conference-event-package [enable/disable]");
299 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700300 }
301
James.cf Linbcdf8b32021-01-14 16:44:13 +0800302 private void onHelpUce() {
303 PrintWriter pw = getOutPrintWriter();
304 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800305 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
306 pw.println(" Get the EAB contacts from the EAB database.");
307 pw.println(" Options are:");
308 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
309 pw.println(" Expected output format :");
310 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800311 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
312 pw.println(" Remove the EAB contacts from the EAB database.");
313 pw.println(" Options are:");
314 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
315 pw.println(" is specified, it will choose the default voice SIM slot.");
316 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800317 pw.println(" uce get-device-enabled");
318 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
319 pw.println(" uce set-device-enabled true|false");
320 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
321 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800322 }
323
Hall Liud892bec2018-11-30 14:51:45 -0800324 private void onHelpNumberVerification() {
325 PrintWriter pw = getOutPrintWriter();
326 pw.println("Number verification commands");
327 pw.println(" numverify override-package PACKAGE_NAME;");
328 pw.println(" Set the authorized package for number verification.");
329 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800330 pw.println(" numverify fake-call NUMBER;");
331 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
332 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800333 }
334
Shuo Qianf5125122019-12-16 17:03:07 -0800335 private void onHelpDataTestMode() {
336 PrintWriter pw = getOutPrintWriter();
337 pw.println("Mobile Data Test Mode Commands:");
338 pw.println(" data enable: enable mobile data connectivity");
339 pw.println(" data disable: disable mobile data connectivity");
340 }
341
sqian9d4df8b2019-01-15 18:32:07 -0800342 private void onHelpEmergencyNumber() {
343 PrintWriter pw = getOutPrintWriter();
344 pw.println("Emergency Number Test Mode Commands:");
345 pw.println(" emergency-number-test-mode ");
346 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
347 + " the test mode");
348 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700349 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800350 pw.println(" -c: clear the emergency number list in the test mode.");
351 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700352 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800353 pw.println(" -p: get the full emergency number list in the test mode.");
354 }
355
Shuo Qian489d9282020-07-09 11:30:03 -0700356 private void onHelpEndBlockSupperssion() {
357 PrintWriter pw = getOutPrintWriter();
358 pw.println("End Block Suppression command:");
359 pw.println(" end-block-suppression: disable suppressing blocking by contact");
360 pw.println(" with emergency services.");
361 }
362
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100363 private void onHelpCc() {
364 PrintWriter pw = getOutPrintWriter();
365 pw.println("Carrier Config Commands:");
366 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
367 pw.println(" Print carrier config values.");
368 pw.println(" Options are:");
369 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
370 pw.println(" is specified, it will choose the default voice SIM slot.");
371 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
372 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100373 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100374 pw.println(" Set carrier config KEY to NEW_VALUE.");
375 pw.println(" Options are:");
376 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
377 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100378 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100379 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
380 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
381 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
382 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
383 pw.println(" cc clear-values [-s SLOT_ID]");
384 pw.println(" Clear all carrier override values that has previously been set");
385 pw.println(" with set-value");
386 pw.println(" Options are:");
387 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
388 pw.println(" is specified, it will choose the default voice SIM slot.");
389 }
390
Hui Wang0866fcc2020-10-12 12:14:23 -0700391 private void onHelpGba() {
392 PrintWriter pw = getOutPrintWriter();
393 pw.println("Gba Commands:");
394 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
395 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
396 pw.println(" Options are:");
397 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
398 pw.println(" is specified, it will choose the default voice SIM slot.");
399 pw.println(" gba get-service [-s SLOT_ID]");
400 pw.println(" Gets the package name of the currently defined GbaService.");
401 pw.println(" Options are:");
402 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
403 pw.println(" is specified, it will choose the default voice SIM slot.");
404 pw.println(" gba set-release [-s SLOT_ID] n");
405 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
406 pw.println(" Do not release/unbind if n is -1.");
407 pw.println(" Options are:");
408 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
409 pw.println(" is specified, it will choose the default voice SIM slot.");
410 pw.println(" gba get-release [-s SLOT_ID]");
411 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
412 pw.println(" Options are:");
413 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
414 pw.println(" is specified, it will choose the default voice SIM slot.");
415 }
416
Hui Wang068ab862020-10-31 05:12:53 +0000417 private void onHelpSrc() {
418 PrintWriter pw = getOutPrintWriter();
419 pw.println("RCS VoLTE Single Registration Config Commands:");
420 pw.println(" src set-device-enabled true|false|null");
421 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
422 pw.println(" The value could be true, false, or null(undefined).");
423 pw.println(" src get-device-enabled");
424 pw.println(" Gets the device config for RCS VoLTE single registration.");
425 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
426 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
427 pw.println(" The value could be true, false, or null(undefined).");
428 pw.println(" Options are:");
429 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
430 pw.println(" is specified, it will choose the default voice SIM slot.");
431 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
432 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
433 pw.println(" Options are:");
434 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
435 pw.println(" is specified, it will choose the default voice SIM slot.");
436 }
437
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700438 private int handleImsCommand() {
439 String arg = getNextArg();
440 if (arg == null) {
441 onHelpIms();
442 return 0;
443 }
444
445 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800446 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700447 return handleImsSetServiceCommand();
448 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800449 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700450 return handleImsGetServiceCommand();
451 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800452 case IMS_CLEAR_SERVICE_OVERRIDE: {
453 return handleImsClearCarrierServiceCommand();
454 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700455 case IMS_ENABLE: {
456 return handleEnableIms();
457 }
458 case IMS_DISABLE: {
459 return handleDisableIms();
460 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700461 case IMS_CEP: {
462 return handleCepChange();
463 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700464 }
465
466 return -1;
467 }
468
Shuo Qianf5125122019-12-16 17:03:07 -0800469 private int handleDataTestModeCommand() {
470 PrintWriter errPw = getErrPrintWriter();
471 String arg = getNextArgRequired();
472 if (arg == null) {
473 onHelpDataTestMode();
474 return 0;
475 }
476 switch (arg) {
477 case DATA_ENABLE: {
478 try {
479 mInterface.enableDataConnectivity();
480 } catch (RemoteException ex) {
481 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
482 errPw.println("Exception: " + ex.getMessage());
483 return -1;
484 }
485 break;
486 }
487 case DATA_DISABLE: {
488 try {
489 mInterface.disableDataConnectivity();
490 } catch (RemoteException ex) {
491 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
492 errPw.println("Exception: " + ex.getMessage());
493 return -1;
494 }
495 break;
496 }
497 default:
498 onHelpDataTestMode();
499 break;
500 }
501 return 0;
502 }
503
sqian9d4df8b2019-01-15 18:32:07 -0800504 private int handleEmergencyNumberTestModeCommand() {
505 PrintWriter errPw = getErrPrintWriter();
506 String opt = getNextOption();
507 if (opt == null) {
508 onHelpEmergencyNumber();
509 return 0;
510 }
511
512 switch (opt) {
513 case "-a": {
514 String emergencyNumberCmd = getNextArgRequired();
515 if (emergencyNumberCmd == null
516 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700517 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800518 + " to be specified after -a in the command ");
519 return -1;
520 }
521 try {
522 mInterface.updateEmergencyNumberListTestMode(
523 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
524 new EmergencyNumber(emergencyNumberCmd, "", "",
525 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
526 new ArrayList<String>(),
527 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
528 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
529 } catch (RemoteException ex) {
530 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
531 + ", error " + ex.getMessage());
532 errPw.println("Exception: " + ex.getMessage());
533 return -1;
534 }
535 break;
536 }
537 case "-c": {
538 try {
539 mInterface.updateEmergencyNumberListTestMode(
540 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
541 } catch (RemoteException ex) {
542 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
543 errPw.println("Exception: " + ex.getMessage());
544 return -1;
545 }
546 break;
547 }
548 case "-r": {
549 String emergencyNumberCmd = getNextArgRequired();
550 if (emergencyNumberCmd == null
551 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700552 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800553 + " to be specified after -r in the command ");
554 return -1;
555 }
556 try {
557 mInterface.updateEmergencyNumberListTestMode(
558 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
559 new EmergencyNumber(emergencyNumberCmd, "", "",
560 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
561 new ArrayList<String>(),
562 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
563 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
564 } catch (RemoteException ex) {
565 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
566 + ", error " + ex.getMessage());
567 errPw.println("Exception: " + ex.getMessage());
568 return -1;
569 }
570 break;
571 }
572 case "-p": {
573 try {
574 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
575 } catch (RemoteException ex) {
576 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
577 errPw.println("Exception: " + ex.getMessage());
578 return -1;
579 }
580 break;
581 }
582 default:
583 onHelpEmergencyNumber();
584 break;
585 }
586 return 0;
587 }
588
Hall Liud892bec2018-11-30 14:51:45 -0800589 private int handleNumberVerificationCommand() {
590 String arg = getNextArg();
591 if (arg == null) {
592 onHelpNumberVerification();
593 return 0;
594 }
595
Hall Liuca5af3a2018-12-04 16:58:23 -0800596 if (!checkShellUid()) {
597 return -1;
598 }
599
Hall Liud892bec2018-11-30 14:51:45 -0800600 switch (arg) {
601 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800602 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
603 return 0;
604 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800605 case NUMBER_VERIFICATION_FAKE_CALL: {
606 boolean val = NumberVerificationManager.getInstance()
607 .checkIncomingCall(getNextArg());
608 getOutPrintWriter().println(val ? "1" : "0");
609 return 0;
610 }
Hall Liud892bec2018-11-30 14:51:45 -0800611 }
612
613 return -1;
614 }
615
Tyler Gunn92479152021-01-20 16:30:10 -0800616 private int handleD2dCommand() {
617 String arg = getNextArg();
618 if (arg == null) {
619 onHelpD2D();
620 return 0;
621 }
622
623 switch (arg) {
624 case D2D_SEND: {
625 return handleD2dSendCommand();
626 }
627 }
628
629 return -1;
630 }
631
632 private int handleD2dSendCommand() {
633 PrintWriter errPw = getErrPrintWriter();
634 String opt;
635 int messageType = -1;
636 int messageValue = -1;
637
638
639 String arg = getNextArg();
640 if (arg == null) {
641 onHelpD2D();
642 return 0;
643 }
644 try {
645 messageType = Integer.parseInt(arg);
646 } catch (NumberFormatException e) {
647 errPw.println("message type must be a valid integer");
648 return -1;
649 }
650
651 arg = getNextArg();
652 if (arg == null) {
653 onHelpD2D();
654 return 0;
655 }
656 try {
657 messageValue = Integer.parseInt(arg);
658 } catch (NumberFormatException e) {
659 errPw.println("message value must be a valid integer");
660 return -1;
661 }
662
663 try {
664 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
665 } catch (RemoteException e) {
666 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
667 errPw.println("Exception: " + e.getMessage());
668 return -1;
669 }
670
671 return 0;
672 }
673
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700674 // ims set-ims-service
675 private int handleImsSetServiceCommand() {
676 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700677 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700678 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800679 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700680
681 String opt;
682 while ((opt = getNextOption()) != null) {
683 switch (opt) {
684 case "-s": {
685 try {
686 slotId = Integer.parseInt(getNextArgRequired());
687 } catch (NumberFormatException e) {
688 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
689 return -1;
690 }
691 break;
692 }
693 case "-c": {
694 isCarrierService = true;
695 break;
696 }
697 case "-d": {
698 isCarrierService = false;
699 break;
700 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800701 case "-f": {
702 String featureString = getNextArgRequired();
703 String[] features = featureString.split(",");
704 for (int i = 0; i < features.length; i++) {
705 try {
706 Integer result = Integer.parseInt(features[i]);
707 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
708 || result >= ImsFeature.FEATURE_MAX) {
709 errPw.println("ims set-ims-service -f " + result
710 + " is an invalid feature.");
711 return -1;
712 }
713 featuresList.add(result);
714 } catch (NumberFormatException e) {
715 errPw.println("ims set-ims-service -f tried to parse " + features[i]
716 + " as an integer.");
717 return -1;
718 }
719 }
720 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700721 }
722 }
723 // Mandatory param, either -c or -d
724 if (isCarrierService == null) {
725 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
726 return -1;
727 }
728
729 String packageName = getNextArg();
730
731 try {
732 if (packageName == null) {
733 packageName = "";
734 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800735 int[] featureArray = new int[featuresList.size()];
736 for (int i = 0; i < featuresList.size(); i++) {
737 featureArray[i] = featuresList.get(i);
738 }
739 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
740 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700741 if (VDBG) {
742 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800743 + (isCarrierService ? "-c " : "-d ")
744 + "-f " + featuresList + " "
745 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700746 }
747 getOutPrintWriter().println(result);
748 } catch (RemoteException e) {
749 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800750 + (isCarrierService ? "-c " : "-d ")
751 + "-f " + featuresList + " "
752 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700753 errPw.println("Exception: " + e.getMessage());
754 return -1;
755 }
756 return 0;
757 }
758
Brad Ebinger999d3302020-11-25 14:31:39 -0800759 // ims clear-ims-service-override
760 private int handleImsClearCarrierServiceCommand() {
761 PrintWriter errPw = getErrPrintWriter();
762 int slotId = getDefaultSlot();
763
764 String opt;
765 while ((opt = getNextOption()) != null) {
766 switch (opt) {
767 case "-s": {
768 try {
769 slotId = Integer.parseInt(getNextArgRequired());
770 } catch (NumberFormatException e) {
771 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
772 return -1;
773 }
774 break;
775 }
776 }
777 }
778
779 try {
780 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
781 if (VDBG) {
782 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
783 + ", result=" + result);
784 }
785 getOutPrintWriter().println(result);
786 } catch (RemoteException e) {
787 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
788 + ", error" + e.getMessage());
789 errPw.println("Exception: " + e.getMessage());
790 return -1;
791 }
792 return 0;
793 }
794
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700795 // ims get-ims-service
796 private int handleImsGetServiceCommand() {
797 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700798 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700799 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800800 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700801
802 String opt;
803 while ((opt = getNextOption()) != null) {
804 switch (opt) {
805 case "-s": {
806 try {
807 slotId = Integer.parseInt(getNextArgRequired());
808 } catch (NumberFormatException e) {
809 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
810 return -1;
811 }
812 break;
813 }
814 case "-c": {
815 isCarrierService = true;
816 break;
817 }
818 case "-d": {
819 isCarrierService = false;
820 break;
821 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800822 case "-f": {
823 try {
824 featureType = Integer.parseInt(getNextArg());
825 } catch (NumberFormatException e) {
826 errPw.println("ims get-ims-service -f requires valid integer as feature.");
827 return -1;
828 }
829 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
830 || featureType >= ImsFeature.FEATURE_MAX) {
831 errPw.println("ims get-ims-service -f invalid feature.");
832 return -1;
833 }
834 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700835 }
836 }
837 // Mandatory param, either -c or -d
838 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800839 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700840 return -1;
841 }
842
843 String result;
844 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800845 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700846 } catch (RemoteException e) {
847 return -1;
848 }
849 if (VDBG) {
850 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800851 + (isCarrierService ? "-c " : "-d ")
852 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
853 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700854 }
855 getOutPrintWriter().println(result);
856 return 0;
857 }
858
859 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700860 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700861 String opt;
862 while ((opt = getNextOption()) != null) {
863 switch (opt) {
864 case "-s": {
865 try {
866 slotId = Integer.parseInt(getNextArgRequired());
867 } catch (NumberFormatException e) {
868 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
869 return -1;
870 }
871 break;
872 }
873 }
874 }
875 try {
876 mInterface.enableIms(slotId);
877 } catch (RemoteException e) {
878 return -1;
879 }
880 if (VDBG) {
881 Log.v(LOG_TAG, "ims enable -s " + slotId);
882 }
883 return 0;
884 }
885
886 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700887 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700888 String opt;
889 while ((opt = getNextOption()) != null) {
890 switch (opt) {
891 case "-s": {
892 try {
893 slotId = Integer.parseInt(getNextArgRequired());
894 } catch (NumberFormatException e) {
895 getErrPrintWriter().println(
896 "ims disable requires an integer as a SLOT_ID.");
897 return -1;
898 }
899 break;
900 }
901 }
902 }
903 try {
904 mInterface.disableIms(slotId);
905 } catch (RemoteException e) {
906 return -1;
907 }
908 if (VDBG) {
909 Log.v(LOG_TAG, "ims disable -s " + slotId);
910 }
911 return 0;
912 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700913
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700914 private int handleCepChange() {
915 Log.i(LOG_TAG, "handleCepChange");
916 String opt = getNextArg();
917 if (opt == null) {
918 return -1;
919 }
920 boolean isCepEnabled = opt.equals("enable");
921
922 try {
923 mInterface.setCepEnabled(isCepEnabled);
924 } catch (RemoteException e) {
925 return -1;
926 }
927 return 0;
928 }
929
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700930 private int getDefaultSlot() {
931 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
932 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
933 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
934 // If there is no default, default to slot 0.
935 slotId = DEFAULT_PHONE_ID;
936 }
937 return slotId;
938 }
sqian2fff4a32018-11-05 14:18:37 -0800939
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100940 // Parse options related to Carrier Config Commands.
941 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100942 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100943 CcOptionParseResult result = new CcOptionParseResult();
944 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
945 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100946
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100947 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100948 while ((opt = getNextOption()) != null) {
949 switch (opt) {
950 case "-s": {
951 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100952 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
953 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
954 errPw.println(tag + "No valid subscription found.");
955 return null;
956 }
957
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100958 } catch (IllegalArgumentException e) {
959 // Missing slot id
960 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100961 return null;
962 }
963 break;
964 }
965 case "-p": {
966 if (allowOptionPersistent) {
967 result.mPersistent = true;
968 } else {
969 errPw.println(tag + "Unexpected option " + opt);
970 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100971 }
972 break;
973 }
974 default: {
975 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100976 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100977 }
978 }
979 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100980 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100981 }
982
983 private int slotStringToSubId(String tag, String slotString) {
984 int slotId = -1;
985 try {
986 slotId = Integer.parseInt(slotString);
987 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800988 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
989 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
990 }
991
992 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100993 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
994 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
995 }
996
Qiong Liuf25799b2020-09-10 10:13:46 +0800997 Phone phone = PhoneFactory.getPhone(slotId);
998 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100999 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1000 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1001 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001002 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001003 }
1004
Hall Liud892bec2018-11-30 14:51:45 -08001005 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001006 // adb can run as root or as shell, depending on whether the device is rooted.
1007 return Binder.getCallingUid() == Process.SHELL_UID
1008 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001009 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001010
1011 private int handleCcCommand() {
1012 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1013 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001014 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001015 getErrPrintWriter().println("cc: Permission denied.");
1016 return -1;
1017 }
1018
1019 String arg = getNextArg();
1020 if (arg == null) {
1021 onHelpCc();
1022 return 0;
1023 }
1024
1025 switch (arg) {
1026 case CC_GET_VALUE: {
1027 return handleCcGetValue();
1028 }
1029 case CC_SET_VALUE: {
1030 return handleCcSetValue();
1031 }
1032 case CC_CLEAR_VALUES: {
1033 return handleCcClearValues();
1034 }
1035 default: {
1036 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1037 }
1038 }
1039 return -1;
1040 }
1041
1042 // cc get-value
1043 private int handleCcGetValue() {
1044 PrintWriter errPw = getErrPrintWriter();
1045 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1046 String key = null;
1047
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001048 // Parse all options
1049 CcOptionParseResult options = parseCcOptions(tag, false);
1050 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001051 return -1;
1052 }
1053
1054 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001055 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001056 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001057 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001058 return -1;
1059 }
1060
1061 // Get the key.
1062 key = getNextArg();
1063 if (key != null) {
1064 // A key was provided. Verify if it is a valid key
1065 if (!bundle.containsKey(key)) {
1066 errPw.println(tag + key + " is not a valid key.");
1067 return -1;
1068 }
1069
1070 // Print the carrier config value for key.
1071 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1072 } else {
1073 // No key provided. Show all values.
1074 // Iterate over a sorted list of all carrier config keys and print them.
1075 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1076 for (String k : sortedSet) {
1077 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1078 }
1079 }
1080 return 0;
1081 }
1082
1083 // cc set-value
1084 private int handleCcSetValue() {
1085 PrintWriter errPw = getErrPrintWriter();
1086 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1087
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001088 // Parse all options
1089 CcOptionParseResult options = parseCcOptions(tag, true);
1090 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001091 return -1;
1092 }
1093
1094 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001095 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001096 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001097 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001098 return -1;
1099 }
1100
1101 // Get the key.
1102 String key = getNextArg();
1103 if (key == null || key.equals("")) {
1104 errPw.println(tag + "KEY is missing");
1105 return -1;
1106 }
1107
1108 // Verify if the key is valid
1109 if (!originalValues.containsKey(key)) {
1110 errPw.println(tag + key + " is not a valid key.");
1111 return -1;
1112 }
1113
1114 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1115 ArrayList<String> valueList = new ArrayList<String>();
1116 while (peekNextArg() != null) {
1117 valueList.add(getNextArg());
1118 }
1119
1120 // Find the type of the carrier config value
1121 CcType type = getType(tag, key, originalValues);
1122 if (type == CcType.UNKNOWN) {
1123 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1124 return -1;
1125 }
1126
1127 // Create an override bundle containing the key and value that should be overriden.
1128 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1129 if (overrideBundle == null) {
1130 return -1;
1131 }
1132
1133 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001134 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001135
1136 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001137 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001138 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001139 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001140 return -1;
1141 }
1142
1143 // Print the original and new value.
1144 String originalValueString = ccValueToString(key, type, originalValues);
1145 String newValueString = ccValueToString(key, type, newValues);
1146 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1147 getOutPrintWriter().println("New value: \n" + newValueString);
1148
1149 return 0;
1150 }
1151
1152 // cc clear-values
1153 private int handleCcClearValues() {
1154 PrintWriter errPw = getErrPrintWriter();
1155 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1156
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001157 // Parse all options
1158 CcOptionParseResult options = parseCcOptions(tag, false);
1159 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001160 return -1;
1161 }
1162
1163 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001164 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001165 getOutPrintWriter()
1166 .println("All previously set carrier config override values has been cleared");
1167 return 0;
1168 }
1169
1170 private CcType getType(String tag, String key, PersistableBundle bundle) {
1171 // Find the type by checking the type of the current value stored in the bundle.
1172 Object value = bundle.get(key);
1173
1174 if (CC_TYPE_MAP.containsKey(key)) {
1175 return CC_TYPE_MAP.get(key);
1176 } else if (value != null) {
1177 if (value instanceof Boolean) {
1178 return CcType.BOOLEAN;
1179 } else if (value instanceof Double) {
1180 return CcType.DOUBLE;
1181 } else if (value instanceof double[]) {
1182 return CcType.DOUBLE_ARRAY;
1183 } else if (value instanceof Integer) {
1184 return CcType.INT;
1185 } else if (value instanceof int[]) {
1186 return CcType.INT_ARRAY;
1187 } else if (value instanceof Long) {
1188 return CcType.LONG;
1189 } else if (value instanceof long[]) {
1190 return CcType.LONG_ARRAY;
1191 } else if (value instanceof String) {
1192 return CcType.STRING;
1193 } else if (value instanceof String[]) {
1194 return CcType.STRING_ARRAY;
1195 }
1196 } else {
1197 // Current value was null and can therefore not be used in order to find the type.
1198 // Check the name of the key to infer the type. This check is not needed for primitive
1199 // data types (boolean, double, int and long), since they can not be null.
1200 if (key.endsWith("double_array")) {
1201 return CcType.DOUBLE_ARRAY;
1202 }
1203 if (key.endsWith("int_array")) {
1204 return CcType.INT_ARRAY;
1205 }
1206 if (key.endsWith("long_array")) {
1207 return CcType.LONG_ARRAY;
1208 }
1209 if (key.endsWith("string")) {
1210 return CcType.STRING;
1211 }
1212 if (key.endsWith("string_array") || key.endsWith("strings")) {
1213 return CcType.STRING_ARRAY;
1214 }
1215 }
1216
1217 // Not possible to infer the type by looking at the current value or the key.
1218 PrintWriter errPw = getErrPrintWriter();
1219 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1220 return CcType.UNKNOWN;
1221 }
1222
1223 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1224 String result;
1225 StringBuilder valueString = new StringBuilder();
1226 String typeString = type.toString();
1227 Object value = bundle.get(key);
1228
1229 if (value == null) {
1230 valueString.append("null");
1231 } else {
1232 switch (type) {
1233 case DOUBLE_ARRAY: {
1234 // Format the string representation of the int array as value1 value2......
1235 double[] valueArray = (double[]) value;
1236 for (int i = 0; i < valueArray.length; i++) {
1237 if (i != 0) {
1238 valueString.append(" ");
1239 }
1240 valueString.append(valueArray[i]);
1241 }
1242 break;
1243 }
1244 case INT_ARRAY: {
1245 // Format the string representation of the int array as value1 value2......
1246 int[] valueArray = (int[]) value;
1247 for (int i = 0; i < valueArray.length; i++) {
1248 if (i != 0) {
1249 valueString.append(" ");
1250 }
1251 valueString.append(valueArray[i]);
1252 }
1253 break;
1254 }
1255 case LONG_ARRAY: {
1256 // Format the string representation of the int array as value1 value2......
1257 long[] valueArray = (long[]) value;
1258 for (int i = 0; i < valueArray.length; i++) {
1259 if (i != 0) {
1260 valueString.append(" ");
1261 }
1262 valueString.append(valueArray[i]);
1263 }
1264 break;
1265 }
1266 case STRING: {
1267 valueString.append("\"" + value.toString() + "\"");
1268 break;
1269 }
1270 case STRING_ARRAY: {
1271 // Format the string representation of the string array as "value1" "value2"....
1272 String[] valueArray = (String[]) value;
1273 for (int i = 0; i < valueArray.length; i++) {
1274 if (i != 0) {
1275 valueString.append(" ");
1276 }
1277 if (valueArray[i] != null) {
1278 valueString.append("\"" + valueArray[i] + "\"");
1279 } else {
1280 valueString.append("null");
1281 }
1282 }
1283 break;
1284 }
1285 default: {
1286 valueString.append(value.toString());
1287 }
1288 }
1289 }
1290 return String.format("%-70s %-15s %s", key, typeString, valueString);
1291 }
1292
1293 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1294 ArrayList<String> valueList) {
1295 PrintWriter errPw = getErrPrintWriter();
1296 PersistableBundle bundle = new PersistableBundle();
1297
1298 // First verify that a valid number of values has been provided for the type.
1299 switch (type) {
1300 case BOOLEAN:
1301 case DOUBLE:
1302 case INT:
1303 case LONG: {
1304 if (valueList.size() != 1) {
1305 errPw.println(tag + "Expected 1 value for type " + type
1306 + ". Found: " + valueList.size());
1307 return null;
1308 }
1309 break;
1310 }
1311 case STRING: {
1312 if (valueList.size() > 1) {
1313 errPw.println(tag + "Expected 0 or 1 values for type " + type
1314 + ". Found: " + valueList.size());
1315 return null;
1316 }
1317 break;
1318 }
1319 }
1320
1321 // Parse the value according to type and add it to the Bundle.
1322 switch (type) {
1323 case BOOLEAN: {
1324 if ("true".equalsIgnoreCase(valueList.get(0))) {
1325 bundle.putBoolean(key, true);
1326 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1327 bundle.putBoolean(key, false);
1328 } else {
1329 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1330 return null;
1331 }
1332 break;
1333 }
1334 case DOUBLE: {
1335 try {
1336 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1337 } catch (NumberFormatException nfe) {
1338 // Not a valid double
1339 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1340 return null;
1341 }
1342 break;
1343 }
1344 case DOUBLE_ARRAY: {
1345 double[] valueDoubleArray = null;
1346 if (valueList.size() > 0) {
1347 valueDoubleArray = new double[valueList.size()];
1348 for (int i = 0; i < valueList.size(); i++) {
1349 try {
1350 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1351 } catch (NumberFormatException nfe) {
1352 // Not a valid double
1353 errPw.println(
1354 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1355 return null;
1356 }
1357 }
1358 }
1359 bundle.putDoubleArray(key, valueDoubleArray);
1360 break;
1361 }
1362 case INT: {
1363 try {
1364 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1365 } catch (NumberFormatException nfe) {
1366 // Not a valid integer
1367 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1368 return null;
1369 }
1370 break;
1371 }
1372 case INT_ARRAY: {
1373 int[] valueIntArray = null;
1374 if (valueList.size() > 0) {
1375 valueIntArray = new int[valueList.size()];
1376 for (int i = 0; i < valueList.size(); i++) {
1377 try {
1378 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1379 } catch (NumberFormatException nfe) {
1380 // Not a valid integer
1381 errPw.println(tag
1382 + "Unable to parse " + valueList.get(i) + " as an integer.");
1383 return null;
1384 }
1385 }
1386 }
1387 bundle.putIntArray(key, valueIntArray);
1388 break;
1389 }
1390 case LONG: {
1391 try {
1392 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1393 } catch (NumberFormatException nfe) {
1394 // Not a valid long
1395 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1396 return null;
1397 }
1398 break;
1399 }
1400 case LONG_ARRAY: {
1401 long[] valueLongArray = null;
1402 if (valueList.size() > 0) {
1403 valueLongArray = new long[valueList.size()];
1404 for (int i = 0; i < valueList.size(); i++) {
1405 try {
1406 valueLongArray[i] = Long.parseLong(valueList.get(i));
1407 } catch (NumberFormatException nfe) {
1408 // Not a valid long
1409 errPw.println(
1410 tag + "Unable to parse " + valueList.get(i) + " as a long");
1411 return null;
1412 }
1413 }
1414 }
1415 bundle.putLongArray(key, valueLongArray);
1416 break;
1417 }
1418 case STRING: {
1419 String value = null;
1420 if (valueList.size() > 0) {
1421 value = valueList.get(0);
1422 }
1423 bundle.putString(key, value);
1424 break;
1425 }
1426 case STRING_ARRAY: {
1427 String[] valueStringArray = null;
1428 if (valueList.size() > 0) {
1429 valueStringArray = new String[valueList.size()];
1430 valueList.toArray(valueStringArray);
1431 }
1432 bundle.putStringArray(key, valueStringArray);
1433 break;
1434 }
1435 }
1436 return bundle;
1437 }
Shuo Qian489d9282020-07-09 11:30:03 -07001438
1439 private int handleEndBlockSuppressionCommand() {
1440 if (!checkShellUid()) {
1441 return -1;
1442 }
1443
1444 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1445 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1446 }
1447 return 0;
1448 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001449
Michele Berionne38c1afa2020-12-28 20:23:16 +00001450 private int handleRestartModemCommand() {
1451 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1452 // non user build.
1453 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1454 getErrPrintWriter().println("RestartModem: Permission denied.");
1455 return -1;
1456 }
1457
1458 boolean result = TelephonyManager.getDefault().rebootRadio();
1459 getOutPrintWriter().println(result);
1460
1461 return result ? 0 : -1;
1462 }
1463
Michele Berionned9fbae52020-11-13 02:36:59 +00001464 private int handleUnattendedReboot() {
1465 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1466 // non user build.
1467 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1468 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1469 return -1;
1470 }
1471
1472 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1473 getOutPrintWriter().println("result: " + result);
1474
1475 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1476 }
1477
Hui Wang0866fcc2020-10-12 12:14:23 -07001478 private int handleGbaCommand() {
1479 String arg = getNextArg();
1480 if (arg == null) {
1481 onHelpGba();
1482 return 0;
1483 }
1484
1485 switch (arg) {
1486 case GBA_SET_SERVICE: {
1487 return handleGbaSetServiceCommand();
1488 }
1489 case GBA_GET_SERVICE: {
1490 return handleGbaGetServiceCommand();
1491 }
1492 case GBA_SET_RELEASE_TIME: {
1493 return handleGbaSetReleaseCommand();
1494 }
1495 case GBA_GET_RELEASE_TIME: {
1496 return handleGbaGetReleaseCommand();
1497 }
1498 }
1499
1500 return -1;
1501 }
1502
1503 private int getSubId(String cmd) {
1504 int slotId = getDefaultSlot();
1505 String opt = getNextOption();
1506 if (opt != null && opt.equals("-s")) {
1507 try {
1508 slotId = Integer.parseInt(getNextArgRequired());
1509 } catch (NumberFormatException e) {
1510 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1511 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1512 }
1513 }
1514 int[] subIds = SubscriptionManager.getSubId(slotId);
1515 return subIds[0];
1516 }
1517
1518 private int handleGbaSetServiceCommand() {
1519 int subId = getSubId("gba set-service");
1520 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1521 return -1;
1522 }
1523
1524 String packageName = getNextArg();
1525 try {
1526 if (packageName == null) {
1527 packageName = "";
1528 }
1529 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1530 if (VDBG) {
1531 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1532 + packageName + ", result=" + result);
1533 }
1534 getOutPrintWriter().println(result);
1535 } catch (RemoteException e) {
1536 Log.w(LOG_TAG, "gba set-service " + subId + " "
1537 + packageName + ", error" + e.getMessage());
1538 getErrPrintWriter().println("Exception: " + e.getMessage());
1539 return -1;
1540 }
1541 return 0;
1542 }
1543
1544 private int handleGbaGetServiceCommand() {
1545 String result;
1546
1547 int subId = getSubId("gba get-service");
1548 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1549 return -1;
1550 }
1551
1552 try {
1553 result = mInterface.getBoundGbaService(subId);
1554 } catch (RemoteException e) {
1555 return -1;
1556 }
1557 if (VDBG) {
1558 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1559 }
1560 getOutPrintWriter().println(result);
1561 return 0;
1562 }
1563
1564 private int handleGbaSetReleaseCommand() {
1565 //the release time value could be -1
1566 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1567 : SubscriptionManager.getDefaultSubscriptionId();
1568 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1569 return -1;
1570 }
1571
1572 String intervalStr = getNextArg();
1573 if (intervalStr == null) {
1574 return -1;
1575 }
1576
1577 try {
1578 int interval = Integer.parseInt(intervalStr);
1579 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1580 if (VDBG) {
1581 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1582 + intervalStr + ", result=" + result);
1583 }
1584 getOutPrintWriter().println(result);
1585 } catch (NumberFormatException | RemoteException e) {
1586 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1587 + intervalStr + ", error" + e.getMessage());
1588 getErrPrintWriter().println("Exception: " + e.getMessage());
1589 return -1;
1590 }
1591 return 0;
1592 }
1593
1594 private int handleGbaGetReleaseCommand() {
1595 int subId = getSubId("gba get-release");
1596 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1597 return -1;
1598 }
1599
1600 int result = 0;
1601 try {
1602 result = mInterface.getGbaReleaseTime(subId);
1603 } catch (RemoteException e) {
1604 return -1;
1605 }
1606 if (VDBG) {
1607 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1608 }
1609 getOutPrintWriter().println(result);
1610 return 0;
1611 }
Hui Wang068ab862020-10-31 05:12:53 +00001612
1613 private int handleSingleRegistrationConfigCommand() {
1614 String arg = getNextArg();
1615 if (arg == null) {
1616 onHelpSrc();
1617 return 0;
1618 }
1619
1620 switch (arg) {
1621 case SRC_SET_DEVICE_ENABLED: {
1622 return handleSrcSetDeviceEnabledCommand();
1623 }
1624 case SRC_GET_DEVICE_ENABLED: {
1625 return handleSrcGetDeviceEnabledCommand();
1626 }
1627 case SRC_SET_CARRIER_ENABLED: {
1628 return handleSrcSetCarrierEnabledCommand();
1629 }
1630 case SRC_GET_CARRIER_ENABLED: {
1631 return handleSrcGetCarrierEnabledCommand();
1632 }
1633 }
1634
1635 return -1;
1636 }
1637
James.cf Linbcdf8b32021-01-14 16:44:13 +08001638 private int handleRcsUceCommand() {
1639 String arg = getNextArg();
1640 if (arg == null) {
1641 Log.w(LOG_TAG, "cannot get uce parameter");
1642 return -1;
1643 }
1644
1645 switch (arg) {
1646 case UCE_REMOVE_EAB_CONTACT:
1647 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001648 case UCE_GET_EAB_CONTACT:
1649 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001650 case UCE_GET_DEVICE_ENABLED:
1651 return handleUceGetDeviceEnabledCommand();
1652 case UCE_SET_DEVICE_ENABLED:
1653 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001654 }
1655 return -1;
1656 }
1657
1658 private int handleRemovingEabContactCommand() {
1659 int subId = getSubId("uce remove-eab-contact");
1660 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1661 return -1;
1662 }
1663
1664 String phoneNumber = getNextArgRequired();
1665 if (TextUtils.isEmpty(phoneNumber)) {
1666 return -1;
1667 }
1668 int result = 0;
1669 try {
1670 result = mInterface.removeContactFromEab(subId, phoneNumber);
1671 } catch (RemoteException e) {
1672 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1673 getErrPrintWriter().println("Exception: " + e.getMessage());
1674 return -1;
1675 }
1676
1677 if (VDBG) {
1678 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1679 }
calvinpan293ea1b2021-02-04 17:52:13 +08001680 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001681 }
1682
calvinpane4a8a1d2021-01-25 13:51:18 +08001683 private int handleGettingEabContactCommand() {
1684 String phoneNumber = getNextArgRequired();
1685 if (TextUtils.isEmpty(phoneNumber)) {
1686 return -1;
1687 }
1688 String result = "";
1689 try {
1690 result = mInterface.getContactFromEab(phoneNumber);
1691
1692 } catch (RemoteException e) {
1693 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1694 getErrPrintWriter().println("Exception: " + e.getMessage());
1695 return -1;
1696 }
1697
1698 if (VDBG) {
1699 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1700 }
calvinpan293ea1b2021-02-04 17:52:13 +08001701 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001702 return 0;
1703 }
1704
1705 private int handleUceGetDeviceEnabledCommand() {
1706 boolean result = false;
1707 try {
1708 result = mInterface.getDeviceUceEnabled();
1709 } catch (RemoteException e) {
1710 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1711 return -1;
1712 }
1713 if (VDBG) {
1714 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1715 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001716 getOutPrintWriter().println(result);
1717 return 0;
1718 }
1719
James.cf Lin4b784aa2021-01-31 03:25:15 +08001720 private int handleUceSetDeviceEnabledCommand() {
1721 String enabledStr = getNextArg();
1722 if (TextUtils.isEmpty(enabledStr)) {
1723 return -1;
1724 }
1725
1726 try {
1727 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1728 mInterface.setDeviceUceEnabled(isEnabled);
1729 if (VDBG) {
1730 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1731 }
1732 } catch (NumberFormatException | RemoteException e) {
1733 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1734 getErrPrintWriter().println("Exception: " + e.getMessage());
1735 return -1;
1736 }
1737 return 0;
1738 }
1739
Hui Wang068ab862020-10-31 05:12:53 +00001740 private int handleSrcSetDeviceEnabledCommand() {
1741 String enabledStr = getNextArg();
1742 if (enabledStr == null) {
1743 return -1;
1744 }
1745
1746 try {
1747 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1748 if (VDBG) {
1749 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1750 }
1751 getOutPrintWriter().println("Done");
1752 } catch (NumberFormatException | RemoteException e) {
1753 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1754 getErrPrintWriter().println("Exception: " + e.getMessage());
1755 return -1;
1756 }
1757 return 0;
1758 }
1759
1760 private int handleSrcGetDeviceEnabledCommand() {
1761 boolean result = false;
1762 try {
1763 result = mInterface.getDeviceSingleRegistrationEnabled();
1764 } catch (RemoteException e) {
1765 return -1;
1766 }
1767 if (VDBG) {
1768 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1769 }
1770 getOutPrintWriter().println(result);
1771 return 0;
1772 }
1773
1774 private int handleSrcSetCarrierEnabledCommand() {
1775 //the release time value could be -1
1776 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1777 : SubscriptionManager.getDefaultSubscriptionId();
1778 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1779 return -1;
1780 }
1781
1782 String enabledStr = getNextArg();
1783 if (enabledStr == null) {
1784 return -1;
1785 }
1786
1787 try {
1788 boolean result =
1789 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1790 if (VDBG) {
1791 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1792 + enabledStr + ", result=" + result);
1793 }
1794 getOutPrintWriter().println(result);
1795 } catch (NumberFormatException | RemoteException e) {
1796 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1797 + enabledStr + ", error" + e.getMessage());
1798 getErrPrintWriter().println("Exception: " + e.getMessage());
1799 return -1;
1800 }
1801 return 0;
1802 }
1803
1804 private int handleSrcGetCarrierEnabledCommand() {
1805 int subId = getSubId("src get-carrier-enabled");
1806 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1807 return -1;
1808 }
1809
1810 boolean result = false;
1811 try {
1812 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1813 } catch (RemoteException e) {
1814 return -1;
1815 }
1816 if (VDBG) {
1817 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1818 }
1819 getOutPrintWriter().println(result);
1820 return 0;
1821 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001822}