blob: 74d6b573d9357c7a0071d080abb5ced5463c5b11 [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";
Hui Wang19a21872021-02-19 20:45:36 -0800105 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
106 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wang068ab862020-10-31 05:12:53 +0000107
Tyler Gunn92479152021-01-20 16:30:10 -0800108 private static final String D2D_SUBCOMMAND = "d2d";
109 private static final String D2D_SEND = "send";
110
James.cf Linbcdf8b32021-01-14 16:44:13 +0800111 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800112 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800113 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800114 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
115 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800116
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700117 // Take advantage of existing methods that already contain permissions checks when possible.
118 private final ITelephony mInterface;
119
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100120 private SubscriptionManager mSubscriptionManager;
121 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700122 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100123
124 private enum CcType {
125 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
126 STRING_ARRAY, UNKNOWN
127 }
128
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100129 private class CcOptionParseResult {
130 public int mSubId;
131 public boolean mPersistent;
132 }
133
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100134 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
135 // keys by looking at the end of the string which usually tells the type.
136 // For instance: "xxxx_string", "xxxx_string_array", etc.
137 // The carrier config keys in this map does not follow this convention. It is therefore not
138 // possible to infer the type for these keys by looking at the string.
139 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
140 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
141 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
142 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
143 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
151 CcType.STRING);
152 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
153 CcType.STRING_ARRAY);
154 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
155 CcType.STRING_ARRAY);
156 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
157 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
158 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
159 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
160 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
161 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
162 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
163 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
164 }
165 };
166
167 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700168 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100169 mCarrierConfigManager =
170 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
171 mSubscriptionManager = (SubscriptionManager)
172 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700173 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700174 }
175
176 @Override
177 public int onCommand(String cmd) {
178 if (cmd == null) {
179 return handleDefaultCommands(null);
180 }
181
182 switch (cmd) {
183 case IMS_SUBCOMMAND: {
184 return handleImsCommand();
185 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800186 case RCS_UCE_COMMAND:
187 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800188 case NUMBER_VERIFICATION_SUBCOMMAND:
189 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800190 case EMERGENCY_NUMBER_TEST_MODE:
191 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100192 case CARRIER_CONFIG_SUBCOMMAND: {
193 return handleCcCommand();
194 }
Shuo Qianf5125122019-12-16 17:03:07 -0800195 case DATA_TEST_MODE:
196 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700197 case END_BLOCK_SUPPRESSION:
198 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700199 case GBA_SUBCOMMAND:
200 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800201 case D2D_SUBCOMMAND:
202 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000203 case SINGLE_REGISTATION_CONFIG:
204 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000205 case RESTART_MODEM:
206 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000207 case UNATTENDED_REBOOT:
208 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700209 default: {
210 return handleDefaultCommands(cmd);
211 }
212 }
213 }
214
215 @Override
216 public void onHelp() {
217 PrintWriter pw = getOutPrintWriter();
218 pw.println("Telephony Commands:");
219 pw.println(" help");
220 pw.println(" Print this help text.");
221 pw.println(" ims");
222 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800223 pw.println(" uce");
224 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800225 pw.println(" emergency-number-test-mode");
226 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700227 pw.println(" end-block-suppression");
228 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800229 pw.println(" data");
230 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100231 pw.println(" cc");
232 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700233 pw.println(" gba");
234 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000235 pw.println(" src");
236 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000237 pw.println(" restart-modem");
238 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000239 pw.println(" unattended-reboot");
240 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700241 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800242 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800243 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700244 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800245 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100246 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700247 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000248 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800249 onHelpD2D();
250 }
251
252 private void onHelpD2D() {
253 PrintWriter pw = getOutPrintWriter();
254 pw.println("D2D Comms Commands:");
255 pw.println(" d2d send TYPE VALUE");
256 pw.println(" Sends a D2D message of specified type and value.");
257 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
258 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
259 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
260 MESSAGE_CALL_AUDIO_CODEC));
261 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
262 + Communicator.messageToString(
263 MESSAGE_DEVICE_BATTERY_STATE));
264 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
265 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700266 }
267
268 private void onHelpIms() {
269 PrintWriter pw = getOutPrintWriter();
270 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800271 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700272 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
273 pw.println(" ImsService. Options are:");
274 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
275 pw.println(" is specified, it will choose the default voice SIM slot.");
276 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
277 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800278 pw.println(" -f: Set the feature that this override if for, if no option is");
279 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700280 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
281 pw.println(" Gets the package name of the currently defined ImsService.");
282 pw.println(" Options are:");
283 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
284 pw.println(" is specified, it will choose the default voice SIM slot.");
285 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000286 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800287 pw.println(" -f: The feature type that the query will be requested for. If none is");
288 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800289 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
290 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
291 pw.println(" configuration overrides. Options are:");
292 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
293 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700294 pw.println(" ims enable [-s SLOT_ID]");
295 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
296 pw.println(" if none is specified.");
297 pw.println(" ims disable [-s SLOT_ID]");
298 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
299 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700300 pw.println(" ims conference-event-package [enable/disable]");
301 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700302 }
303
James.cf Linbcdf8b32021-01-14 16:44:13 +0800304 private void onHelpUce() {
305 PrintWriter pw = getOutPrintWriter();
306 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800307 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
308 pw.println(" Get the EAB contacts from the EAB database.");
309 pw.println(" Options are:");
310 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
311 pw.println(" Expected output format :");
312 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800313 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
314 pw.println(" Remove the EAB contacts from the EAB database.");
315 pw.println(" Options are:");
316 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
317 pw.println(" is specified, it will choose the default voice SIM slot.");
318 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800319 pw.println(" uce get-device-enabled");
320 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
321 pw.println(" uce set-device-enabled true|false");
322 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
323 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800324 }
325
Hall Liud892bec2018-11-30 14:51:45 -0800326 private void onHelpNumberVerification() {
327 PrintWriter pw = getOutPrintWriter();
328 pw.println("Number verification commands");
329 pw.println(" numverify override-package PACKAGE_NAME;");
330 pw.println(" Set the authorized package for number verification.");
331 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800332 pw.println(" numverify fake-call NUMBER;");
333 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
334 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800335 }
336
Shuo Qianf5125122019-12-16 17:03:07 -0800337 private void onHelpDataTestMode() {
338 PrintWriter pw = getOutPrintWriter();
339 pw.println("Mobile Data Test Mode Commands:");
340 pw.println(" data enable: enable mobile data connectivity");
341 pw.println(" data disable: disable mobile data connectivity");
342 }
343
sqian9d4df8b2019-01-15 18:32:07 -0800344 private void onHelpEmergencyNumber() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("Emergency Number Test Mode Commands:");
347 pw.println(" emergency-number-test-mode ");
348 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
349 + " the test mode");
350 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700351 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800352 pw.println(" -c: clear the emergency number list in the test mode.");
353 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700354 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800355 pw.println(" -p: get the full emergency number list in the test mode.");
356 }
357
Shuo Qian489d9282020-07-09 11:30:03 -0700358 private void onHelpEndBlockSupperssion() {
359 PrintWriter pw = getOutPrintWriter();
360 pw.println("End Block Suppression command:");
361 pw.println(" end-block-suppression: disable suppressing blocking by contact");
362 pw.println(" with emergency services.");
363 }
364
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100365 private void onHelpCc() {
366 PrintWriter pw = getOutPrintWriter();
367 pw.println("Carrier Config Commands:");
368 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
369 pw.println(" Print carrier config values.");
370 pw.println(" Options are:");
371 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
372 pw.println(" is specified, it will choose the default voice SIM slot.");
373 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
374 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100375 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100376 pw.println(" Set carrier config KEY to NEW_VALUE.");
377 pw.println(" Options are:");
378 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
379 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100380 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100381 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
382 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
383 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
384 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
385 pw.println(" cc clear-values [-s SLOT_ID]");
386 pw.println(" Clear all carrier override values that has previously been set");
387 pw.println(" with set-value");
388 pw.println(" Options are:");
389 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
390 pw.println(" is specified, it will choose the default voice SIM slot.");
391 }
392
Hui Wang0866fcc2020-10-12 12:14:23 -0700393 private void onHelpGba() {
394 PrintWriter pw = getOutPrintWriter();
395 pw.println("Gba Commands:");
396 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
397 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
398 pw.println(" Options are:");
399 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
400 pw.println(" is specified, it will choose the default voice SIM slot.");
401 pw.println(" gba get-service [-s SLOT_ID]");
402 pw.println(" Gets the package name of the currently defined GbaService.");
403 pw.println(" Options are:");
404 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
405 pw.println(" is specified, it will choose the default voice SIM slot.");
406 pw.println(" gba set-release [-s SLOT_ID] n");
407 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
408 pw.println(" Do not release/unbind if n is -1.");
409 pw.println(" Options are:");
410 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
411 pw.println(" is specified, it will choose the default voice SIM slot.");
412 pw.println(" gba get-release [-s SLOT_ID]");
413 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
414 pw.println(" Options are:");
415 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
416 pw.println(" is specified, it will choose the default voice SIM slot.");
417 }
418
Hui Wang068ab862020-10-31 05:12:53 +0000419 private void onHelpSrc() {
420 PrintWriter pw = getOutPrintWriter();
421 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wang19a21872021-02-19 20:45:36 -0800422 pw.println(" src set-test-enabled true|false");
423 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
424 pw.println(" The value could be true, false, or null(undefined).");
425 pw.println(" src get-test-enabled");
426 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang068ab862020-10-31 05:12:53 +0000427 pw.println(" src set-device-enabled true|false|null");
428 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
429 pw.println(" The value could be true, false, or null(undefined).");
430 pw.println(" src get-device-enabled");
431 pw.println(" Gets the device config for RCS VoLTE single registration.");
432 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
433 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
434 pw.println(" The value could be true, false, or null(undefined).");
435 pw.println(" Options are:");
436 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
437 pw.println(" is specified, it will choose the default voice SIM slot.");
438 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
439 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
440 pw.println(" Options are:");
441 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
442 pw.println(" is specified, it will choose the default voice SIM slot.");
443 }
444
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700445 private int handleImsCommand() {
446 String arg = getNextArg();
447 if (arg == null) {
448 onHelpIms();
449 return 0;
450 }
451
452 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800453 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700454 return handleImsSetServiceCommand();
455 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800456 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700457 return handleImsGetServiceCommand();
458 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800459 case IMS_CLEAR_SERVICE_OVERRIDE: {
460 return handleImsClearCarrierServiceCommand();
461 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700462 case IMS_ENABLE: {
463 return handleEnableIms();
464 }
465 case IMS_DISABLE: {
466 return handleDisableIms();
467 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700468 case IMS_CEP: {
469 return handleCepChange();
470 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700471 }
472
473 return -1;
474 }
475
Shuo Qianf5125122019-12-16 17:03:07 -0800476 private int handleDataTestModeCommand() {
477 PrintWriter errPw = getErrPrintWriter();
478 String arg = getNextArgRequired();
479 if (arg == null) {
480 onHelpDataTestMode();
481 return 0;
482 }
483 switch (arg) {
484 case DATA_ENABLE: {
485 try {
486 mInterface.enableDataConnectivity();
487 } catch (RemoteException ex) {
488 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
489 errPw.println("Exception: " + ex.getMessage());
490 return -1;
491 }
492 break;
493 }
494 case DATA_DISABLE: {
495 try {
496 mInterface.disableDataConnectivity();
497 } catch (RemoteException ex) {
498 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
499 errPw.println("Exception: " + ex.getMessage());
500 return -1;
501 }
502 break;
503 }
504 default:
505 onHelpDataTestMode();
506 break;
507 }
508 return 0;
509 }
510
sqian9d4df8b2019-01-15 18:32:07 -0800511 private int handleEmergencyNumberTestModeCommand() {
512 PrintWriter errPw = getErrPrintWriter();
513 String opt = getNextOption();
514 if (opt == null) {
515 onHelpEmergencyNumber();
516 return 0;
517 }
518
519 switch (opt) {
520 case "-a": {
521 String emergencyNumberCmd = getNextArgRequired();
522 if (emergencyNumberCmd == null
523 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700524 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800525 + " to be specified after -a in the command ");
526 return -1;
527 }
528 try {
529 mInterface.updateEmergencyNumberListTestMode(
530 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
531 new EmergencyNumber(emergencyNumberCmd, "", "",
532 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
533 new ArrayList<String>(),
534 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
535 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
536 } catch (RemoteException ex) {
537 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
538 + ", error " + ex.getMessage());
539 errPw.println("Exception: " + ex.getMessage());
540 return -1;
541 }
542 break;
543 }
544 case "-c": {
545 try {
546 mInterface.updateEmergencyNumberListTestMode(
547 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
548 } catch (RemoteException ex) {
549 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
550 errPw.println("Exception: " + ex.getMessage());
551 return -1;
552 }
553 break;
554 }
555 case "-r": {
556 String emergencyNumberCmd = getNextArgRequired();
557 if (emergencyNumberCmd == null
558 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700559 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800560 + " to be specified after -r in the command ");
561 return -1;
562 }
563 try {
564 mInterface.updateEmergencyNumberListTestMode(
565 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
566 new EmergencyNumber(emergencyNumberCmd, "", "",
567 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
568 new ArrayList<String>(),
569 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
570 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
571 } catch (RemoteException ex) {
572 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
573 + ", error " + ex.getMessage());
574 errPw.println("Exception: " + ex.getMessage());
575 return -1;
576 }
577 break;
578 }
579 case "-p": {
580 try {
581 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
582 } catch (RemoteException ex) {
583 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
584 errPw.println("Exception: " + ex.getMessage());
585 return -1;
586 }
587 break;
588 }
589 default:
590 onHelpEmergencyNumber();
591 break;
592 }
593 return 0;
594 }
595
Hall Liud892bec2018-11-30 14:51:45 -0800596 private int handleNumberVerificationCommand() {
597 String arg = getNextArg();
598 if (arg == null) {
599 onHelpNumberVerification();
600 return 0;
601 }
602
Hall Liuca5af3a2018-12-04 16:58:23 -0800603 if (!checkShellUid()) {
604 return -1;
605 }
606
Hall Liud892bec2018-11-30 14:51:45 -0800607 switch (arg) {
608 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800609 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
610 return 0;
611 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800612 case NUMBER_VERIFICATION_FAKE_CALL: {
613 boolean val = NumberVerificationManager.getInstance()
614 .checkIncomingCall(getNextArg());
615 getOutPrintWriter().println(val ? "1" : "0");
616 return 0;
617 }
Hall Liud892bec2018-11-30 14:51:45 -0800618 }
619
620 return -1;
621 }
622
Tyler Gunn92479152021-01-20 16:30:10 -0800623 private int handleD2dCommand() {
624 String arg = getNextArg();
625 if (arg == null) {
626 onHelpD2D();
627 return 0;
628 }
629
630 switch (arg) {
631 case D2D_SEND: {
632 return handleD2dSendCommand();
633 }
634 }
635
636 return -1;
637 }
638
639 private int handleD2dSendCommand() {
640 PrintWriter errPw = getErrPrintWriter();
641 String opt;
642 int messageType = -1;
643 int messageValue = -1;
644
645
646 String arg = getNextArg();
647 if (arg == null) {
648 onHelpD2D();
649 return 0;
650 }
651 try {
652 messageType = Integer.parseInt(arg);
653 } catch (NumberFormatException e) {
654 errPw.println("message type must be a valid integer");
655 return -1;
656 }
657
658 arg = getNextArg();
659 if (arg == null) {
660 onHelpD2D();
661 return 0;
662 }
663 try {
664 messageValue = Integer.parseInt(arg);
665 } catch (NumberFormatException e) {
666 errPw.println("message value must be a valid integer");
667 return -1;
668 }
669
670 try {
671 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
672 } catch (RemoteException e) {
673 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
674 errPw.println("Exception: " + e.getMessage());
675 return -1;
676 }
677
678 return 0;
679 }
680
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700681 // ims set-ims-service
682 private int handleImsSetServiceCommand() {
683 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700684 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700685 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800686 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700687
688 String opt;
689 while ((opt = getNextOption()) != null) {
690 switch (opt) {
691 case "-s": {
692 try {
693 slotId = Integer.parseInt(getNextArgRequired());
694 } catch (NumberFormatException e) {
695 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
696 return -1;
697 }
698 break;
699 }
700 case "-c": {
701 isCarrierService = true;
702 break;
703 }
704 case "-d": {
705 isCarrierService = false;
706 break;
707 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800708 case "-f": {
709 String featureString = getNextArgRequired();
710 String[] features = featureString.split(",");
711 for (int i = 0; i < features.length; i++) {
712 try {
713 Integer result = Integer.parseInt(features[i]);
714 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
715 || result >= ImsFeature.FEATURE_MAX) {
716 errPw.println("ims set-ims-service -f " + result
717 + " is an invalid feature.");
718 return -1;
719 }
720 featuresList.add(result);
721 } catch (NumberFormatException e) {
722 errPw.println("ims set-ims-service -f tried to parse " + features[i]
723 + " as an integer.");
724 return -1;
725 }
726 }
727 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700728 }
729 }
730 // Mandatory param, either -c or -d
731 if (isCarrierService == null) {
732 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
733 return -1;
734 }
735
736 String packageName = getNextArg();
737
738 try {
739 if (packageName == null) {
740 packageName = "";
741 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800742 int[] featureArray = new int[featuresList.size()];
743 for (int i = 0; i < featuresList.size(); i++) {
744 featureArray[i] = featuresList.get(i);
745 }
746 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
747 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700748 if (VDBG) {
749 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800750 + (isCarrierService ? "-c " : "-d ")
751 + "-f " + featuresList + " "
752 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700753 }
754 getOutPrintWriter().println(result);
755 } catch (RemoteException e) {
756 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800757 + (isCarrierService ? "-c " : "-d ")
758 + "-f " + featuresList + " "
759 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700760 errPw.println("Exception: " + e.getMessage());
761 return -1;
762 }
763 return 0;
764 }
765
Brad Ebinger999d3302020-11-25 14:31:39 -0800766 // ims clear-ims-service-override
767 private int handleImsClearCarrierServiceCommand() {
768 PrintWriter errPw = getErrPrintWriter();
769 int slotId = getDefaultSlot();
770
771 String opt;
772 while ((opt = getNextOption()) != null) {
773 switch (opt) {
774 case "-s": {
775 try {
776 slotId = Integer.parseInt(getNextArgRequired());
777 } catch (NumberFormatException e) {
778 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
779 return -1;
780 }
781 break;
782 }
783 }
784 }
785
786 try {
787 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
788 if (VDBG) {
789 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
790 + ", result=" + result);
791 }
792 getOutPrintWriter().println(result);
793 } catch (RemoteException e) {
794 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
795 + ", error" + e.getMessage());
796 errPw.println("Exception: " + e.getMessage());
797 return -1;
798 }
799 return 0;
800 }
801
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700802 // ims get-ims-service
803 private int handleImsGetServiceCommand() {
804 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700805 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700806 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800807 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700808
809 String opt;
810 while ((opt = getNextOption()) != null) {
811 switch (opt) {
812 case "-s": {
813 try {
814 slotId = Integer.parseInt(getNextArgRequired());
815 } catch (NumberFormatException e) {
816 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
817 return -1;
818 }
819 break;
820 }
821 case "-c": {
822 isCarrierService = true;
823 break;
824 }
825 case "-d": {
826 isCarrierService = false;
827 break;
828 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800829 case "-f": {
830 try {
831 featureType = Integer.parseInt(getNextArg());
832 } catch (NumberFormatException e) {
833 errPw.println("ims get-ims-service -f requires valid integer as feature.");
834 return -1;
835 }
836 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
837 || featureType >= ImsFeature.FEATURE_MAX) {
838 errPw.println("ims get-ims-service -f invalid feature.");
839 return -1;
840 }
841 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700842 }
843 }
844 // Mandatory param, either -c or -d
845 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800846 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700847 return -1;
848 }
849
850 String result;
851 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800852 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700853 } catch (RemoteException e) {
854 return -1;
855 }
856 if (VDBG) {
857 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800858 + (isCarrierService ? "-c " : "-d ")
859 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
860 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700861 }
862 getOutPrintWriter().println(result);
863 return 0;
864 }
865
866 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700867 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700868 String opt;
869 while ((opt = getNextOption()) != null) {
870 switch (opt) {
871 case "-s": {
872 try {
873 slotId = Integer.parseInt(getNextArgRequired());
874 } catch (NumberFormatException e) {
875 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
876 return -1;
877 }
878 break;
879 }
880 }
881 }
882 try {
883 mInterface.enableIms(slotId);
884 } catch (RemoteException e) {
885 return -1;
886 }
887 if (VDBG) {
888 Log.v(LOG_TAG, "ims enable -s " + slotId);
889 }
890 return 0;
891 }
892
893 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700894 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700895 String opt;
896 while ((opt = getNextOption()) != null) {
897 switch (opt) {
898 case "-s": {
899 try {
900 slotId = Integer.parseInt(getNextArgRequired());
901 } catch (NumberFormatException e) {
902 getErrPrintWriter().println(
903 "ims disable requires an integer as a SLOT_ID.");
904 return -1;
905 }
906 break;
907 }
908 }
909 }
910 try {
911 mInterface.disableIms(slotId);
912 } catch (RemoteException e) {
913 return -1;
914 }
915 if (VDBG) {
916 Log.v(LOG_TAG, "ims disable -s " + slotId);
917 }
918 return 0;
919 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700920
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700921 private int handleCepChange() {
922 Log.i(LOG_TAG, "handleCepChange");
923 String opt = getNextArg();
924 if (opt == null) {
925 return -1;
926 }
927 boolean isCepEnabled = opt.equals("enable");
928
929 try {
930 mInterface.setCepEnabled(isCepEnabled);
931 } catch (RemoteException e) {
932 return -1;
933 }
934 return 0;
935 }
936
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700937 private int getDefaultSlot() {
938 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
939 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
940 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
941 // If there is no default, default to slot 0.
942 slotId = DEFAULT_PHONE_ID;
943 }
944 return slotId;
945 }
sqian2fff4a32018-11-05 14:18:37 -0800946
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100947 // Parse options related to Carrier Config Commands.
948 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100949 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100950 CcOptionParseResult result = new CcOptionParseResult();
951 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
952 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100953
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100954 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100955 while ((opt = getNextOption()) != null) {
956 switch (opt) {
957 case "-s": {
958 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100959 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
960 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
961 errPw.println(tag + "No valid subscription found.");
962 return null;
963 }
964
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100965 } catch (IllegalArgumentException e) {
966 // Missing slot id
967 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100968 return null;
969 }
970 break;
971 }
972 case "-p": {
973 if (allowOptionPersistent) {
974 result.mPersistent = true;
975 } else {
976 errPw.println(tag + "Unexpected option " + opt);
977 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100978 }
979 break;
980 }
981 default: {
982 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100983 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100984 }
985 }
986 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100987 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100988 }
989
990 private int slotStringToSubId(String tag, String slotString) {
991 int slotId = -1;
992 try {
993 slotId = Integer.parseInt(slotString);
994 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800995 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
996 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
997 }
998
999 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001000 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1001 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1002 }
1003
Qiong Liuf25799b2020-09-10 10:13:46 +08001004 Phone phone = PhoneFactory.getPhone(slotId);
1005 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001006 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1007 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1008 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001009 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001010 }
1011
Hall Liud892bec2018-11-30 14:51:45 -08001012 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001013 // adb can run as root or as shell, depending on whether the device is rooted.
1014 return Binder.getCallingUid() == Process.SHELL_UID
1015 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001016 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001017
1018 private int handleCcCommand() {
1019 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1020 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001021 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001022 getErrPrintWriter().println("cc: Permission denied.");
1023 return -1;
1024 }
1025
1026 String arg = getNextArg();
1027 if (arg == null) {
1028 onHelpCc();
1029 return 0;
1030 }
1031
1032 switch (arg) {
1033 case CC_GET_VALUE: {
1034 return handleCcGetValue();
1035 }
1036 case CC_SET_VALUE: {
1037 return handleCcSetValue();
1038 }
1039 case CC_CLEAR_VALUES: {
1040 return handleCcClearValues();
1041 }
1042 default: {
1043 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1044 }
1045 }
1046 return -1;
1047 }
1048
1049 // cc get-value
1050 private int handleCcGetValue() {
1051 PrintWriter errPw = getErrPrintWriter();
1052 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1053 String key = null;
1054
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001055 // Parse all options
1056 CcOptionParseResult options = parseCcOptions(tag, false);
1057 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001058 return -1;
1059 }
1060
1061 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001062 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001063 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001064 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001065 return -1;
1066 }
1067
1068 // Get the key.
1069 key = getNextArg();
1070 if (key != null) {
1071 // A key was provided. Verify if it is a valid key
1072 if (!bundle.containsKey(key)) {
1073 errPw.println(tag + key + " is not a valid key.");
1074 return -1;
1075 }
1076
1077 // Print the carrier config value for key.
1078 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1079 } else {
1080 // No key provided. Show all values.
1081 // Iterate over a sorted list of all carrier config keys and print them.
1082 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1083 for (String k : sortedSet) {
1084 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1085 }
1086 }
1087 return 0;
1088 }
1089
1090 // cc set-value
1091 private int handleCcSetValue() {
1092 PrintWriter errPw = getErrPrintWriter();
1093 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1094
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001095 // Parse all options
1096 CcOptionParseResult options = parseCcOptions(tag, true);
1097 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001098 return -1;
1099 }
1100
1101 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001102 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001103 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001104 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001105 return -1;
1106 }
1107
1108 // Get the key.
1109 String key = getNextArg();
1110 if (key == null || key.equals("")) {
1111 errPw.println(tag + "KEY is missing");
1112 return -1;
1113 }
1114
1115 // Verify if the key is valid
1116 if (!originalValues.containsKey(key)) {
1117 errPw.println(tag + key + " is not a valid key.");
1118 return -1;
1119 }
1120
1121 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1122 ArrayList<String> valueList = new ArrayList<String>();
1123 while (peekNextArg() != null) {
1124 valueList.add(getNextArg());
1125 }
1126
1127 // Find the type of the carrier config value
1128 CcType type = getType(tag, key, originalValues);
1129 if (type == CcType.UNKNOWN) {
1130 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1131 return -1;
1132 }
1133
1134 // Create an override bundle containing the key and value that should be overriden.
1135 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1136 if (overrideBundle == null) {
1137 return -1;
1138 }
1139
1140 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001141 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001142
1143 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001144 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001145 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001146 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001147 return -1;
1148 }
1149
1150 // Print the original and new value.
1151 String originalValueString = ccValueToString(key, type, originalValues);
1152 String newValueString = ccValueToString(key, type, newValues);
1153 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1154 getOutPrintWriter().println("New value: \n" + newValueString);
1155
1156 return 0;
1157 }
1158
1159 // cc clear-values
1160 private int handleCcClearValues() {
1161 PrintWriter errPw = getErrPrintWriter();
1162 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1163
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001164 // Parse all options
1165 CcOptionParseResult options = parseCcOptions(tag, false);
1166 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001167 return -1;
1168 }
1169
1170 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001171 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001172 getOutPrintWriter()
1173 .println("All previously set carrier config override values has been cleared");
1174 return 0;
1175 }
1176
1177 private CcType getType(String tag, String key, PersistableBundle bundle) {
1178 // Find the type by checking the type of the current value stored in the bundle.
1179 Object value = bundle.get(key);
1180
1181 if (CC_TYPE_MAP.containsKey(key)) {
1182 return CC_TYPE_MAP.get(key);
1183 } else if (value != null) {
1184 if (value instanceof Boolean) {
1185 return CcType.BOOLEAN;
1186 } else if (value instanceof Double) {
1187 return CcType.DOUBLE;
1188 } else if (value instanceof double[]) {
1189 return CcType.DOUBLE_ARRAY;
1190 } else if (value instanceof Integer) {
1191 return CcType.INT;
1192 } else if (value instanceof int[]) {
1193 return CcType.INT_ARRAY;
1194 } else if (value instanceof Long) {
1195 return CcType.LONG;
1196 } else if (value instanceof long[]) {
1197 return CcType.LONG_ARRAY;
1198 } else if (value instanceof String) {
1199 return CcType.STRING;
1200 } else if (value instanceof String[]) {
1201 return CcType.STRING_ARRAY;
1202 }
1203 } else {
1204 // Current value was null and can therefore not be used in order to find the type.
1205 // Check the name of the key to infer the type. This check is not needed for primitive
1206 // data types (boolean, double, int and long), since they can not be null.
1207 if (key.endsWith("double_array")) {
1208 return CcType.DOUBLE_ARRAY;
1209 }
1210 if (key.endsWith("int_array")) {
1211 return CcType.INT_ARRAY;
1212 }
1213 if (key.endsWith("long_array")) {
1214 return CcType.LONG_ARRAY;
1215 }
1216 if (key.endsWith("string")) {
1217 return CcType.STRING;
1218 }
1219 if (key.endsWith("string_array") || key.endsWith("strings")) {
1220 return CcType.STRING_ARRAY;
1221 }
1222 }
1223
1224 // Not possible to infer the type by looking at the current value or the key.
1225 PrintWriter errPw = getErrPrintWriter();
1226 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1227 return CcType.UNKNOWN;
1228 }
1229
1230 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1231 String result;
1232 StringBuilder valueString = new StringBuilder();
1233 String typeString = type.toString();
1234 Object value = bundle.get(key);
1235
1236 if (value == null) {
1237 valueString.append("null");
1238 } else {
1239 switch (type) {
1240 case DOUBLE_ARRAY: {
1241 // Format the string representation of the int array as value1 value2......
1242 double[] valueArray = (double[]) value;
1243 for (int i = 0; i < valueArray.length; i++) {
1244 if (i != 0) {
1245 valueString.append(" ");
1246 }
1247 valueString.append(valueArray[i]);
1248 }
1249 break;
1250 }
1251 case INT_ARRAY: {
1252 // Format the string representation of the int array as value1 value2......
1253 int[] valueArray = (int[]) value;
1254 for (int i = 0; i < valueArray.length; i++) {
1255 if (i != 0) {
1256 valueString.append(" ");
1257 }
1258 valueString.append(valueArray[i]);
1259 }
1260 break;
1261 }
1262 case LONG_ARRAY: {
1263 // Format the string representation of the int array as value1 value2......
1264 long[] valueArray = (long[]) value;
1265 for (int i = 0; i < valueArray.length; i++) {
1266 if (i != 0) {
1267 valueString.append(" ");
1268 }
1269 valueString.append(valueArray[i]);
1270 }
1271 break;
1272 }
1273 case STRING: {
1274 valueString.append("\"" + value.toString() + "\"");
1275 break;
1276 }
1277 case STRING_ARRAY: {
1278 // Format the string representation of the string array as "value1" "value2"....
1279 String[] valueArray = (String[]) value;
1280 for (int i = 0; i < valueArray.length; i++) {
1281 if (i != 0) {
1282 valueString.append(" ");
1283 }
1284 if (valueArray[i] != null) {
1285 valueString.append("\"" + valueArray[i] + "\"");
1286 } else {
1287 valueString.append("null");
1288 }
1289 }
1290 break;
1291 }
1292 default: {
1293 valueString.append(value.toString());
1294 }
1295 }
1296 }
1297 return String.format("%-70s %-15s %s", key, typeString, valueString);
1298 }
1299
1300 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1301 ArrayList<String> valueList) {
1302 PrintWriter errPw = getErrPrintWriter();
1303 PersistableBundle bundle = new PersistableBundle();
1304
1305 // First verify that a valid number of values has been provided for the type.
1306 switch (type) {
1307 case BOOLEAN:
1308 case DOUBLE:
1309 case INT:
1310 case LONG: {
1311 if (valueList.size() != 1) {
1312 errPw.println(tag + "Expected 1 value for type " + type
1313 + ". Found: " + valueList.size());
1314 return null;
1315 }
1316 break;
1317 }
1318 case STRING: {
1319 if (valueList.size() > 1) {
1320 errPw.println(tag + "Expected 0 or 1 values for type " + type
1321 + ". Found: " + valueList.size());
1322 return null;
1323 }
1324 break;
1325 }
1326 }
1327
1328 // Parse the value according to type and add it to the Bundle.
1329 switch (type) {
1330 case BOOLEAN: {
1331 if ("true".equalsIgnoreCase(valueList.get(0))) {
1332 bundle.putBoolean(key, true);
1333 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1334 bundle.putBoolean(key, false);
1335 } else {
1336 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1337 return null;
1338 }
1339 break;
1340 }
1341 case DOUBLE: {
1342 try {
1343 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1344 } catch (NumberFormatException nfe) {
1345 // Not a valid double
1346 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1347 return null;
1348 }
1349 break;
1350 }
1351 case DOUBLE_ARRAY: {
1352 double[] valueDoubleArray = null;
1353 if (valueList.size() > 0) {
1354 valueDoubleArray = new double[valueList.size()];
1355 for (int i = 0; i < valueList.size(); i++) {
1356 try {
1357 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1358 } catch (NumberFormatException nfe) {
1359 // Not a valid double
1360 errPw.println(
1361 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1362 return null;
1363 }
1364 }
1365 }
1366 bundle.putDoubleArray(key, valueDoubleArray);
1367 break;
1368 }
1369 case INT: {
1370 try {
1371 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1372 } catch (NumberFormatException nfe) {
1373 // Not a valid integer
1374 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1375 return null;
1376 }
1377 break;
1378 }
1379 case INT_ARRAY: {
1380 int[] valueIntArray = null;
1381 if (valueList.size() > 0) {
1382 valueIntArray = new int[valueList.size()];
1383 for (int i = 0; i < valueList.size(); i++) {
1384 try {
1385 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1386 } catch (NumberFormatException nfe) {
1387 // Not a valid integer
1388 errPw.println(tag
1389 + "Unable to parse " + valueList.get(i) + " as an integer.");
1390 return null;
1391 }
1392 }
1393 }
1394 bundle.putIntArray(key, valueIntArray);
1395 break;
1396 }
1397 case LONG: {
1398 try {
1399 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1400 } catch (NumberFormatException nfe) {
1401 // Not a valid long
1402 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1403 return null;
1404 }
1405 break;
1406 }
1407 case LONG_ARRAY: {
1408 long[] valueLongArray = null;
1409 if (valueList.size() > 0) {
1410 valueLongArray = new long[valueList.size()];
1411 for (int i = 0; i < valueList.size(); i++) {
1412 try {
1413 valueLongArray[i] = Long.parseLong(valueList.get(i));
1414 } catch (NumberFormatException nfe) {
1415 // Not a valid long
1416 errPw.println(
1417 tag + "Unable to parse " + valueList.get(i) + " as a long");
1418 return null;
1419 }
1420 }
1421 }
1422 bundle.putLongArray(key, valueLongArray);
1423 break;
1424 }
1425 case STRING: {
1426 String value = null;
1427 if (valueList.size() > 0) {
1428 value = valueList.get(0);
1429 }
1430 bundle.putString(key, value);
1431 break;
1432 }
1433 case STRING_ARRAY: {
1434 String[] valueStringArray = null;
1435 if (valueList.size() > 0) {
1436 valueStringArray = new String[valueList.size()];
1437 valueList.toArray(valueStringArray);
1438 }
1439 bundle.putStringArray(key, valueStringArray);
1440 break;
1441 }
1442 }
1443 return bundle;
1444 }
Shuo Qian489d9282020-07-09 11:30:03 -07001445
1446 private int handleEndBlockSuppressionCommand() {
1447 if (!checkShellUid()) {
1448 return -1;
1449 }
1450
1451 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1452 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1453 }
1454 return 0;
1455 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001456
Michele Berionne38c1afa2020-12-28 20:23:16 +00001457 private int handleRestartModemCommand() {
1458 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1459 // non user build.
1460 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1461 getErrPrintWriter().println("RestartModem: Permission denied.");
1462 return -1;
1463 }
1464
1465 boolean result = TelephonyManager.getDefault().rebootRadio();
1466 getOutPrintWriter().println(result);
1467
1468 return result ? 0 : -1;
1469 }
1470
Michele Berionned9fbae52020-11-13 02:36:59 +00001471 private int handleUnattendedReboot() {
1472 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1473 // non user build.
1474 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1475 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1476 return -1;
1477 }
1478
1479 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1480 getOutPrintWriter().println("result: " + result);
1481
1482 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1483 }
1484
Hui Wang0866fcc2020-10-12 12:14:23 -07001485 private int handleGbaCommand() {
1486 String arg = getNextArg();
1487 if (arg == null) {
1488 onHelpGba();
1489 return 0;
1490 }
1491
1492 switch (arg) {
1493 case GBA_SET_SERVICE: {
1494 return handleGbaSetServiceCommand();
1495 }
1496 case GBA_GET_SERVICE: {
1497 return handleGbaGetServiceCommand();
1498 }
1499 case GBA_SET_RELEASE_TIME: {
1500 return handleGbaSetReleaseCommand();
1501 }
1502 case GBA_GET_RELEASE_TIME: {
1503 return handleGbaGetReleaseCommand();
1504 }
1505 }
1506
1507 return -1;
1508 }
1509
1510 private int getSubId(String cmd) {
1511 int slotId = getDefaultSlot();
1512 String opt = getNextOption();
1513 if (opt != null && opt.equals("-s")) {
1514 try {
1515 slotId = Integer.parseInt(getNextArgRequired());
1516 } catch (NumberFormatException e) {
1517 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1518 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1519 }
1520 }
1521 int[] subIds = SubscriptionManager.getSubId(slotId);
1522 return subIds[0];
1523 }
1524
1525 private int handleGbaSetServiceCommand() {
1526 int subId = getSubId("gba set-service");
1527 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1528 return -1;
1529 }
1530
1531 String packageName = getNextArg();
1532 try {
1533 if (packageName == null) {
1534 packageName = "";
1535 }
1536 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1537 if (VDBG) {
1538 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1539 + packageName + ", result=" + result);
1540 }
1541 getOutPrintWriter().println(result);
1542 } catch (RemoteException e) {
1543 Log.w(LOG_TAG, "gba set-service " + subId + " "
1544 + packageName + ", error" + e.getMessage());
1545 getErrPrintWriter().println("Exception: " + e.getMessage());
1546 return -1;
1547 }
1548 return 0;
1549 }
1550
1551 private int handleGbaGetServiceCommand() {
1552 String result;
1553
1554 int subId = getSubId("gba get-service");
1555 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1556 return -1;
1557 }
1558
1559 try {
1560 result = mInterface.getBoundGbaService(subId);
1561 } catch (RemoteException e) {
1562 return -1;
1563 }
1564 if (VDBG) {
1565 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1566 }
1567 getOutPrintWriter().println(result);
1568 return 0;
1569 }
1570
1571 private int handleGbaSetReleaseCommand() {
1572 //the release time value could be -1
1573 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1574 : SubscriptionManager.getDefaultSubscriptionId();
1575 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1576 return -1;
1577 }
1578
1579 String intervalStr = getNextArg();
1580 if (intervalStr == null) {
1581 return -1;
1582 }
1583
1584 try {
1585 int interval = Integer.parseInt(intervalStr);
1586 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1587 if (VDBG) {
1588 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1589 + intervalStr + ", result=" + result);
1590 }
1591 getOutPrintWriter().println(result);
1592 } catch (NumberFormatException | RemoteException e) {
1593 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1594 + intervalStr + ", error" + e.getMessage());
1595 getErrPrintWriter().println("Exception: " + e.getMessage());
1596 return -1;
1597 }
1598 return 0;
1599 }
1600
1601 private int handleGbaGetReleaseCommand() {
1602 int subId = getSubId("gba get-release");
1603 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1604 return -1;
1605 }
1606
1607 int result = 0;
1608 try {
1609 result = mInterface.getGbaReleaseTime(subId);
1610 } catch (RemoteException e) {
1611 return -1;
1612 }
1613 if (VDBG) {
1614 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1615 }
1616 getOutPrintWriter().println(result);
1617 return 0;
1618 }
Hui Wang068ab862020-10-31 05:12:53 +00001619
1620 private int handleSingleRegistrationConfigCommand() {
1621 String arg = getNextArg();
1622 if (arg == null) {
1623 onHelpSrc();
1624 return 0;
1625 }
1626
1627 switch (arg) {
Hui Wang19a21872021-02-19 20:45:36 -08001628 case SRC_SET_TEST_ENABLED: {
1629 return handleSrcSetTestEnabledCommand();
1630 }
1631 case SRC_GET_TEST_ENABLED: {
1632 return handleSrcGetTestEnabledCommand();
1633 }
Hui Wang068ab862020-10-31 05:12:53 +00001634 case SRC_SET_DEVICE_ENABLED: {
1635 return handleSrcSetDeviceEnabledCommand();
1636 }
1637 case SRC_GET_DEVICE_ENABLED: {
1638 return handleSrcGetDeviceEnabledCommand();
1639 }
1640 case SRC_SET_CARRIER_ENABLED: {
1641 return handleSrcSetCarrierEnabledCommand();
1642 }
1643 case SRC_GET_CARRIER_ENABLED: {
1644 return handleSrcGetCarrierEnabledCommand();
1645 }
1646 }
1647
1648 return -1;
1649 }
1650
James.cf Linbcdf8b32021-01-14 16:44:13 +08001651 private int handleRcsUceCommand() {
1652 String arg = getNextArg();
1653 if (arg == null) {
1654 Log.w(LOG_TAG, "cannot get uce parameter");
1655 return -1;
1656 }
1657
1658 switch (arg) {
1659 case UCE_REMOVE_EAB_CONTACT:
1660 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001661 case UCE_GET_EAB_CONTACT:
1662 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001663 case UCE_GET_DEVICE_ENABLED:
1664 return handleUceGetDeviceEnabledCommand();
1665 case UCE_SET_DEVICE_ENABLED:
1666 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001667 }
1668 return -1;
1669 }
1670
1671 private int handleRemovingEabContactCommand() {
1672 int subId = getSubId("uce remove-eab-contact");
1673 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1674 return -1;
1675 }
1676
1677 String phoneNumber = getNextArgRequired();
1678 if (TextUtils.isEmpty(phoneNumber)) {
1679 return -1;
1680 }
1681 int result = 0;
1682 try {
1683 result = mInterface.removeContactFromEab(subId, phoneNumber);
1684 } catch (RemoteException e) {
1685 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1686 getErrPrintWriter().println("Exception: " + e.getMessage());
1687 return -1;
1688 }
1689
1690 if (VDBG) {
1691 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1692 }
calvinpan293ea1b2021-02-04 17:52:13 +08001693 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001694 }
1695
calvinpane4a8a1d2021-01-25 13:51:18 +08001696 private int handleGettingEabContactCommand() {
1697 String phoneNumber = getNextArgRequired();
1698 if (TextUtils.isEmpty(phoneNumber)) {
1699 return -1;
1700 }
1701 String result = "";
1702 try {
1703 result = mInterface.getContactFromEab(phoneNumber);
1704
1705 } catch (RemoteException e) {
1706 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1707 getErrPrintWriter().println("Exception: " + e.getMessage());
1708 return -1;
1709 }
1710
1711 if (VDBG) {
1712 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1713 }
calvinpan293ea1b2021-02-04 17:52:13 +08001714 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001715 return 0;
1716 }
1717
1718 private int handleUceGetDeviceEnabledCommand() {
1719 boolean result = false;
1720 try {
1721 result = mInterface.getDeviceUceEnabled();
1722 } catch (RemoteException e) {
1723 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1724 return -1;
1725 }
1726 if (VDBG) {
1727 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1728 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001729 getOutPrintWriter().println(result);
1730 return 0;
1731 }
1732
James.cf Lin4b784aa2021-01-31 03:25:15 +08001733 private int handleUceSetDeviceEnabledCommand() {
1734 String enabledStr = getNextArg();
1735 if (TextUtils.isEmpty(enabledStr)) {
1736 return -1;
1737 }
1738
1739 try {
1740 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1741 mInterface.setDeviceUceEnabled(isEnabled);
1742 if (VDBG) {
1743 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1744 }
1745 } catch (NumberFormatException | RemoteException e) {
1746 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1747 getErrPrintWriter().println("Exception: " + e.getMessage());
1748 return -1;
1749 }
1750 return 0;
1751 }
1752
Hui Wang19a21872021-02-19 20:45:36 -08001753 private int handleSrcSetTestEnabledCommand() {
1754 String enabledStr = getNextArg();
1755 if (enabledStr == null) {
1756 return -1;
1757 }
1758
1759 try {
1760 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1761 if (VDBG) {
1762 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1763 }
1764 getOutPrintWriter().println("Done");
1765 } catch (NumberFormatException | RemoteException e) {
1766 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1767 getErrPrintWriter().println("Exception: " + e.getMessage());
1768 return -1;
1769 }
1770 return 0;
1771 }
1772
1773 private int handleSrcGetTestEnabledCommand() {
1774 boolean result = false;
1775 try {
1776 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1777 } catch (RemoteException e) {
1778 return -1;
1779 }
1780 if (VDBG) {
1781 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1782 }
1783 getOutPrintWriter().println(result);
1784 return 0;
1785 }
1786
Hui Wang068ab862020-10-31 05:12:53 +00001787 private int handleSrcSetDeviceEnabledCommand() {
1788 String enabledStr = getNextArg();
1789 if (enabledStr == null) {
1790 return -1;
1791 }
1792
1793 try {
1794 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1795 if (VDBG) {
1796 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1797 }
1798 getOutPrintWriter().println("Done");
1799 } catch (NumberFormatException | RemoteException e) {
1800 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1801 getErrPrintWriter().println("Exception: " + e.getMessage());
1802 return -1;
1803 }
1804 return 0;
1805 }
1806
1807 private int handleSrcGetDeviceEnabledCommand() {
1808 boolean result = false;
1809 try {
1810 result = mInterface.getDeviceSingleRegistrationEnabled();
1811 } catch (RemoteException e) {
1812 return -1;
1813 }
1814 if (VDBG) {
1815 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1816 }
1817 getOutPrintWriter().println(result);
1818 return 0;
1819 }
1820
1821 private int handleSrcSetCarrierEnabledCommand() {
1822 //the release time value could be -1
1823 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1824 : SubscriptionManager.getDefaultSubscriptionId();
1825 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1826 return -1;
1827 }
1828
1829 String enabledStr = getNextArg();
1830 if (enabledStr == null) {
1831 return -1;
1832 }
1833
1834 try {
1835 boolean result =
1836 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1837 if (VDBG) {
1838 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1839 + enabledStr + ", result=" + result);
1840 }
1841 getOutPrintWriter().println(result);
1842 } catch (NumberFormatException | RemoteException e) {
1843 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1844 + enabledStr + ", error" + e.getMessage());
1845 getErrPrintWriter().println("Exception: " + e.getMessage());
1846 return -1;
1847 }
1848 return 0;
1849 }
1850
1851 private int handleSrcGetCarrierEnabledCommand() {
1852 int subId = getSubId("src get-carrier-enabled");
1853 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1854 return -1;
1855 }
1856
1857 boolean result = false;
1858 try {
1859 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1860 } catch (RemoteException e) {
1861 return -1;
1862 }
1863 if (VDBG) {
1864 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1865 }
1866 getOutPrintWriter().println(result);
1867 return 0;
1868 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001869}