blob: 1bd60509066d1a20b73691b950ab9f8b60db9f63 [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";
Shuo Qian479dd9e2021-02-22 18:32:21 -080068 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080069 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070070 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne38c1afa2020-12-28 20:23:16 +000071 private static final String RESTART_MODEM = "restart-modem";
Michele Berionned9fbae52020-11-13 02:36:59 +000072 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010073 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080074 private static final String DATA_TEST_MODE = "data";
75 private static final String DATA_ENABLE = "enable";
76 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080077
Brad Ebinger999d3302020-11-25 14:31:39 -080078 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
79 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
80 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070081 private static final String IMS_ENABLE = "enable";
82 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070083 // Used to disable or enable processing of conference event package data from the network.
84 // This is handy for testing scenarios where CEP data does not exist on a network which does
85 // support CEP data.
86 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070087
Hall Liud892bec2018-11-30 14:51:45 -080088 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080089 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080090
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010091 private static final String CC_GET_VALUE = "get-value";
92 private static final String CC_SET_VALUE = "set-value";
93 private static final String CC_CLEAR_VALUES = "clear-values";
94
Hui Wang0866fcc2020-10-12 12:14:23 -070095 private static final String GBA_SUBCOMMAND = "gba";
96 private static final String GBA_SET_SERVICE = "set-service";
97 private static final String GBA_GET_SERVICE = "get-service";
98 private static final String GBA_SET_RELEASE_TIME = "set-release";
99 private static final String GBA_GET_RELEASE_TIME = "get-release";
100
Hui Wang068ab862020-10-31 05:12:53 +0000101 private static final String SINGLE_REGISTATION_CONFIG = "src";
102 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
103 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
104 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
105 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
106
Tyler Gunn92479152021-01-20 16:30:10 -0800107 private static final String D2D_SUBCOMMAND = "d2d";
108 private static final String D2D_SEND = "send";
109
James.cf Linbcdf8b32021-01-14 16:44:13 +0800110 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800111 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800112 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800113 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
114 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800115
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700116 // Take advantage of existing methods that already contain permissions checks when possible.
117 private final ITelephony mInterface;
118
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100119 private SubscriptionManager mSubscriptionManager;
120 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700121 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100122
123 private enum CcType {
124 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
125 STRING_ARRAY, UNKNOWN
126 }
127
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100128 private class CcOptionParseResult {
129 public int mSubId;
130 public boolean mPersistent;
131 }
132
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100133 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
134 // keys by looking at the end of the string which usually tells the type.
135 // For instance: "xxxx_string", "xxxx_string_array", etc.
136 // The carrier config keys in this map does not follow this convention. It is therefore not
137 // possible to infer the type for these keys by looking at the string.
138 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
139 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
140 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
141 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
142 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
143 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
150 CcType.STRING);
151 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
152 CcType.STRING_ARRAY);
153 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
154 CcType.STRING_ARRAY);
155 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
156 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
157 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
158 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
159 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
160 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
161 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
162 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
163 }
164 };
165
166 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700167 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100168 mCarrierConfigManager =
169 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
170 mSubscriptionManager = (SubscriptionManager)
171 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700172 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700173 }
174
175 @Override
176 public int onCommand(String cmd) {
177 if (cmd == null) {
178 return handleDefaultCommands(null);
179 }
180
181 switch (cmd) {
182 case IMS_SUBCOMMAND: {
183 return handleImsCommand();
184 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800185 case RCS_UCE_COMMAND:
186 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800187 case NUMBER_VERIFICATION_SUBCOMMAND:
188 return handleNumberVerificationCommand();
Shuo Qian479dd9e2021-02-22 18:32:21 -0800189 case EMERGENCY_CALLBACK_MODE:
190 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800191 case EMERGENCY_NUMBER_TEST_MODE:
192 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100193 case CARRIER_CONFIG_SUBCOMMAND: {
194 return handleCcCommand();
195 }
Shuo Qianf5125122019-12-16 17:03:07 -0800196 case DATA_TEST_MODE:
197 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700198 case END_BLOCK_SUPPRESSION:
199 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700200 case GBA_SUBCOMMAND:
201 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800202 case D2D_SUBCOMMAND:
203 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000204 case SINGLE_REGISTATION_CONFIG:
205 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000206 case RESTART_MODEM:
207 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000208 case UNATTENDED_REBOOT:
209 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700210 default: {
211 return handleDefaultCommands(cmd);
212 }
213 }
214 }
215
216 @Override
217 public void onHelp() {
218 PrintWriter pw = getOutPrintWriter();
219 pw.println("Telephony Commands:");
220 pw.println(" help");
221 pw.println(" Print this help text.");
222 pw.println(" ims");
223 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800224 pw.println(" uce");
225 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800226 pw.println(" emergency-number-test-mode");
227 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700228 pw.println(" end-block-suppression");
229 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800230 pw.println(" data");
231 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100232 pw.println(" cc");
233 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700234 pw.println(" gba");
235 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000236 pw.println(" src");
237 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000238 pw.println(" restart-modem");
239 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000240 pw.println(" unattended-reboot");
241 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700242 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800243 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800244 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700245 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800246 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100247 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700248 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000249 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800250 onHelpD2D();
251 }
252
253 private void onHelpD2D() {
254 PrintWriter pw = getOutPrintWriter();
255 pw.println("D2D Comms Commands:");
256 pw.println(" d2d send TYPE VALUE");
257 pw.println(" Sends a D2D message of specified type and value.");
258 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
259 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
260 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
261 MESSAGE_CALL_AUDIO_CODEC));
262 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
263 + Communicator.messageToString(
264 MESSAGE_DEVICE_BATTERY_STATE));
265 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
266 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700267 }
268
269 private void onHelpIms() {
270 PrintWriter pw = getOutPrintWriter();
271 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800272 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700273 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
274 pw.println(" ImsService. Options are:");
275 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
276 pw.println(" is specified, it will choose the default voice SIM slot.");
277 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
278 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800279 pw.println(" -f: Set the feature that this override if for, if no option is");
280 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700281 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
282 pw.println(" Gets the package name of the currently defined ImsService.");
283 pw.println(" Options are:");
284 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
285 pw.println(" is specified, it will choose the default voice SIM slot.");
286 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000287 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800288 pw.println(" -f: The feature type that the query will be requested for. If none is");
289 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800290 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
291 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
292 pw.println(" configuration overrides. Options are:");
293 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
294 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700295 pw.println(" ims enable [-s SLOT_ID]");
296 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
297 pw.println(" if none is specified.");
298 pw.println(" ims disable [-s SLOT_ID]");
299 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
300 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700301 pw.println(" ims conference-event-package [enable/disable]");
302 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700303 }
304
James.cf Linbcdf8b32021-01-14 16:44:13 +0800305 private void onHelpUce() {
306 PrintWriter pw = getOutPrintWriter();
307 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800308 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
309 pw.println(" Get the EAB contacts from the EAB database.");
310 pw.println(" Options are:");
311 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
312 pw.println(" Expected output format :");
313 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800314 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
315 pw.println(" Remove the EAB contacts from the EAB database.");
316 pw.println(" Options are:");
317 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
318 pw.println(" is specified, it will choose the default voice SIM slot.");
319 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800320 pw.println(" uce get-device-enabled");
321 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
322 pw.println(" uce set-device-enabled true|false");
323 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
324 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800325 }
326
Hall Liud892bec2018-11-30 14:51:45 -0800327 private void onHelpNumberVerification() {
328 PrintWriter pw = getOutPrintWriter();
329 pw.println("Number verification commands");
330 pw.println(" numverify override-package PACKAGE_NAME;");
331 pw.println(" Set the authorized package for number verification.");
332 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800333 pw.println(" numverify fake-call NUMBER;");
334 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
335 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800336 }
337
Shuo Qianf5125122019-12-16 17:03:07 -0800338 private void onHelpDataTestMode() {
339 PrintWriter pw = getOutPrintWriter();
340 pw.println("Mobile Data Test Mode Commands:");
341 pw.println(" data enable: enable mobile data connectivity");
342 pw.println(" data disable: disable mobile data connectivity");
343 }
344
sqian9d4df8b2019-01-15 18:32:07 -0800345 private void onHelpEmergencyNumber() {
346 PrintWriter pw = getOutPrintWriter();
347 pw.println("Emergency Number Test Mode Commands:");
348 pw.println(" emergency-number-test-mode ");
349 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
350 + " the test mode");
351 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700352 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800353 pw.println(" -c: clear the emergency number list in the test mode.");
354 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700355 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800356 pw.println(" -p: get the full emergency number list in the test mode.");
357 }
358
Shuo Qian489d9282020-07-09 11:30:03 -0700359 private void onHelpEndBlockSupperssion() {
360 PrintWriter pw = getOutPrintWriter();
361 pw.println("End Block Suppression command:");
362 pw.println(" end-block-suppression: disable suppressing blocking by contact");
363 pw.println(" with emergency services.");
364 }
365
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100366 private void onHelpCc() {
367 PrintWriter pw = getOutPrintWriter();
368 pw.println("Carrier Config Commands:");
369 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
370 pw.println(" Print carrier config values.");
371 pw.println(" Options are:");
372 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
373 pw.println(" is specified, it will choose the default voice SIM slot.");
374 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
375 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100376 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100377 pw.println(" Set carrier config KEY to NEW_VALUE.");
378 pw.println(" Options are:");
379 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
380 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100381 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100382 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
383 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
384 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
385 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
386 pw.println(" cc clear-values [-s SLOT_ID]");
387 pw.println(" Clear all carrier override values that has previously been set");
388 pw.println(" with set-value");
389 pw.println(" Options are:");
390 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
391 pw.println(" is specified, it will choose the default voice SIM slot.");
392 }
393
Hui Wang0866fcc2020-10-12 12:14:23 -0700394 private void onHelpGba() {
395 PrintWriter pw = getOutPrintWriter();
396 pw.println("Gba Commands:");
397 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
398 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
399 pw.println(" Options are:");
400 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
401 pw.println(" is specified, it will choose the default voice SIM slot.");
402 pw.println(" gba get-service [-s SLOT_ID]");
403 pw.println(" Gets the package name of the currently defined GbaService.");
404 pw.println(" Options are:");
405 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
406 pw.println(" is specified, it will choose the default voice SIM slot.");
407 pw.println(" gba set-release [-s SLOT_ID] n");
408 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
409 pw.println(" Do not release/unbind if n is -1.");
410 pw.println(" Options are:");
411 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
412 pw.println(" is specified, it will choose the default voice SIM slot.");
413 pw.println(" gba get-release [-s SLOT_ID]");
414 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
415 pw.println(" Options are:");
416 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
417 pw.println(" is specified, it will choose the default voice SIM slot.");
418 }
419
Hui Wang068ab862020-10-31 05:12:53 +0000420 private void onHelpSrc() {
421 PrintWriter pw = getOutPrintWriter();
422 pw.println("RCS VoLTE Single Registration Config Commands:");
423 pw.println(" src set-device-enabled true|false|null");
424 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
425 pw.println(" The value could be true, false, or null(undefined).");
426 pw.println(" src get-device-enabled");
427 pw.println(" Gets the device config for RCS VoLTE single registration.");
428 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
429 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
430 pw.println(" The value could be true, false, or null(undefined).");
431 pw.println(" Options are:");
432 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
433 pw.println(" is specified, it will choose the default voice SIM slot.");
434 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
435 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
436 pw.println(" Options are:");
437 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
438 pw.println(" is specified, it will choose the default voice SIM slot.");
439 }
440
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700441 private int handleImsCommand() {
442 String arg = getNextArg();
443 if (arg == null) {
444 onHelpIms();
445 return 0;
446 }
447
448 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800449 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700450 return handleImsSetServiceCommand();
451 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800452 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700453 return handleImsGetServiceCommand();
454 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800455 case IMS_CLEAR_SERVICE_OVERRIDE: {
456 return handleImsClearCarrierServiceCommand();
457 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700458 case IMS_ENABLE: {
459 return handleEnableIms();
460 }
461 case IMS_DISABLE: {
462 return handleDisableIms();
463 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700464 case IMS_CEP: {
465 return handleCepChange();
466 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700467 }
468
469 return -1;
470 }
471
Shuo Qianf5125122019-12-16 17:03:07 -0800472 private int handleDataTestModeCommand() {
473 PrintWriter errPw = getErrPrintWriter();
474 String arg = getNextArgRequired();
475 if (arg == null) {
476 onHelpDataTestMode();
477 return 0;
478 }
479 switch (arg) {
480 case DATA_ENABLE: {
481 try {
482 mInterface.enableDataConnectivity();
483 } catch (RemoteException ex) {
484 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
485 errPw.println("Exception: " + ex.getMessage());
486 return -1;
487 }
488 break;
489 }
490 case DATA_DISABLE: {
491 try {
492 mInterface.disableDataConnectivity();
493 } catch (RemoteException ex) {
494 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
495 errPw.println("Exception: " + ex.getMessage());
496 return -1;
497 }
498 break;
499 }
500 default:
501 onHelpDataTestMode();
502 break;
503 }
504 return 0;
505 }
506
Shuo Qian479dd9e2021-02-22 18:32:21 -0800507 private int handleEmergencyCallbackModeCommand() {
508 PrintWriter errPw = getErrPrintWriter();
509 try {
510 mInterface.startEmergencyCallbackMode();
511 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
512 } catch (RemoteException ex) {
513 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
514 errPw.println("Exception: " + ex.getMessage());
515 return -1;
516 }
517 return 0;
518 }
519
sqian9d4df8b2019-01-15 18:32:07 -0800520 private int handleEmergencyNumberTestModeCommand() {
521 PrintWriter errPw = getErrPrintWriter();
522 String opt = getNextOption();
523 if (opt == null) {
524 onHelpEmergencyNumber();
525 return 0;
526 }
527
528 switch (opt) {
529 case "-a": {
530 String emergencyNumberCmd = getNextArgRequired();
531 if (emergencyNumberCmd == null
532 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700533 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800534 + " to be specified after -a in the command ");
535 return -1;
536 }
537 try {
538 mInterface.updateEmergencyNumberListTestMode(
539 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
540 new EmergencyNumber(emergencyNumberCmd, "", "",
541 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
542 new ArrayList<String>(),
543 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
544 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
545 } catch (RemoteException ex) {
546 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
547 + ", error " + ex.getMessage());
548 errPw.println("Exception: " + ex.getMessage());
549 return -1;
550 }
551 break;
552 }
553 case "-c": {
554 try {
555 mInterface.updateEmergencyNumberListTestMode(
556 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
557 } catch (RemoteException ex) {
558 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
559 errPw.println("Exception: " + ex.getMessage());
560 return -1;
561 }
562 break;
563 }
564 case "-r": {
565 String emergencyNumberCmd = getNextArgRequired();
566 if (emergencyNumberCmd == null
567 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700568 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800569 + " to be specified after -r in the command ");
570 return -1;
571 }
572 try {
573 mInterface.updateEmergencyNumberListTestMode(
574 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
575 new EmergencyNumber(emergencyNumberCmd, "", "",
576 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
577 new ArrayList<String>(),
578 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
579 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
580 } catch (RemoteException ex) {
581 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
582 + ", error " + ex.getMessage());
583 errPw.println("Exception: " + ex.getMessage());
584 return -1;
585 }
586 break;
587 }
588 case "-p": {
589 try {
590 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
591 } catch (RemoteException ex) {
592 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
593 errPw.println("Exception: " + ex.getMessage());
594 return -1;
595 }
596 break;
597 }
598 default:
599 onHelpEmergencyNumber();
600 break;
601 }
602 return 0;
603 }
604
Hall Liud892bec2018-11-30 14:51:45 -0800605 private int handleNumberVerificationCommand() {
606 String arg = getNextArg();
607 if (arg == null) {
608 onHelpNumberVerification();
609 return 0;
610 }
611
Hall Liuca5af3a2018-12-04 16:58:23 -0800612 if (!checkShellUid()) {
613 return -1;
614 }
615
Hall Liud892bec2018-11-30 14:51:45 -0800616 switch (arg) {
617 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800618 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
619 return 0;
620 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800621 case NUMBER_VERIFICATION_FAKE_CALL: {
622 boolean val = NumberVerificationManager.getInstance()
623 .checkIncomingCall(getNextArg());
624 getOutPrintWriter().println(val ? "1" : "0");
625 return 0;
626 }
Hall Liud892bec2018-11-30 14:51:45 -0800627 }
628
629 return -1;
630 }
631
Tyler Gunn92479152021-01-20 16:30:10 -0800632 private int handleD2dCommand() {
633 String arg = getNextArg();
634 if (arg == null) {
635 onHelpD2D();
636 return 0;
637 }
638
639 switch (arg) {
640 case D2D_SEND: {
641 return handleD2dSendCommand();
642 }
643 }
644
645 return -1;
646 }
647
648 private int handleD2dSendCommand() {
649 PrintWriter errPw = getErrPrintWriter();
650 String opt;
651 int messageType = -1;
652 int messageValue = -1;
653
654
655 String arg = getNextArg();
656 if (arg == null) {
657 onHelpD2D();
658 return 0;
659 }
660 try {
661 messageType = Integer.parseInt(arg);
662 } catch (NumberFormatException e) {
663 errPw.println("message type must be a valid integer");
664 return -1;
665 }
666
667 arg = getNextArg();
668 if (arg == null) {
669 onHelpD2D();
670 return 0;
671 }
672 try {
673 messageValue = Integer.parseInt(arg);
674 } catch (NumberFormatException e) {
675 errPw.println("message value must be a valid integer");
676 return -1;
677 }
678
679 try {
680 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
681 } catch (RemoteException e) {
682 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
683 errPw.println("Exception: " + e.getMessage());
684 return -1;
685 }
686
687 return 0;
688 }
689
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700690 // ims set-ims-service
691 private int handleImsSetServiceCommand() {
692 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700693 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700694 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800695 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700696
697 String opt;
698 while ((opt = getNextOption()) != null) {
699 switch (opt) {
700 case "-s": {
701 try {
702 slotId = Integer.parseInt(getNextArgRequired());
703 } catch (NumberFormatException e) {
704 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
705 return -1;
706 }
707 break;
708 }
709 case "-c": {
710 isCarrierService = true;
711 break;
712 }
713 case "-d": {
714 isCarrierService = false;
715 break;
716 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800717 case "-f": {
718 String featureString = getNextArgRequired();
719 String[] features = featureString.split(",");
720 for (int i = 0; i < features.length; i++) {
721 try {
722 Integer result = Integer.parseInt(features[i]);
723 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
724 || result >= ImsFeature.FEATURE_MAX) {
725 errPw.println("ims set-ims-service -f " + result
726 + " is an invalid feature.");
727 return -1;
728 }
729 featuresList.add(result);
730 } catch (NumberFormatException e) {
731 errPw.println("ims set-ims-service -f tried to parse " + features[i]
732 + " as an integer.");
733 return -1;
734 }
735 }
736 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700737 }
738 }
739 // Mandatory param, either -c or -d
740 if (isCarrierService == null) {
741 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
742 return -1;
743 }
744
745 String packageName = getNextArg();
746
747 try {
748 if (packageName == null) {
749 packageName = "";
750 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800751 int[] featureArray = new int[featuresList.size()];
752 for (int i = 0; i < featuresList.size(); i++) {
753 featureArray[i] = featuresList.get(i);
754 }
755 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
756 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700757 if (VDBG) {
758 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800759 + (isCarrierService ? "-c " : "-d ")
760 + "-f " + featuresList + " "
761 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700762 }
763 getOutPrintWriter().println(result);
764 } catch (RemoteException e) {
765 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800766 + (isCarrierService ? "-c " : "-d ")
767 + "-f " + featuresList + " "
768 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700769 errPw.println("Exception: " + e.getMessage());
770 return -1;
771 }
772 return 0;
773 }
774
Brad Ebinger999d3302020-11-25 14:31:39 -0800775 // ims clear-ims-service-override
776 private int handleImsClearCarrierServiceCommand() {
777 PrintWriter errPw = getErrPrintWriter();
778 int slotId = getDefaultSlot();
779
780 String opt;
781 while ((opt = getNextOption()) != null) {
782 switch (opt) {
783 case "-s": {
784 try {
785 slotId = Integer.parseInt(getNextArgRequired());
786 } catch (NumberFormatException e) {
787 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
788 return -1;
789 }
790 break;
791 }
792 }
793 }
794
795 try {
796 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
797 if (VDBG) {
798 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
799 + ", result=" + result);
800 }
801 getOutPrintWriter().println(result);
802 } catch (RemoteException e) {
803 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
804 + ", error" + e.getMessage());
805 errPw.println("Exception: " + e.getMessage());
806 return -1;
807 }
808 return 0;
809 }
810
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700811 // ims get-ims-service
812 private int handleImsGetServiceCommand() {
813 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700814 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700815 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800816 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700817
818 String opt;
819 while ((opt = getNextOption()) != null) {
820 switch (opt) {
821 case "-s": {
822 try {
823 slotId = Integer.parseInt(getNextArgRequired());
824 } catch (NumberFormatException e) {
825 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
826 return -1;
827 }
828 break;
829 }
830 case "-c": {
831 isCarrierService = true;
832 break;
833 }
834 case "-d": {
835 isCarrierService = false;
836 break;
837 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800838 case "-f": {
839 try {
840 featureType = Integer.parseInt(getNextArg());
841 } catch (NumberFormatException e) {
842 errPw.println("ims get-ims-service -f requires valid integer as feature.");
843 return -1;
844 }
845 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
846 || featureType >= ImsFeature.FEATURE_MAX) {
847 errPw.println("ims get-ims-service -f invalid feature.");
848 return -1;
849 }
850 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700851 }
852 }
853 // Mandatory param, either -c or -d
854 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800855 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700856 return -1;
857 }
858
859 String result;
860 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800861 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700862 } catch (RemoteException e) {
863 return -1;
864 }
865 if (VDBG) {
866 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800867 + (isCarrierService ? "-c " : "-d ")
868 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
869 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700870 }
871 getOutPrintWriter().println(result);
872 return 0;
873 }
874
875 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700876 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700877 String opt;
878 while ((opt = getNextOption()) != null) {
879 switch (opt) {
880 case "-s": {
881 try {
882 slotId = Integer.parseInt(getNextArgRequired());
883 } catch (NumberFormatException e) {
884 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
885 return -1;
886 }
887 break;
888 }
889 }
890 }
891 try {
892 mInterface.enableIms(slotId);
893 } catch (RemoteException e) {
894 return -1;
895 }
896 if (VDBG) {
897 Log.v(LOG_TAG, "ims enable -s " + slotId);
898 }
899 return 0;
900 }
901
902 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700903 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700904 String opt;
905 while ((opt = getNextOption()) != null) {
906 switch (opt) {
907 case "-s": {
908 try {
909 slotId = Integer.parseInt(getNextArgRequired());
910 } catch (NumberFormatException e) {
911 getErrPrintWriter().println(
912 "ims disable requires an integer as a SLOT_ID.");
913 return -1;
914 }
915 break;
916 }
917 }
918 }
919 try {
920 mInterface.disableIms(slotId);
921 } catch (RemoteException e) {
922 return -1;
923 }
924 if (VDBG) {
925 Log.v(LOG_TAG, "ims disable -s " + slotId);
926 }
927 return 0;
928 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700929
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700930 private int handleCepChange() {
931 Log.i(LOG_TAG, "handleCepChange");
932 String opt = getNextArg();
933 if (opt == null) {
934 return -1;
935 }
936 boolean isCepEnabled = opt.equals("enable");
937
938 try {
939 mInterface.setCepEnabled(isCepEnabled);
940 } catch (RemoteException e) {
941 return -1;
942 }
943 return 0;
944 }
945
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700946 private int getDefaultSlot() {
947 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
948 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
949 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
950 // If there is no default, default to slot 0.
951 slotId = DEFAULT_PHONE_ID;
952 }
953 return slotId;
954 }
sqian2fff4a32018-11-05 14:18:37 -0800955
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100956 // Parse options related to Carrier Config Commands.
957 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100958 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100959 CcOptionParseResult result = new CcOptionParseResult();
960 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
961 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100962
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100963 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100964 while ((opt = getNextOption()) != null) {
965 switch (opt) {
966 case "-s": {
967 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100968 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
969 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
970 errPw.println(tag + "No valid subscription found.");
971 return null;
972 }
973
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100974 } catch (IllegalArgumentException e) {
975 // Missing slot id
976 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100977 return null;
978 }
979 break;
980 }
981 case "-p": {
982 if (allowOptionPersistent) {
983 result.mPersistent = true;
984 } else {
985 errPw.println(tag + "Unexpected option " + opt);
986 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100987 }
988 break;
989 }
990 default: {
991 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100992 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100993 }
994 }
995 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100996 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100997 }
998
999 private int slotStringToSubId(String tag, String slotString) {
1000 int slotId = -1;
1001 try {
1002 slotId = Integer.parseInt(slotString);
1003 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001004 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1005 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1006 }
1007
1008 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001009 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1010 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1011 }
1012
Qiong Liuf25799b2020-09-10 10:13:46 +08001013 Phone phone = PhoneFactory.getPhone(slotId);
1014 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001015 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1016 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1017 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001018 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001019 }
1020
Hall Liud892bec2018-11-30 14:51:45 -08001021 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001022 // adb can run as root or as shell, depending on whether the device is rooted.
1023 return Binder.getCallingUid() == Process.SHELL_UID
1024 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001025 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001026
1027 private int handleCcCommand() {
1028 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1029 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001030 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001031 getErrPrintWriter().println("cc: Permission denied.");
1032 return -1;
1033 }
1034
1035 String arg = getNextArg();
1036 if (arg == null) {
1037 onHelpCc();
1038 return 0;
1039 }
1040
1041 switch (arg) {
1042 case CC_GET_VALUE: {
1043 return handleCcGetValue();
1044 }
1045 case CC_SET_VALUE: {
1046 return handleCcSetValue();
1047 }
1048 case CC_CLEAR_VALUES: {
1049 return handleCcClearValues();
1050 }
1051 default: {
1052 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1053 }
1054 }
1055 return -1;
1056 }
1057
1058 // cc get-value
1059 private int handleCcGetValue() {
1060 PrintWriter errPw = getErrPrintWriter();
1061 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1062 String key = null;
1063
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001064 // Parse all options
1065 CcOptionParseResult options = parseCcOptions(tag, false);
1066 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001067 return -1;
1068 }
1069
1070 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001071 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001072 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001073 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001074 return -1;
1075 }
1076
1077 // Get the key.
1078 key = getNextArg();
1079 if (key != null) {
1080 // A key was provided. Verify if it is a valid key
1081 if (!bundle.containsKey(key)) {
1082 errPw.println(tag + key + " is not a valid key.");
1083 return -1;
1084 }
1085
1086 // Print the carrier config value for key.
1087 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1088 } else {
1089 // No key provided. Show all values.
1090 // Iterate over a sorted list of all carrier config keys and print them.
1091 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1092 for (String k : sortedSet) {
1093 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1094 }
1095 }
1096 return 0;
1097 }
1098
1099 // cc set-value
1100 private int handleCcSetValue() {
1101 PrintWriter errPw = getErrPrintWriter();
1102 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1103
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001104 // Parse all options
1105 CcOptionParseResult options = parseCcOptions(tag, true);
1106 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001107 return -1;
1108 }
1109
1110 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001111 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001112 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001113 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001114 return -1;
1115 }
1116
1117 // Get the key.
1118 String key = getNextArg();
1119 if (key == null || key.equals("")) {
1120 errPw.println(tag + "KEY is missing");
1121 return -1;
1122 }
1123
1124 // Verify if the key is valid
1125 if (!originalValues.containsKey(key)) {
1126 errPw.println(tag + key + " is not a valid key.");
1127 return -1;
1128 }
1129
1130 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1131 ArrayList<String> valueList = new ArrayList<String>();
1132 while (peekNextArg() != null) {
1133 valueList.add(getNextArg());
1134 }
1135
1136 // Find the type of the carrier config value
1137 CcType type = getType(tag, key, originalValues);
1138 if (type == CcType.UNKNOWN) {
1139 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1140 return -1;
1141 }
1142
1143 // Create an override bundle containing the key and value that should be overriden.
1144 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1145 if (overrideBundle == null) {
1146 return -1;
1147 }
1148
1149 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001150 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001151
1152 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001153 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001154 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001155 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001156 return -1;
1157 }
1158
1159 // Print the original and new value.
1160 String originalValueString = ccValueToString(key, type, originalValues);
1161 String newValueString = ccValueToString(key, type, newValues);
1162 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1163 getOutPrintWriter().println("New value: \n" + newValueString);
1164
1165 return 0;
1166 }
1167
1168 // cc clear-values
1169 private int handleCcClearValues() {
1170 PrintWriter errPw = getErrPrintWriter();
1171 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1172
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001173 // Parse all options
1174 CcOptionParseResult options = parseCcOptions(tag, false);
1175 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001176 return -1;
1177 }
1178
1179 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001180 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001181 getOutPrintWriter()
1182 .println("All previously set carrier config override values has been cleared");
1183 return 0;
1184 }
1185
1186 private CcType getType(String tag, String key, PersistableBundle bundle) {
1187 // Find the type by checking the type of the current value stored in the bundle.
1188 Object value = bundle.get(key);
1189
1190 if (CC_TYPE_MAP.containsKey(key)) {
1191 return CC_TYPE_MAP.get(key);
1192 } else if (value != null) {
1193 if (value instanceof Boolean) {
1194 return CcType.BOOLEAN;
1195 } else if (value instanceof Double) {
1196 return CcType.DOUBLE;
1197 } else if (value instanceof double[]) {
1198 return CcType.DOUBLE_ARRAY;
1199 } else if (value instanceof Integer) {
1200 return CcType.INT;
1201 } else if (value instanceof int[]) {
1202 return CcType.INT_ARRAY;
1203 } else if (value instanceof Long) {
1204 return CcType.LONG;
1205 } else if (value instanceof long[]) {
1206 return CcType.LONG_ARRAY;
1207 } else if (value instanceof String) {
1208 return CcType.STRING;
1209 } else if (value instanceof String[]) {
1210 return CcType.STRING_ARRAY;
1211 }
1212 } else {
1213 // Current value was null and can therefore not be used in order to find the type.
1214 // Check the name of the key to infer the type. This check is not needed for primitive
1215 // data types (boolean, double, int and long), since they can not be null.
1216 if (key.endsWith("double_array")) {
1217 return CcType.DOUBLE_ARRAY;
1218 }
1219 if (key.endsWith("int_array")) {
1220 return CcType.INT_ARRAY;
1221 }
1222 if (key.endsWith("long_array")) {
1223 return CcType.LONG_ARRAY;
1224 }
1225 if (key.endsWith("string")) {
1226 return CcType.STRING;
1227 }
1228 if (key.endsWith("string_array") || key.endsWith("strings")) {
1229 return CcType.STRING_ARRAY;
1230 }
1231 }
1232
1233 // Not possible to infer the type by looking at the current value or the key.
1234 PrintWriter errPw = getErrPrintWriter();
1235 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1236 return CcType.UNKNOWN;
1237 }
1238
1239 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1240 String result;
1241 StringBuilder valueString = new StringBuilder();
1242 String typeString = type.toString();
1243 Object value = bundle.get(key);
1244
1245 if (value == null) {
1246 valueString.append("null");
1247 } else {
1248 switch (type) {
1249 case DOUBLE_ARRAY: {
1250 // Format the string representation of the int array as value1 value2......
1251 double[] valueArray = (double[]) value;
1252 for (int i = 0; i < valueArray.length; i++) {
1253 if (i != 0) {
1254 valueString.append(" ");
1255 }
1256 valueString.append(valueArray[i]);
1257 }
1258 break;
1259 }
1260 case INT_ARRAY: {
1261 // Format the string representation of the int array as value1 value2......
1262 int[] valueArray = (int[]) value;
1263 for (int i = 0; i < valueArray.length; i++) {
1264 if (i != 0) {
1265 valueString.append(" ");
1266 }
1267 valueString.append(valueArray[i]);
1268 }
1269 break;
1270 }
1271 case LONG_ARRAY: {
1272 // Format the string representation of the int array as value1 value2......
1273 long[] valueArray = (long[]) value;
1274 for (int i = 0; i < valueArray.length; i++) {
1275 if (i != 0) {
1276 valueString.append(" ");
1277 }
1278 valueString.append(valueArray[i]);
1279 }
1280 break;
1281 }
1282 case STRING: {
1283 valueString.append("\"" + value.toString() + "\"");
1284 break;
1285 }
1286 case STRING_ARRAY: {
1287 // Format the string representation of the string array as "value1" "value2"....
1288 String[] valueArray = (String[]) value;
1289 for (int i = 0; i < valueArray.length; i++) {
1290 if (i != 0) {
1291 valueString.append(" ");
1292 }
1293 if (valueArray[i] != null) {
1294 valueString.append("\"" + valueArray[i] + "\"");
1295 } else {
1296 valueString.append("null");
1297 }
1298 }
1299 break;
1300 }
1301 default: {
1302 valueString.append(value.toString());
1303 }
1304 }
1305 }
1306 return String.format("%-70s %-15s %s", key, typeString, valueString);
1307 }
1308
1309 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1310 ArrayList<String> valueList) {
1311 PrintWriter errPw = getErrPrintWriter();
1312 PersistableBundle bundle = new PersistableBundle();
1313
1314 // First verify that a valid number of values has been provided for the type.
1315 switch (type) {
1316 case BOOLEAN:
1317 case DOUBLE:
1318 case INT:
1319 case LONG: {
1320 if (valueList.size() != 1) {
1321 errPw.println(tag + "Expected 1 value for type " + type
1322 + ". Found: " + valueList.size());
1323 return null;
1324 }
1325 break;
1326 }
1327 case STRING: {
1328 if (valueList.size() > 1) {
1329 errPw.println(tag + "Expected 0 or 1 values for type " + type
1330 + ". Found: " + valueList.size());
1331 return null;
1332 }
1333 break;
1334 }
1335 }
1336
1337 // Parse the value according to type and add it to the Bundle.
1338 switch (type) {
1339 case BOOLEAN: {
1340 if ("true".equalsIgnoreCase(valueList.get(0))) {
1341 bundle.putBoolean(key, true);
1342 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1343 bundle.putBoolean(key, false);
1344 } else {
1345 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1346 return null;
1347 }
1348 break;
1349 }
1350 case DOUBLE: {
1351 try {
1352 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1353 } catch (NumberFormatException nfe) {
1354 // Not a valid double
1355 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1356 return null;
1357 }
1358 break;
1359 }
1360 case DOUBLE_ARRAY: {
1361 double[] valueDoubleArray = null;
1362 if (valueList.size() > 0) {
1363 valueDoubleArray = new double[valueList.size()];
1364 for (int i = 0; i < valueList.size(); i++) {
1365 try {
1366 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1367 } catch (NumberFormatException nfe) {
1368 // Not a valid double
1369 errPw.println(
1370 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1371 return null;
1372 }
1373 }
1374 }
1375 bundle.putDoubleArray(key, valueDoubleArray);
1376 break;
1377 }
1378 case INT: {
1379 try {
1380 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1381 } catch (NumberFormatException nfe) {
1382 // Not a valid integer
1383 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1384 return null;
1385 }
1386 break;
1387 }
1388 case INT_ARRAY: {
1389 int[] valueIntArray = null;
1390 if (valueList.size() > 0) {
1391 valueIntArray = new int[valueList.size()];
1392 for (int i = 0; i < valueList.size(); i++) {
1393 try {
1394 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1395 } catch (NumberFormatException nfe) {
1396 // Not a valid integer
1397 errPw.println(tag
1398 + "Unable to parse " + valueList.get(i) + " as an integer.");
1399 return null;
1400 }
1401 }
1402 }
1403 bundle.putIntArray(key, valueIntArray);
1404 break;
1405 }
1406 case LONG: {
1407 try {
1408 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1409 } catch (NumberFormatException nfe) {
1410 // Not a valid long
1411 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1412 return null;
1413 }
1414 break;
1415 }
1416 case LONG_ARRAY: {
1417 long[] valueLongArray = null;
1418 if (valueList.size() > 0) {
1419 valueLongArray = new long[valueList.size()];
1420 for (int i = 0; i < valueList.size(); i++) {
1421 try {
1422 valueLongArray[i] = Long.parseLong(valueList.get(i));
1423 } catch (NumberFormatException nfe) {
1424 // Not a valid long
1425 errPw.println(
1426 tag + "Unable to parse " + valueList.get(i) + " as a long");
1427 return null;
1428 }
1429 }
1430 }
1431 bundle.putLongArray(key, valueLongArray);
1432 break;
1433 }
1434 case STRING: {
1435 String value = null;
1436 if (valueList.size() > 0) {
1437 value = valueList.get(0);
1438 }
1439 bundle.putString(key, value);
1440 break;
1441 }
1442 case STRING_ARRAY: {
1443 String[] valueStringArray = null;
1444 if (valueList.size() > 0) {
1445 valueStringArray = new String[valueList.size()];
1446 valueList.toArray(valueStringArray);
1447 }
1448 bundle.putStringArray(key, valueStringArray);
1449 break;
1450 }
1451 }
1452 return bundle;
1453 }
Shuo Qian489d9282020-07-09 11:30:03 -07001454
1455 private int handleEndBlockSuppressionCommand() {
1456 if (!checkShellUid()) {
1457 return -1;
1458 }
1459
1460 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1461 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1462 }
1463 return 0;
1464 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001465
Michele Berionne38c1afa2020-12-28 20:23:16 +00001466 private int handleRestartModemCommand() {
1467 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1468 // non user build.
1469 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1470 getErrPrintWriter().println("RestartModem: Permission denied.");
1471 return -1;
1472 }
1473
1474 boolean result = TelephonyManager.getDefault().rebootRadio();
1475 getOutPrintWriter().println(result);
1476
1477 return result ? 0 : -1;
1478 }
1479
Michele Berionned9fbae52020-11-13 02:36:59 +00001480 private int handleUnattendedReboot() {
1481 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1482 // non user build.
1483 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1484 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1485 return -1;
1486 }
1487
1488 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1489 getOutPrintWriter().println("result: " + result);
1490
1491 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1492 }
1493
Hui Wang0866fcc2020-10-12 12:14:23 -07001494 private int handleGbaCommand() {
1495 String arg = getNextArg();
1496 if (arg == null) {
1497 onHelpGba();
1498 return 0;
1499 }
1500
1501 switch (arg) {
1502 case GBA_SET_SERVICE: {
1503 return handleGbaSetServiceCommand();
1504 }
1505 case GBA_GET_SERVICE: {
1506 return handleGbaGetServiceCommand();
1507 }
1508 case GBA_SET_RELEASE_TIME: {
1509 return handleGbaSetReleaseCommand();
1510 }
1511 case GBA_GET_RELEASE_TIME: {
1512 return handleGbaGetReleaseCommand();
1513 }
1514 }
1515
1516 return -1;
1517 }
1518
1519 private int getSubId(String cmd) {
1520 int slotId = getDefaultSlot();
1521 String opt = getNextOption();
1522 if (opt != null && opt.equals("-s")) {
1523 try {
1524 slotId = Integer.parseInt(getNextArgRequired());
1525 } catch (NumberFormatException e) {
1526 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1527 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1528 }
1529 }
1530 int[] subIds = SubscriptionManager.getSubId(slotId);
1531 return subIds[0];
1532 }
1533
1534 private int handleGbaSetServiceCommand() {
1535 int subId = getSubId("gba set-service");
1536 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1537 return -1;
1538 }
1539
1540 String packageName = getNextArg();
1541 try {
1542 if (packageName == null) {
1543 packageName = "";
1544 }
1545 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1546 if (VDBG) {
1547 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1548 + packageName + ", result=" + result);
1549 }
1550 getOutPrintWriter().println(result);
1551 } catch (RemoteException e) {
1552 Log.w(LOG_TAG, "gba set-service " + subId + " "
1553 + packageName + ", error" + e.getMessage());
1554 getErrPrintWriter().println("Exception: " + e.getMessage());
1555 return -1;
1556 }
1557 return 0;
1558 }
1559
1560 private int handleGbaGetServiceCommand() {
1561 String result;
1562
1563 int subId = getSubId("gba get-service");
1564 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1565 return -1;
1566 }
1567
1568 try {
1569 result = mInterface.getBoundGbaService(subId);
1570 } catch (RemoteException e) {
1571 return -1;
1572 }
1573 if (VDBG) {
1574 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1575 }
1576 getOutPrintWriter().println(result);
1577 return 0;
1578 }
1579
1580 private int handleGbaSetReleaseCommand() {
1581 //the release time value could be -1
1582 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1583 : SubscriptionManager.getDefaultSubscriptionId();
1584 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1585 return -1;
1586 }
1587
1588 String intervalStr = getNextArg();
1589 if (intervalStr == null) {
1590 return -1;
1591 }
1592
1593 try {
1594 int interval = Integer.parseInt(intervalStr);
1595 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1596 if (VDBG) {
1597 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1598 + intervalStr + ", result=" + result);
1599 }
1600 getOutPrintWriter().println(result);
1601 } catch (NumberFormatException | RemoteException e) {
1602 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1603 + intervalStr + ", error" + e.getMessage());
1604 getErrPrintWriter().println("Exception: " + e.getMessage());
1605 return -1;
1606 }
1607 return 0;
1608 }
1609
1610 private int handleGbaGetReleaseCommand() {
1611 int subId = getSubId("gba get-release");
1612 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1613 return -1;
1614 }
1615
1616 int result = 0;
1617 try {
1618 result = mInterface.getGbaReleaseTime(subId);
1619 } catch (RemoteException e) {
1620 return -1;
1621 }
1622 if (VDBG) {
1623 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1624 }
1625 getOutPrintWriter().println(result);
1626 return 0;
1627 }
Hui Wang068ab862020-10-31 05:12:53 +00001628
1629 private int handleSingleRegistrationConfigCommand() {
1630 String arg = getNextArg();
1631 if (arg == null) {
1632 onHelpSrc();
1633 return 0;
1634 }
1635
1636 switch (arg) {
1637 case SRC_SET_DEVICE_ENABLED: {
1638 return handleSrcSetDeviceEnabledCommand();
1639 }
1640 case SRC_GET_DEVICE_ENABLED: {
1641 return handleSrcGetDeviceEnabledCommand();
1642 }
1643 case SRC_SET_CARRIER_ENABLED: {
1644 return handleSrcSetCarrierEnabledCommand();
1645 }
1646 case SRC_GET_CARRIER_ENABLED: {
1647 return handleSrcGetCarrierEnabledCommand();
1648 }
1649 }
1650
1651 return -1;
1652 }
1653
James.cf Linbcdf8b32021-01-14 16:44:13 +08001654 private int handleRcsUceCommand() {
1655 String arg = getNextArg();
1656 if (arg == null) {
1657 Log.w(LOG_TAG, "cannot get uce parameter");
1658 return -1;
1659 }
1660
1661 switch (arg) {
1662 case UCE_REMOVE_EAB_CONTACT:
1663 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001664 case UCE_GET_EAB_CONTACT:
1665 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001666 case UCE_GET_DEVICE_ENABLED:
1667 return handleUceGetDeviceEnabledCommand();
1668 case UCE_SET_DEVICE_ENABLED:
1669 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001670 }
1671 return -1;
1672 }
1673
1674 private int handleRemovingEabContactCommand() {
1675 int subId = getSubId("uce remove-eab-contact");
1676 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1677 return -1;
1678 }
1679
1680 String phoneNumber = getNextArgRequired();
1681 if (TextUtils.isEmpty(phoneNumber)) {
1682 return -1;
1683 }
1684 int result = 0;
1685 try {
1686 result = mInterface.removeContactFromEab(subId, phoneNumber);
1687 } catch (RemoteException e) {
1688 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1689 getErrPrintWriter().println("Exception: " + e.getMessage());
1690 return -1;
1691 }
1692
1693 if (VDBG) {
1694 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1695 }
calvinpan293ea1b2021-02-04 17:52:13 +08001696 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001697 }
1698
calvinpane4a8a1d2021-01-25 13:51:18 +08001699 private int handleGettingEabContactCommand() {
1700 String phoneNumber = getNextArgRequired();
1701 if (TextUtils.isEmpty(phoneNumber)) {
1702 return -1;
1703 }
1704 String result = "";
1705 try {
1706 result = mInterface.getContactFromEab(phoneNumber);
1707
1708 } catch (RemoteException e) {
1709 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1710 getErrPrintWriter().println("Exception: " + e.getMessage());
1711 return -1;
1712 }
1713
1714 if (VDBG) {
1715 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1716 }
calvinpan293ea1b2021-02-04 17:52:13 +08001717 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001718 return 0;
1719 }
1720
1721 private int handleUceGetDeviceEnabledCommand() {
1722 boolean result = false;
1723 try {
1724 result = mInterface.getDeviceUceEnabled();
1725 } catch (RemoteException e) {
1726 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1727 return -1;
1728 }
1729 if (VDBG) {
1730 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1731 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001732 getOutPrintWriter().println(result);
1733 return 0;
1734 }
1735
James.cf Lin4b784aa2021-01-31 03:25:15 +08001736 private int handleUceSetDeviceEnabledCommand() {
1737 String enabledStr = getNextArg();
1738 if (TextUtils.isEmpty(enabledStr)) {
1739 return -1;
1740 }
1741
1742 try {
1743 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1744 mInterface.setDeviceUceEnabled(isEnabled);
1745 if (VDBG) {
1746 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1747 }
1748 } catch (NumberFormatException | RemoteException e) {
1749 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1750 getErrPrintWriter().println("Exception: " + e.getMessage());
1751 return -1;
1752 }
1753 return 0;
1754 }
1755
Hui Wang068ab862020-10-31 05:12:53 +00001756 private int handleSrcSetDeviceEnabledCommand() {
1757 String enabledStr = getNextArg();
1758 if (enabledStr == null) {
1759 return -1;
1760 }
1761
1762 try {
1763 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1764 if (VDBG) {
1765 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1766 }
1767 getOutPrintWriter().println("Done");
1768 } catch (NumberFormatException | RemoteException e) {
1769 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1770 getErrPrintWriter().println("Exception: " + e.getMessage());
1771 return -1;
1772 }
1773 return 0;
1774 }
1775
1776 private int handleSrcGetDeviceEnabledCommand() {
1777 boolean result = false;
1778 try {
1779 result = mInterface.getDeviceSingleRegistrationEnabled();
1780 } catch (RemoteException e) {
1781 return -1;
1782 }
1783 if (VDBG) {
1784 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1785 }
1786 getOutPrintWriter().println(result);
1787 return 0;
1788 }
1789
1790 private int handleSrcSetCarrierEnabledCommand() {
1791 //the release time value could be -1
1792 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1793 : SubscriptionManager.getDefaultSubscriptionId();
1794 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1795 return -1;
1796 }
1797
1798 String enabledStr = getNextArg();
1799 if (enabledStr == null) {
1800 return -1;
1801 }
1802
1803 try {
1804 boolean result =
1805 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1806 if (VDBG) {
1807 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1808 + enabledStr + ", result=" + result);
1809 }
1810 getOutPrintWriter().println(result);
1811 } catch (NumberFormatException | RemoteException e) {
1812 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1813 + enabledStr + ", error" + e.getMessage());
1814 getErrPrintWriter().println("Exception: " + e.getMessage());
1815 return -1;
1816 }
1817 return 0;
1818 }
1819
1820 private int handleSrcGetCarrierEnabledCommand() {
1821 int subId = getSubId("src get-carrier-enabled");
1822 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1823 return -1;
1824 }
1825
1826 boolean result = false;
1827 try {
1828 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1829 } catch (RemoteException e) {
1830 return -1;
1831 }
1832 if (VDBG) {
1833 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1834 }
1835 getOutPrintWriter().println(result);
1836 return 0;
1837 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001838}