blob: c294a813d31e6eddf95c5384dae578ee7d3b2a16 [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
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Shuo Qian489d9282020-07-09 11:30:03 -070031import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010032import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070033import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000034import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080035import android.telephony.emergency.EmergencyNumber;
Brad Ebinger24c29992019-12-05 13:03:21 -080036import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080037import android.text.TextUtils;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.util.Log;
39
40import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080041import com.android.internal.telephony.Phone;
42import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080043import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080044import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080045import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080046import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080047import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
49import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080050import java.util.ArrayList;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010051import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080052import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010053import java.util.Map;
54import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080055import java.util.UUID;
56import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070057
58/**
59 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
60 * permission checks have been done before onCommand was called. Make sure any commands processed
61 * here also contain the appropriate permissions checks.
62 */
63
Hall Liua1548bd2019-12-24 14:14:12 -080064public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070065
66 private static final String LOG_TAG = "TelephonyShellCommand";
67 // Don't commit with this true.
68 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070069 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070
Hall Liuaa4211e2021-01-20 15:43:39 -080071 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070072 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080073 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080074 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070075 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000076 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000077 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010078 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080079 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080080 private static final String ENABLE = "enable";
81 private static final String DISABLE = "disable";
82 private static final String QUERY = "query";
83
Hall Liu7135e502021-02-04 16:58:17 -080084 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080085 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -080086 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -080087
Brad Ebinger999d3302020-11-25 14:31:39 -080088 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
89 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
90 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070091 // Used to disable or enable processing of conference event package data from the network.
92 // This is handy for testing scenarios where CEP data does not exist on a network which does
93 // support CEP data.
94 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070095
Hall Liud892bec2018-11-30 14:51:45 -080096 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080097 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080098
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010099 private static final String CC_GET_VALUE = "get-value";
100 private static final String CC_SET_VALUE = "set-value";
101 private static final String CC_CLEAR_VALUES = "clear-values";
102
Hui Wang641e81c2020-10-12 12:14:23 -0700103 private static final String GBA_SUBCOMMAND = "gba";
104 private static final String GBA_SET_SERVICE = "set-service";
105 private static final String GBA_GET_SERVICE = "get-service";
106 private static final String GBA_SET_RELEASE_TIME = "set-release";
107 private static final String GBA_GET_RELEASE_TIME = "get-release";
108
Hui Wang761a6682020-10-31 05:12:53 +0000109 private static final String SINGLE_REGISTATION_CONFIG = "src";
110 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
111 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
112 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
113 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
114
Tyler Gunn92479152021-01-20 16:30:10 -0800115 private static final String D2D_SUBCOMMAND = "d2d";
116 private static final String D2D_SEND = "send";
117
James.cf Linbcdf8b32021-01-14 16:44:13 +0800118 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800119 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800120 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800121 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
122 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800123
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700124 // Take advantage of existing methods that already contain permissions checks when possible.
125 private final ITelephony mInterface;
126
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private SubscriptionManager mSubscriptionManager;
128 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700129 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100130
131 private enum CcType {
132 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
133 STRING_ARRAY, UNKNOWN
134 }
135
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100136 private class CcOptionParseResult {
137 public int mSubId;
138 public boolean mPersistent;
139 }
140
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100141 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
142 // keys by looking at the end of the string which usually tells the type.
143 // For instance: "xxxx_string", "xxxx_string_array", etc.
144 // The carrier config keys in this map does not follow this convention. It is therefore not
145 // possible to infer the type for these keys by looking at the string.
146 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
147 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
157 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
158 CcType.STRING);
159 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
160 CcType.STRING_ARRAY);
161 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
162 CcType.STRING_ARRAY);
163 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
164 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
165 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
167 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
168 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
169 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
170 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
171 }
172 };
173
174 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700175 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100176 mCarrierConfigManager =
177 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
178 mSubscriptionManager = (SubscriptionManager)
179 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700180 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700181 }
182
183 @Override
184 public int onCommand(String cmd) {
185 if (cmd == null) {
186 return handleDefaultCommands(null);
187 }
188
189 switch (cmd) {
190 case IMS_SUBCOMMAND: {
191 return handleImsCommand();
192 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800193 case RCS_UCE_COMMAND:
194 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800195 case NUMBER_VERIFICATION_SUBCOMMAND:
196 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800197 case EMERGENCY_NUMBER_TEST_MODE:
198 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100199 case CARRIER_CONFIG_SUBCOMMAND: {
200 return handleCcCommand();
201 }
Shuo Qianf5125122019-12-16 17:03:07 -0800202 case DATA_TEST_MODE:
203 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700204 case END_BLOCK_SUPPRESSION:
205 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700206 case GBA_SUBCOMMAND:
207 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800208 case D2D_SUBCOMMAND:
209 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000210 case SINGLE_REGISTATION_CONFIG:
211 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000212 case RESTART_MODEM:
213 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800214 case CALL_COMPOSER_SUBCOMMAND:
215 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000216 case UNATTENDED_REBOOT:
217 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700218 default: {
219 return handleDefaultCommands(cmd);
220 }
221 }
222 }
223
224 @Override
225 public void onHelp() {
226 PrintWriter pw = getOutPrintWriter();
227 pw.println("Telephony Commands:");
228 pw.println(" help");
229 pw.println(" Print this help text.");
230 pw.println(" ims");
231 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800232 pw.println(" uce");
233 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800234 pw.println(" emergency-number-test-mode");
235 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700236 pw.println(" end-block-suppression");
237 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800238 pw.println(" data");
239 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100240 pw.println(" cc");
241 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700242 pw.println(" gba");
243 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000244 pw.println(" src");
245 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000246 pw.println(" restart-modem");
247 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000248 pw.println(" unattended-reboot");
249 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700250 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800251 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800252 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700253 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800254 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100255 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700256 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000257 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800258 onHelpD2D();
259 }
260
261 private void onHelpD2D() {
262 PrintWriter pw = getOutPrintWriter();
263 pw.println("D2D Comms Commands:");
264 pw.println(" d2d send TYPE VALUE");
265 pw.println(" Sends a D2D message of specified type and value.");
266 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
267 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
268 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
269 MESSAGE_CALL_AUDIO_CODEC));
270 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
271 + Communicator.messageToString(
272 MESSAGE_DEVICE_BATTERY_STATE));
273 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
274 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700275 }
276
277 private void onHelpIms() {
278 PrintWriter pw = getOutPrintWriter();
279 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800280 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700281 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
282 pw.println(" ImsService. Options are:");
283 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
284 pw.println(" is specified, it will choose the default voice SIM slot.");
285 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
286 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800287 pw.println(" -f: Set the feature that this override if for, if no option is");
288 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700289 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
290 pw.println(" Gets the package name of the currently defined ImsService.");
291 pw.println(" 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.");
294 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000295 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800296 pw.println(" -f: The feature type that the query will be requested for. If none is");
297 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800298 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
299 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
300 pw.println(" configuration overrides. Options are:");
301 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
302 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700303 pw.println(" ims enable [-s SLOT_ID]");
304 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
305 pw.println(" if none is specified.");
306 pw.println(" ims disable [-s SLOT_ID]");
307 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
308 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700309 pw.println(" ims conference-event-package [enable/disable]");
310 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700311 }
312
James.cf Linbcdf8b32021-01-14 16:44:13 +0800313 private void onHelpUce() {
314 PrintWriter pw = getOutPrintWriter();
315 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800316 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
317 pw.println(" Get the EAB contacts from the EAB database.");
318 pw.println(" Options are:");
319 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
320 pw.println(" Expected output format :");
321 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800322 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
323 pw.println(" Remove the EAB contacts from the EAB database.");
324 pw.println(" Options are:");
325 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
326 pw.println(" is specified, it will choose the default voice SIM slot.");
327 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800328 pw.println(" uce get-device-enabled");
329 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
330 pw.println(" uce set-device-enabled true|false");
331 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
332 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800333 }
334
Hall Liud892bec2018-11-30 14:51:45 -0800335 private void onHelpNumberVerification() {
336 PrintWriter pw = getOutPrintWriter();
337 pw.println("Number verification commands");
338 pw.println(" numverify override-package PACKAGE_NAME;");
339 pw.println(" Set the authorized package for number verification.");
340 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800341 pw.println(" numverify fake-call NUMBER;");
342 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
343 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800344 }
345
Shuo Qianf5125122019-12-16 17:03:07 -0800346 private void onHelpDataTestMode() {
347 PrintWriter pw = getOutPrintWriter();
348 pw.println("Mobile Data Test Mode Commands:");
349 pw.println(" data enable: enable mobile data connectivity");
350 pw.println(" data disable: disable mobile data connectivity");
351 }
352
sqian9d4df8b2019-01-15 18:32:07 -0800353 private void onHelpEmergencyNumber() {
354 PrintWriter pw = getOutPrintWriter();
355 pw.println("Emergency Number Test Mode Commands:");
356 pw.println(" emergency-number-test-mode ");
357 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
358 + " the test mode");
359 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700360 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800361 pw.println(" -c: clear the emergency number list in the test mode.");
362 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700363 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800364 pw.println(" -p: get the full emergency number list in the test mode.");
365 }
366
Shuo Qian489d9282020-07-09 11:30:03 -0700367 private void onHelpEndBlockSupperssion() {
368 PrintWriter pw = getOutPrintWriter();
369 pw.println("End Block Suppression command:");
370 pw.println(" end-block-suppression: disable suppressing blocking by contact");
371 pw.println(" with emergency services.");
372 }
373
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100374 private void onHelpCc() {
375 PrintWriter pw = getOutPrintWriter();
376 pw.println("Carrier Config Commands:");
377 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
378 pw.println(" Print carrier config values.");
379 pw.println(" Options are:");
380 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
381 pw.println(" is specified, it will choose the default voice SIM slot.");
382 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
383 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100384 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100385 pw.println(" Set carrier config KEY to NEW_VALUE.");
386 pw.println(" Options are:");
387 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
388 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100389 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100390 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
391 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
392 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
393 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
394 pw.println(" cc clear-values [-s SLOT_ID]");
395 pw.println(" Clear all carrier override values that has previously been set");
396 pw.println(" with set-value");
397 pw.println(" Options are:");
398 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
399 pw.println(" is specified, it will choose the default voice SIM slot.");
400 }
401
Hui Wang641e81c2020-10-12 12:14:23 -0700402 private void onHelpGba() {
403 PrintWriter pw = getOutPrintWriter();
404 pw.println("Gba Commands:");
405 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
406 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
407 pw.println(" Options are:");
408 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
409 pw.println(" is specified, it will choose the default voice SIM slot.");
410 pw.println(" gba get-service [-s SLOT_ID]");
411 pw.println(" Gets the package name of the currently defined GbaService.");
412 pw.println(" Options are:");
413 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
414 pw.println(" is specified, it will choose the default voice SIM slot.");
415 pw.println(" gba set-release [-s SLOT_ID] n");
416 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
417 pw.println(" Do not release/unbind if n is -1.");
418 pw.println(" Options are:");
419 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
420 pw.println(" is specified, it will choose the default voice SIM slot.");
421 pw.println(" gba get-release [-s SLOT_ID]");
422 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
423 pw.println(" Options are:");
424 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
425 pw.println(" is specified, it will choose the default voice SIM slot.");
426 }
427
Hui Wang761a6682020-10-31 05:12:53 +0000428 private void onHelpSrc() {
429 PrintWriter pw = getOutPrintWriter();
430 pw.println("RCS VoLTE Single Registration Config Commands:");
431 pw.println(" src set-device-enabled true|false|null");
432 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
433 pw.println(" The value could be true, false, or null(undefined).");
434 pw.println(" src get-device-enabled");
435 pw.println(" Gets the device config for RCS VoLTE single registration.");
436 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
437 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
438 pw.println(" The value could be true, false, or null(undefined).");
439 pw.println(" Options are:");
440 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
441 pw.println(" is specified, it will choose the default voice SIM slot.");
442 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
443 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
444 pw.println(" Options are:");
445 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
446 pw.println(" is specified, it will choose the default voice SIM slot.");
447 }
448
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700449 private int handleImsCommand() {
450 String arg = getNextArg();
451 if (arg == null) {
452 onHelpIms();
453 return 0;
454 }
455
456 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800457 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700458 return handleImsSetServiceCommand();
459 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800460 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700461 return handleImsGetServiceCommand();
462 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800463 case IMS_CLEAR_SERVICE_OVERRIDE: {
464 return handleImsClearCarrierServiceCommand();
465 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800466 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700467 return handleEnableIms();
468 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800469 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700470 return handleDisableIms();
471 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700472 case IMS_CEP: {
473 return handleCepChange();
474 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700475 }
476
477 return -1;
478 }
479
Shuo Qianf5125122019-12-16 17:03:07 -0800480 private int handleDataTestModeCommand() {
481 PrintWriter errPw = getErrPrintWriter();
482 String arg = getNextArgRequired();
483 if (arg == null) {
484 onHelpDataTestMode();
485 return 0;
486 }
487 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800488 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800489 try {
490 mInterface.enableDataConnectivity();
491 } catch (RemoteException ex) {
492 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
493 errPw.println("Exception: " + ex.getMessage());
494 return -1;
495 }
496 break;
497 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800498 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800499 try {
500 mInterface.disableDataConnectivity();
501 } catch (RemoteException ex) {
502 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
503 errPw.println("Exception: " + ex.getMessage());
504 return -1;
505 }
506 break;
507 }
508 default:
509 onHelpDataTestMode();
510 break;
511 }
512 return 0;
513 }
514
sqian9d4df8b2019-01-15 18:32:07 -0800515 private int handleEmergencyNumberTestModeCommand() {
516 PrintWriter errPw = getErrPrintWriter();
517 String opt = getNextOption();
518 if (opt == null) {
519 onHelpEmergencyNumber();
520 return 0;
521 }
522
523 switch (opt) {
524 case "-a": {
525 String emergencyNumberCmd = getNextArgRequired();
526 if (emergencyNumberCmd == null
527 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700528 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800529 + " to be specified after -a in the command ");
530 return -1;
531 }
532 try {
533 mInterface.updateEmergencyNumberListTestMode(
534 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
535 new EmergencyNumber(emergencyNumberCmd, "", "",
536 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
537 new ArrayList<String>(),
538 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
539 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
540 } catch (RemoteException ex) {
541 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
542 + ", error " + ex.getMessage());
543 errPw.println("Exception: " + ex.getMessage());
544 return -1;
545 }
546 break;
547 }
548 case "-c": {
549 try {
550 mInterface.updateEmergencyNumberListTestMode(
551 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
552 } catch (RemoteException ex) {
553 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
554 errPw.println("Exception: " + ex.getMessage());
555 return -1;
556 }
557 break;
558 }
559 case "-r": {
560 String emergencyNumberCmd = getNextArgRequired();
561 if (emergencyNumberCmd == null
562 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700563 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800564 + " to be specified after -r in the command ");
565 return -1;
566 }
567 try {
568 mInterface.updateEmergencyNumberListTestMode(
569 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
570 new EmergencyNumber(emergencyNumberCmd, "", "",
571 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
572 new ArrayList<String>(),
573 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
574 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
575 } catch (RemoteException ex) {
576 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
577 + ", error " + ex.getMessage());
578 errPw.println("Exception: " + ex.getMessage());
579 return -1;
580 }
581 break;
582 }
583 case "-p": {
584 try {
585 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
586 } catch (RemoteException ex) {
587 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
588 errPw.println("Exception: " + ex.getMessage());
589 return -1;
590 }
591 break;
592 }
593 default:
594 onHelpEmergencyNumber();
595 break;
596 }
597 return 0;
598 }
599
Hall Liud892bec2018-11-30 14:51:45 -0800600 private int handleNumberVerificationCommand() {
601 String arg = getNextArg();
602 if (arg == null) {
603 onHelpNumberVerification();
604 return 0;
605 }
606
Hall Liuca5af3a2018-12-04 16:58:23 -0800607 if (!checkShellUid()) {
608 return -1;
609 }
610
Hall Liud892bec2018-11-30 14:51:45 -0800611 switch (arg) {
612 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800613 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
614 return 0;
615 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800616 case NUMBER_VERIFICATION_FAKE_CALL: {
617 boolean val = NumberVerificationManager.getInstance()
618 .checkIncomingCall(getNextArg());
619 getOutPrintWriter().println(val ? "1" : "0");
620 return 0;
621 }
Hall Liud892bec2018-11-30 14:51:45 -0800622 }
623
624 return -1;
625 }
626
Tyler Gunn92479152021-01-20 16:30:10 -0800627 private int handleD2dCommand() {
628 String arg = getNextArg();
629 if (arg == null) {
630 onHelpD2D();
631 return 0;
632 }
633
634 switch (arg) {
635 case D2D_SEND: {
636 return handleD2dSendCommand();
637 }
638 }
639
640 return -1;
641 }
642
643 private int handleD2dSendCommand() {
644 PrintWriter errPw = getErrPrintWriter();
645 String opt;
646 int messageType = -1;
647 int messageValue = -1;
648
649
650 String arg = getNextArg();
651 if (arg == null) {
652 onHelpD2D();
653 return 0;
654 }
655 try {
656 messageType = Integer.parseInt(arg);
657 } catch (NumberFormatException e) {
658 errPw.println("message type must be a valid integer");
659 return -1;
660 }
661
662 arg = getNextArg();
663 if (arg == null) {
664 onHelpD2D();
665 return 0;
666 }
667 try {
668 messageValue = Integer.parseInt(arg);
669 } catch (NumberFormatException e) {
670 errPw.println("message value must be a valid integer");
671 return -1;
672 }
673
674 try {
675 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
676 } catch (RemoteException e) {
677 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
678 errPw.println("Exception: " + e.getMessage());
679 return -1;
680 }
681
682 return 0;
683 }
684
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700685 // ims set-ims-service
686 private int handleImsSetServiceCommand() {
687 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700688 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700689 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800690 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700691
692 String opt;
693 while ((opt = getNextOption()) != null) {
694 switch (opt) {
695 case "-s": {
696 try {
697 slotId = Integer.parseInt(getNextArgRequired());
698 } catch (NumberFormatException e) {
699 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
700 return -1;
701 }
702 break;
703 }
704 case "-c": {
705 isCarrierService = true;
706 break;
707 }
708 case "-d": {
709 isCarrierService = false;
710 break;
711 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800712 case "-f": {
713 String featureString = getNextArgRequired();
714 String[] features = featureString.split(",");
715 for (int i = 0; i < features.length; i++) {
716 try {
717 Integer result = Integer.parseInt(features[i]);
718 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
719 || result >= ImsFeature.FEATURE_MAX) {
720 errPw.println("ims set-ims-service -f " + result
721 + " is an invalid feature.");
722 return -1;
723 }
724 featuresList.add(result);
725 } catch (NumberFormatException e) {
726 errPw.println("ims set-ims-service -f tried to parse " + features[i]
727 + " as an integer.");
728 return -1;
729 }
730 }
731 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700732 }
733 }
734 // Mandatory param, either -c or -d
735 if (isCarrierService == null) {
736 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
737 return -1;
738 }
739
740 String packageName = getNextArg();
741
742 try {
743 if (packageName == null) {
744 packageName = "";
745 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800746 int[] featureArray = new int[featuresList.size()];
747 for (int i = 0; i < featuresList.size(); i++) {
748 featureArray[i] = featuresList.get(i);
749 }
750 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
751 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700752 if (VDBG) {
753 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800754 + (isCarrierService ? "-c " : "-d ")
755 + "-f " + featuresList + " "
756 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700757 }
758 getOutPrintWriter().println(result);
759 } catch (RemoteException e) {
760 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800761 + (isCarrierService ? "-c " : "-d ")
762 + "-f " + featuresList + " "
763 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700764 errPw.println("Exception: " + e.getMessage());
765 return -1;
766 }
767 return 0;
768 }
769
Brad Ebinger999d3302020-11-25 14:31:39 -0800770 // ims clear-ims-service-override
771 private int handleImsClearCarrierServiceCommand() {
772 PrintWriter errPw = getErrPrintWriter();
773 int slotId = getDefaultSlot();
774
775 String opt;
776 while ((opt = getNextOption()) != null) {
777 switch (opt) {
778 case "-s": {
779 try {
780 slotId = Integer.parseInt(getNextArgRequired());
781 } catch (NumberFormatException e) {
782 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
783 return -1;
784 }
785 break;
786 }
787 }
788 }
789
790 try {
791 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
792 if (VDBG) {
793 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
794 + ", result=" + result);
795 }
796 getOutPrintWriter().println(result);
797 } catch (RemoteException e) {
798 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
799 + ", error" + e.getMessage());
800 errPw.println("Exception: " + e.getMessage());
801 return -1;
802 }
803 return 0;
804 }
805
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700806 // ims get-ims-service
807 private int handleImsGetServiceCommand() {
808 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700809 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700810 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800811 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700812
813 String opt;
814 while ((opt = getNextOption()) != null) {
815 switch (opt) {
816 case "-s": {
817 try {
818 slotId = Integer.parseInt(getNextArgRequired());
819 } catch (NumberFormatException e) {
820 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
821 return -1;
822 }
823 break;
824 }
825 case "-c": {
826 isCarrierService = true;
827 break;
828 }
829 case "-d": {
830 isCarrierService = false;
831 break;
832 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800833 case "-f": {
834 try {
835 featureType = Integer.parseInt(getNextArg());
836 } catch (NumberFormatException e) {
837 errPw.println("ims get-ims-service -f requires valid integer as feature.");
838 return -1;
839 }
840 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
841 || featureType >= ImsFeature.FEATURE_MAX) {
842 errPw.println("ims get-ims-service -f invalid feature.");
843 return -1;
844 }
845 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700846 }
847 }
848 // Mandatory param, either -c or -d
849 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800850 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700851 return -1;
852 }
853
854 String result;
855 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800856 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700857 } catch (RemoteException e) {
858 return -1;
859 }
860 if (VDBG) {
861 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800862 + (isCarrierService ? "-c " : "-d ")
863 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
864 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700865 }
866 getOutPrintWriter().println(result);
867 return 0;
868 }
869
870 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700871 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700872 String opt;
873 while ((opt = getNextOption()) != null) {
874 switch (opt) {
875 case "-s": {
876 try {
877 slotId = Integer.parseInt(getNextArgRequired());
878 } catch (NumberFormatException e) {
879 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
880 return -1;
881 }
882 break;
883 }
884 }
885 }
886 try {
887 mInterface.enableIms(slotId);
888 } catch (RemoteException e) {
889 return -1;
890 }
891 if (VDBG) {
892 Log.v(LOG_TAG, "ims enable -s " + slotId);
893 }
894 return 0;
895 }
896
897 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700898 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700899 String opt;
900 while ((opt = getNextOption()) != null) {
901 switch (opt) {
902 case "-s": {
903 try {
904 slotId = Integer.parseInt(getNextArgRequired());
905 } catch (NumberFormatException e) {
906 getErrPrintWriter().println(
907 "ims disable requires an integer as a SLOT_ID.");
908 return -1;
909 }
910 break;
911 }
912 }
913 }
914 try {
915 mInterface.disableIms(slotId);
916 } catch (RemoteException e) {
917 return -1;
918 }
919 if (VDBG) {
920 Log.v(LOG_TAG, "ims disable -s " + slotId);
921 }
922 return 0;
923 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700924
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700925 private int handleCepChange() {
926 Log.i(LOG_TAG, "handleCepChange");
927 String opt = getNextArg();
928 if (opt == null) {
929 return -1;
930 }
931 boolean isCepEnabled = opt.equals("enable");
932
933 try {
934 mInterface.setCepEnabled(isCepEnabled);
935 } catch (RemoteException e) {
936 return -1;
937 }
938 return 0;
939 }
940
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700941 private int getDefaultSlot() {
942 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
943 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
944 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
945 // If there is no default, default to slot 0.
946 slotId = DEFAULT_PHONE_ID;
947 }
948 return slotId;
949 }
sqian2fff4a32018-11-05 14:18:37 -0800950
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100951 // Parse options related to Carrier Config Commands.
952 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100953 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100954 CcOptionParseResult result = new CcOptionParseResult();
955 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
956 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100957
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100958 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100959 while ((opt = getNextOption()) != null) {
960 switch (opt) {
961 case "-s": {
962 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100963 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
964 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
965 errPw.println(tag + "No valid subscription found.");
966 return null;
967 }
968
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100969 } catch (IllegalArgumentException e) {
970 // Missing slot id
971 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100972 return null;
973 }
974 break;
975 }
976 case "-p": {
977 if (allowOptionPersistent) {
978 result.mPersistent = true;
979 } else {
980 errPw.println(tag + "Unexpected option " + opt);
981 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100982 }
983 break;
984 }
985 default: {
986 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100987 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100988 }
989 }
990 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100991 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100992 }
993
994 private int slotStringToSubId(String tag, String slotString) {
995 int slotId = -1;
996 try {
997 slotId = Integer.parseInt(slotString);
998 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800999 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1000 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1001 }
1002
1003 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001004 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1005 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1006 }
1007
Qiong Liuf25799b2020-09-10 10:13:46 +08001008 Phone phone = PhoneFactory.getPhone(slotId);
1009 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001010 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1011 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1012 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001013 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001014 }
1015
Hall Liud892bec2018-11-30 14:51:45 -08001016 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001017 // adb can run as root or as shell, depending on whether the device is rooted.
1018 return Binder.getCallingUid() == Process.SHELL_UID
1019 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001020 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001021
1022 private int handleCcCommand() {
1023 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1024 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001025 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001026 getErrPrintWriter().println("cc: Permission denied.");
1027 return -1;
1028 }
1029
1030 String arg = getNextArg();
1031 if (arg == null) {
1032 onHelpCc();
1033 return 0;
1034 }
1035
1036 switch (arg) {
1037 case CC_GET_VALUE: {
1038 return handleCcGetValue();
1039 }
1040 case CC_SET_VALUE: {
1041 return handleCcSetValue();
1042 }
1043 case CC_CLEAR_VALUES: {
1044 return handleCcClearValues();
1045 }
1046 default: {
1047 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1048 }
1049 }
1050 return -1;
1051 }
1052
1053 // cc get-value
1054 private int handleCcGetValue() {
1055 PrintWriter errPw = getErrPrintWriter();
1056 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1057 String key = null;
1058
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001059 // Parse all options
1060 CcOptionParseResult options = parseCcOptions(tag, false);
1061 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001062 return -1;
1063 }
1064
1065 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001066 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001067 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001068 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001069 return -1;
1070 }
1071
1072 // Get the key.
1073 key = getNextArg();
1074 if (key != null) {
1075 // A key was provided. Verify if it is a valid key
1076 if (!bundle.containsKey(key)) {
1077 errPw.println(tag + key + " is not a valid key.");
1078 return -1;
1079 }
1080
1081 // Print the carrier config value for key.
1082 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1083 } else {
1084 // No key provided. Show all values.
1085 // Iterate over a sorted list of all carrier config keys and print them.
1086 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1087 for (String k : sortedSet) {
1088 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1089 }
1090 }
1091 return 0;
1092 }
1093
1094 // cc set-value
1095 private int handleCcSetValue() {
1096 PrintWriter errPw = getErrPrintWriter();
1097 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1098
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001099 // Parse all options
1100 CcOptionParseResult options = parseCcOptions(tag, true);
1101 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001102 return -1;
1103 }
1104
1105 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001106 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001107 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001108 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001109 return -1;
1110 }
1111
1112 // Get the key.
1113 String key = getNextArg();
1114 if (key == null || key.equals("")) {
1115 errPw.println(tag + "KEY is missing");
1116 return -1;
1117 }
1118
1119 // Verify if the key is valid
1120 if (!originalValues.containsKey(key)) {
1121 errPw.println(tag + key + " is not a valid key.");
1122 return -1;
1123 }
1124
1125 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1126 ArrayList<String> valueList = new ArrayList<String>();
1127 while (peekNextArg() != null) {
1128 valueList.add(getNextArg());
1129 }
1130
1131 // Find the type of the carrier config value
1132 CcType type = getType(tag, key, originalValues);
1133 if (type == CcType.UNKNOWN) {
1134 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1135 return -1;
1136 }
1137
1138 // Create an override bundle containing the key and value that should be overriden.
1139 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1140 if (overrideBundle == null) {
1141 return -1;
1142 }
1143
1144 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001145 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001146
1147 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001148 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001149 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001150 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001151 return -1;
1152 }
1153
1154 // Print the original and new value.
1155 String originalValueString = ccValueToString(key, type, originalValues);
1156 String newValueString = ccValueToString(key, type, newValues);
1157 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1158 getOutPrintWriter().println("New value: \n" + newValueString);
1159
1160 return 0;
1161 }
1162
1163 // cc clear-values
1164 private int handleCcClearValues() {
1165 PrintWriter errPw = getErrPrintWriter();
1166 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1167
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001168 // Parse all options
1169 CcOptionParseResult options = parseCcOptions(tag, false);
1170 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001171 return -1;
1172 }
1173
1174 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001175 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001176 getOutPrintWriter()
1177 .println("All previously set carrier config override values has been cleared");
1178 return 0;
1179 }
1180
1181 private CcType getType(String tag, String key, PersistableBundle bundle) {
1182 // Find the type by checking the type of the current value stored in the bundle.
1183 Object value = bundle.get(key);
1184
1185 if (CC_TYPE_MAP.containsKey(key)) {
1186 return CC_TYPE_MAP.get(key);
1187 } else if (value != null) {
1188 if (value instanceof Boolean) {
1189 return CcType.BOOLEAN;
1190 } else if (value instanceof Double) {
1191 return CcType.DOUBLE;
1192 } else if (value instanceof double[]) {
1193 return CcType.DOUBLE_ARRAY;
1194 } else if (value instanceof Integer) {
1195 return CcType.INT;
1196 } else if (value instanceof int[]) {
1197 return CcType.INT_ARRAY;
1198 } else if (value instanceof Long) {
1199 return CcType.LONG;
1200 } else if (value instanceof long[]) {
1201 return CcType.LONG_ARRAY;
1202 } else if (value instanceof String) {
1203 return CcType.STRING;
1204 } else if (value instanceof String[]) {
1205 return CcType.STRING_ARRAY;
1206 }
1207 } else {
1208 // Current value was null and can therefore not be used in order to find the type.
1209 // Check the name of the key to infer the type. This check is not needed for primitive
1210 // data types (boolean, double, int and long), since they can not be null.
1211 if (key.endsWith("double_array")) {
1212 return CcType.DOUBLE_ARRAY;
1213 }
1214 if (key.endsWith("int_array")) {
1215 return CcType.INT_ARRAY;
1216 }
1217 if (key.endsWith("long_array")) {
1218 return CcType.LONG_ARRAY;
1219 }
1220 if (key.endsWith("string")) {
1221 return CcType.STRING;
1222 }
1223 if (key.endsWith("string_array") || key.endsWith("strings")) {
1224 return CcType.STRING_ARRAY;
1225 }
1226 }
1227
1228 // Not possible to infer the type by looking at the current value or the key.
1229 PrintWriter errPw = getErrPrintWriter();
1230 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1231 return CcType.UNKNOWN;
1232 }
1233
1234 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1235 String result;
1236 StringBuilder valueString = new StringBuilder();
1237 String typeString = type.toString();
1238 Object value = bundle.get(key);
1239
1240 if (value == null) {
1241 valueString.append("null");
1242 } else {
1243 switch (type) {
1244 case DOUBLE_ARRAY: {
1245 // Format the string representation of the int array as value1 value2......
1246 double[] valueArray = (double[]) value;
1247 for (int i = 0; i < valueArray.length; i++) {
1248 if (i != 0) {
1249 valueString.append(" ");
1250 }
1251 valueString.append(valueArray[i]);
1252 }
1253 break;
1254 }
1255 case INT_ARRAY: {
1256 // Format the string representation of the int array as value1 value2......
1257 int[] valueArray = (int[]) value;
1258 for (int i = 0; i < valueArray.length; i++) {
1259 if (i != 0) {
1260 valueString.append(" ");
1261 }
1262 valueString.append(valueArray[i]);
1263 }
1264 break;
1265 }
1266 case LONG_ARRAY: {
1267 // Format the string representation of the int array as value1 value2......
1268 long[] valueArray = (long[]) value;
1269 for (int i = 0; i < valueArray.length; i++) {
1270 if (i != 0) {
1271 valueString.append(" ");
1272 }
1273 valueString.append(valueArray[i]);
1274 }
1275 break;
1276 }
1277 case STRING: {
1278 valueString.append("\"" + value.toString() + "\"");
1279 break;
1280 }
1281 case STRING_ARRAY: {
1282 // Format the string representation of the string array as "value1" "value2"....
1283 String[] valueArray = (String[]) value;
1284 for (int i = 0; i < valueArray.length; i++) {
1285 if (i != 0) {
1286 valueString.append(" ");
1287 }
1288 if (valueArray[i] != null) {
1289 valueString.append("\"" + valueArray[i] + "\"");
1290 } else {
1291 valueString.append("null");
1292 }
1293 }
1294 break;
1295 }
1296 default: {
1297 valueString.append(value.toString());
1298 }
1299 }
1300 }
1301 return String.format("%-70s %-15s %s", key, typeString, valueString);
1302 }
1303
1304 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1305 ArrayList<String> valueList) {
1306 PrintWriter errPw = getErrPrintWriter();
1307 PersistableBundle bundle = new PersistableBundle();
1308
1309 // First verify that a valid number of values has been provided for the type.
1310 switch (type) {
1311 case BOOLEAN:
1312 case DOUBLE:
1313 case INT:
1314 case LONG: {
1315 if (valueList.size() != 1) {
1316 errPw.println(tag + "Expected 1 value for type " + type
1317 + ". Found: " + valueList.size());
1318 return null;
1319 }
1320 break;
1321 }
1322 case STRING: {
1323 if (valueList.size() > 1) {
1324 errPw.println(tag + "Expected 0 or 1 values for type " + type
1325 + ". Found: " + valueList.size());
1326 return null;
1327 }
1328 break;
1329 }
1330 }
1331
1332 // Parse the value according to type and add it to the Bundle.
1333 switch (type) {
1334 case BOOLEAN: {
1335 if ("true".equalsIgnoreCase(valueList.get(0))) {
1336 bundle.putBoolean(key, true);
1337 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1338 bundle.putBoolean(key, false);
1339 } else {
1340 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1341 return null;
1342 }
1343 break;
1344 }
1345 case DOUBLE: {
1346 try {
1347 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1348 } catch (NumberFormatException nfe) {
1349 // Not a valid double
1350 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1351 return null;
1352 }
1353 break;
1354 }
1355 case DOUBLE_ARRAY: {
1356 double[] valueDoubleArray = null;
1357 if (valueList.size() > 0) {
1358 valueDoubleArray = new double[valueList.size()];
1359 for (int i = 0; i < valueList.size(); i++) {
1360 try {
1361 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1362 } catch (NumberFormatException nfe) {
1363 // Not a valid double
1364 errPw.println(
1365 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1366 return null;
1367 }
1368 }
1369 }
1370 bundle.putDoubleArray(key, valueDoubleArray);
1371 break;
1372 }
1373 case INT: {
1374 try {
1375 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1376 } catch (NumberFormatException nfe) {
1377 // Not a valid integer
1378 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1379 return null;
1380 }
1381 break;
1382 }
1383 case INT_ARRAY: {
1384 int[] valueIntArray = null;
1385 if (valueList.size() > 0) {
1386 valueIntArray = new int[valueList.size()];
1387 for (int i = 0; i < valueList.size(); i++) {
1388 try {
1389 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1390 } catch (NumberFormatException nfe) {
1391 // Not a valid integer
1392 errPw.println(tag
1393 + "Unable to parse " + valueList.get(i) + " as an integer.");
1394 return null;
1395 }
1396 }
1397 }
1398 bundle.putIntArray(key, valueIntArray);
1399 break;
1400 }
1401 case LONG: {
1402 try {
1403 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1404 } catch (NumberFormatException nfe) {
1405 // Not a valid long
1406 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1407 return null;
1408 }
1409 break;
1410 }
1411 case LONG_ARRAY: {
1412 long[] valueLongArray = null;
1413 if (valueList.size() > 0) {
1414 valueLongArray = new long[valueList.size()];
1415 for (int i = 0; i < valueList.size(); i++) {
1416 try {
1417 valueLongArray[i] = Long.parseLong(valueList.get(i));
1418 } catch (NumberFormatException nfe) {
1419 // Not a valid long
1420 errPw.println(
1421 tag + "Unable to parse " + valueList.get(i) + " as a long");
1422 return null;
1423 }
1424 }
1425 }
1426 bundle.putLongArray(key, valueLongArray);
1427 break;
1428 }
1429 case STRING: {
1430 String value = null;
1431 if (valueList.size() > 0) {
1432 value = valueList.get(0);
1433 }
1434 bundle.putString(key, value);
1435 break;
1436 }
1437 case STRING_ARRAY: {
1438 String[] valueStringArray = null;
1439 if (valueList.size() > 0) {
1440 valueStringArray = new String[valueList.size()];
1441 valueList.toArray(valueStringArray);
1442 }
1443 bundle.putStringArray(key, valueStringArray);
1444 break;
1445 }
1446 }
1447 return bundle;
1448 }
Shuo Qian489d9282020-07-09 11:30:03 -07001449
1450 private int handleEndBlockSuppressionCommand() {
1451 if (!checkShellUid()) {
1452 return -1;
1453 }
1454
1455 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1456 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1457 }
1458 return 0;
1459 }
Hui Wang641e81c2020-10-12 12:14:23 -07001460
Michele Berionne54af4632020-12-28 20:23:16 +00001461 private int handleRestartModemCommand() {
1462 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1463 // non user build.
1464 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1465 getErrPrintWriter().println("RestartModem: Permission denied.");
1466 return -1;
1467 }
1468
1469 boolean result = TelephonyManager.getDefault().rebootRadio();
1470 getOutPrintWriter().println(result);
1471
1472 return result ? 0 : -1;
1473 }
1474
Michele Berionne5e411512020-11-13 02:36:59 +00001475 private int handleUnattendedReboot() {
1476 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1477 // non user build.
1478 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1479 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1480 return -1;
1481 }
1482
1483 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1484 getOutPrintWriter().println("result: " + result);
1485
1486 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1487 }
1488
Hui Wang641e81c2020-10-12 12:14:23 -07001489 private int handleGbaCommand() {
1490 String arg = getNextArg();
1491 if (arg == null) {
1492 onHelpGba();
1493 return 0;
1494 }
1495
1496 switch (arg) {
1497 case GBA_SET_SERVICE: {
1498 return handleGbaSetServiceCommand();
1499 }
1500 case GBA_GET_SERVICE: {
1501 return handleGbaGetServiceCommand();
1502 }
1503 case GBA_SET_RELEASE_TIME: {
1504 return handleGbaSetReleaseCommand();
1505 }
1506 case GBA_GET_RELEASE_TIME: {
1507 return handleGbaGetReleaseCommand();
1508 }
1509 }
1510
1511 return -1;
1512 }
1513
1514 private int getSubId(String cmd) {
1515 int slotId = getDefaultSlot();
1516 String opt = getNextOption();
1517 if (opt != null && opt.equals("-s")) {
1518 try {
1519 slotId = Integer.parseInt(getNextArgRequired());
1520 } catch (NumberFormatException e) {
1521 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1522 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1523 }
1524 }
1525 int[] subIds = SubscriptionManager.getSubId(slotId);
1526 return subIds[0];
1527 }
1528
1529 private int handleGbaSetServiceCommand() {
1530 int subId = getSubId("gba set-service");
1531 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1532 return -1;
1533 }
1534
1535 String packageName = getNextArg();
1536 try {
1537 if (packageName == null) {
1538 packageName = "";
1539 }
1540 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1541 if (VDBG) {
1542 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1543 + packageName + ", result=" + result);
1544 }
1545 getOutPrintWriter().println(result);
1546 } catch (RemoteException e) {
1547 Log.w(LOG_TAG, "gba set-service " + subId + " "
1548 + packageName + ", error" + e.getMessage());
1549 getErrPrintWriter().println("Exception: " + e.getMessage());
1550 return -1;
1551 }
1552 return 0;
1553 }
1554
1555 private int handleGbaGetServiceCommand() {
1556 String result;
1557
1558 int subId = getSubId("gba get-service");
1559 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1560 return -1;
1561 }
1562
1563 try {
1564 result = mInterface.getBoundGbaService(subId);
1565 } catch (RemoteException e) {
1566 return -1;
1567 }
1568 if (VDBG) {
1569 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1570 }
1571 getOutPrintWriter().println(result);
1572 return 0;
1573 }
1574
1575 private int handleGbaSetReleaseCommand() {
1576 //the release time value could be -1
1577 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1578 : SubscriptionManager.getDefaultSubscriptionId();
1579 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1580 return -1;
1581 }
1582
1583 String intervalStr = getNextArg();
1584 if (intervalStr == null) {
1585 return -1;
1586 }
1587
1588 try {
1589 int interval = Integer.parseInt(intervalStr);
1590 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1591 if (VDBG) {
1592 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1593 + intervalStr + ", result=" + result);
1594 }
1595 getOutPrintWriter().println(result);
1596 } catch (NumberFormatException | RemoteException e) {
1597 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1598 + intervalStr + ", error" + e.getMessage());
1599 getErrPrintWriter().println("Exception: " + e.getMessage());
1600 return -1;
1601 }
1602 return 0;
1603 }
1604
1605 private int handleGbaGetReleaseCommand() {
1606 int subId = getSubId("gba get-release");
1607 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1608 return -1;
1609 }
1610
1611 int result = 0;
1612 try {
1613 result = mInterface.getGbaReleaseTime(subId);
1614 } catch (RemoteException e) {
1615 return -1;
1616 }
1617 if (VDBG) {
1618 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1619 }
1620 getOutPrintWriter().println(result);
1621 return 0;
1622 }
Hui Wang761a6682020-10-31 05:12:53 +00001623
1624 private int handleSingleRegistrationConfigCommand() {
1625 String arg = getNextArg();
1626 if (arg == null) {
1627 onHelpSrc();
1628 return 0;
1629 }
1630
1631 switch (arg) {
1632 case SRC_SET_DEVICE_ENABLED: {
1633 return handleSrcSetDeviceEnabledCommand();
1634 }
1635 case SRC_GET_DEVICE_ENABLED: {
1636 return handleSrcGetDeviceEnabledCommand();
1637 }
1638 case SRC_SET_CARRIER_ENABLED: {
1639 return handleSrcSetCarrierEnabledCommand();
1640 }
1641 case SRC_GET_CARRIER_ENABLED: {
1642 return handleSrcGetCarrierEnabledCommand();
1643 }
1644 }
1645
1646 return -1;
1647 }
1648
James.cf Linbcdf8b32021-01-14 16:44:13 +08001649 private int handleRcsUceCommand() {
1650 String arg = getNextArg();
1651 if (arg == null) {
1652 Log.w(LOG_TAG, "cannot get uce parameter");
1653 return -1;
1654 }
1655
1656 switch (arg) {
1657 case UCE_REMOVE_EAB_CONTACT:
1658 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001659 case UCE_GET_EAB_CONTACT:
1660 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001661 case UCE_GET_DEVICE_ENABLED:
1662 return handleUceGetDeviceEnabledCommand();
1663 case UCE_SET_DEVICE_ENABLED:
1664 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001665 }
1666 return -1;
1667 }
1668
1669 private int handleRemovingEabContactCommand() {
1670 int subId = getSubId("uce remove-eab-contact");
1671 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1672 return -1;
1673 }
1674
1675 String phoneNumber = getNextArgRequired();
1676 if (TextUtils.isEmpty(phoneNumber)) {
1677 return -1;
1678 }
1679 int result = 0;
1680 try {
1681 result = mInterface.removeContactFromEab(subId, phoneNumber);
1682 } catch (RemoteException e) {
1683 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1684 getErrPrintWriter().println("Exception: " + e.getMessage());
1685 return -1;
1686 }
1687
1688 if (VDBG) {
1689 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1690 }
calvinpan293ea1b2021-02-04 17:52:13 +08001691 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001692 }
1693
calvinpane4a8a1d2021-01-25 13:51:18 +08001694 private int handleGettingEabContactCommand() {
1695 String phoneNumber = getNextArgRequired();
1696 if (TextUtils.isEmpty(phoneNumber)) {
1697 return -1;
1698 }
1699 String result = "";
1700 try {
1701 result = mInterface.getContactFromEab(phoneNumber);
1702
1703 } catch (RemoteException e) {
1704 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1705 getErrPrintWriter().println("Exception: " + e.getMessage());
1706 return -1;
1707 }
1708
1709 if (VDBG) {
1710 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1711 }
calvinpan293ea1b2021-02-04 17:52:13 +08001712 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001713 return 0;
1714 }
1715
1716 private int handleUceGetDeviceEnabledCommand() {
1717 boolean result = false;
1718 try {
1719 result = mInterface.getDeviceUceEnabled();
1720 } catch (RemoteException e) {
1721 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1722 return -1;
1723 }
1724 if (VDBG) {
1725 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1726 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001727 getOutPrintWriter().println(result);
1728 return 0;
1729 }
1730
James.cf Lin4b784aa2021-01-31 03:25:15 +08001731 private int handleUceSetDeviceEnabledCommand() {
1732 String enabledStr = getNextArg();
1733 if (TextUtils.isEmpty(enabledStr)) {
1734 return -1;
1735 }
1736
1737 try {
1738 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1739 mInterface.setDeviceUceEnabled(isEnabled);
1740 if (VDBG) {
1741 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1742 }
1743 } catch (NumberFormatException | RemoteException e) {
1744 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1745 getErrPrintWriter().println("Exception: " + e.getMessage());
1746 return -1;
1747 }
1748 return 0;
1749 }
1750
Hui Wang761a6682020-10-31 05:12:53 +00001751 private int handleSrcSetDeviceEnabledCommand() {
1752 String enabledStr = getNextArg();
1753 if (enabledStr == null) {
1754 return -1;
1755 }
1756
1757 try {
1758 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1759 if (VDBG) {
1760 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1761 }
1762 getOutPrintWriter().println("Done");
1763 } catch (NumberFormatException | RemoteException e) {
1764 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1765 getErrPrintWriter().println("Exception: " + e.getMessage());
1766 return -1;
1767 }
1768 return 0;
1769 }
1770
1771 private int handleSrcGetDeviceEnabledCommand() {
1772 boolean result = false;
1773 try {
1774 result = mInterface.getDeviceSingleRegistrationEnabled();
1775 } catch (RemoteException e) {
1776 return -1;
1777 }
1778 if (VDBG) {
1779 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1780 }
1781 getOutPrintWriter().println(result);
1782 return 0;
1783 }
1784
1785 private int handleSrcSetCarrierEnabledCommand() {
1786 //the release time value could be -1
1787 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1788 : SubscriptionManager.getDefaultSubscriptionId();
1789 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1790 return -1;
1791 }
1792
1793 String enabledStr = getNextArg();
1794 if (enabledStr == null) {
1795 return -1;
1796 }
1797
1798 try {
1799 boolean result =
1800 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1801 if (VDBG) {
1802 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1803 + enabledStr + ", result=" + result);
1804 }
1805 getOutPrintWriter().println(result);
1806 } catch (NumberFormatException | RemoteException e) {
1807 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1808 + enabledStr + ", error" + e.getMessage());
1809 getErrPrintWriter().println("Exception: " + e.getMessage());
1810 return -1;
1811 }
1812 return 0;
1813 }
1814
1815 private int handleSrcGetCarrierEnabledCommand() {
1816 int subId = getSubId("src get-carrier-enabled");
1817 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1818 return -1;
1819 }
1820
1821 boolean result = false;
1822 try {
1823 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1824 } catch (RemoteException e) {
1825 return -1;
1826 }
1827 if (VDBG) {
1828 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1829 }
1830 getOutPrintWriter().println(result);
1831 return 0;
1832 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001833
1834 private void onHelpCallComposer() {
1835 PrintWriter pw = getOutPrintWriter();
1836 pw.println("Call composer commands");
1837 pw.println(" callcomposer test-mode enable|disable|query");
1838 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1839 pw.println(" upload/download from carrier servers is disabled, and operations are");
1840 pw.println(" performed using emulated local files instead.");
1841 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1842 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1843 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08001844 pw.println(" callcomposer user-setting [subId] enable|disable|query");
1845 pw.println(" Enables or disables the user setting for call composer, as set by");
1846 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08001847 }
1848
1849 private int handleCallComposerCommand() {
1850 String arg = getNextArg();
1851 if (arg == null) {
1852 onHelpCallComposer();
1853 return 0;
1854 }
1855
1856 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1857 "MODIFY_PHONE_STATE required for call composer shell cmds");
1858 switch (arg) {
1859 case CALL_COMPOSER_TEST_MODE: {
1860 String enabledStr = getNextArg();
1861 if (ENABLE.equals(enabledStr)) {
1862 CallComposerPictureManager.sTestMode = true;
1863 } else if (DISABLE.equals(enabledStr)) {
1864 CallComposerPictureManager.sTestMode = false;
1865 } else if (QUERY.equals(enabledStr)) {
1866 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1867 } else {
1868 onHelpCallComposer();
1869 return 1;
1870 }
1871 break;
1872 }
1873 case CALL_COMPOSER_SIMULATE_CALL: {
1874 int subscriptionId = Integer.valueOf(getNextArg());
1875 String uuidString = getNextArg();
1876 UUID uuid = UUID.fromString(uuidString);
1877 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1878 Binder.withCleanCallingIdentity(() -> {
1879 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1880 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1881 });
1882 try {
1883 Uri uri = storageUriFuture.get();
1884 getOutPrintWriter().println(String.valueOf(uri));
1885 } catch (Exception e) {
1886 throw new RuntimeException(e);
1887 }
1888 break;
1889 }
Hall Liu7917ecf2021-02-23 12:22:31 -08001890 case CALL_COMPOSER_USER_SETTING: {
1891 try {
1892 int subscriptionId = Integer.valueOf(getNextArg());
1893 String enabledStr = getNextArg();
1894 if (ENABLE.equals(enabledStr)) {
1895 mInterface.setCallComposerStatus(subscriptionId,
1896 TelephonyManager.CALL_COMPOSER_STATUS_ON);
1897 } else if (DISABLE.equals(enabledStr)) {
1898 mInterface.setCallComposerStatus(subscriptionId,
1899 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
1900 } else if (QUERY.equals(enabledStr)) {
1901 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
1902 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
1903 } else {
1904 onHelpCallComposer();
1905 return 1;
1906 }
1907 } catch (RemoteException e) {
1908 e.printStackTrace(getOutPrintWriter());
1909 return 1;
1910 }
1911 break;
1912 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001913 }
1914
1915 return 0;
1916 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001917}