blob: 91fa4838cc55a15b42e4ebcca000405955e1149a [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";
Shuo Qianccbaf742021-02-22 18:32:21 -080074 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080075 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070076 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000077 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000078 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010079 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080080 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080081 private static final String ENABLE = "enable";
82 private static final String DISABLE = "disable";
83 private static final String QUERY = "query";
84
Hall Liu7135e502021-02-04 16:58:17 -080085 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080086 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -080087 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -080088
Brad Ebinger999d3302020-11-25 14:31:39 -080089 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
90 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
91 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070092 // Used to disable or enable processing of conference event package data from the network.
93 // This is handy for testing scenarios where CEP data does not exist on a network which does
94 // support CEP data.
95 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070096
Hall Liud892bec2018-11-30 14:51:45 -080097 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080098 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080099
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100100 private static final String CC_GET_VALUE = "get-value";
101 private static final String CC_SET_VALUE = "set-value";
102 private static final String CC_CLEAR_VALUES = "clear-values";
103
Hui Wang641e81c2020-10-12 12:14:23 -0700104 private static final String GBA_SUBCOMMAND = "gba";
105 private static final String GBA_SET_SERVICE = "set-service";
106 private static final String GBA_GET_SERVICE = "get-service";
107 private static final String GBA_SET_RELEASE_TIME = "set-release";
108 private static final String GBA_GET_RELEASE_TIME = "get-release";
109
Hui Wang761a6682020-10-31 05:12:53 +0000110 private static final String SINGLE_REGISTATION_CONFIG = "src";
111 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
112 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
113 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
114 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
115
Tyler Gunn92479152021-01-20 16:30:10 -0800116 private static final String D2D_SUBCOMMAND = "d2d";
117 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800118 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800119
James.cf Linbcdf8b32021-01-14 16:44:13 +0800120 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800121 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800122 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800123 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
124 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800125
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700126 // Take advantage of existing methods that already contain permissions checks when possible.
127 private final ITelephony mInterface;
128
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100129 private SubscriptionManager mSubscriptionManager;
130 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700131 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100132
133 private enum CcType {
134 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
135 STRING_ARRAY, UNKNOWN
136 }
137
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100138 private class CcOptionParseResult {
139 public int mSubId;
140 public boolean mPersistent;
141 }
142
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100143 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
144 // keys by looking at the end of the string which usually tells the type.
145 // For instance: "xxxx_string", "xxxx_string_array", etc.
146 // The carrier config keys in this map does not follow this convention. It is therefore not
147 // possible to infer the type for these keys by looking at the string.
148 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
149 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
157 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
158 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
159 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
160 CcType.STRING);
161 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
162 CcType.STRING_ARRAY);
163 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
164 CcType.STRING_ARRAY);
165 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
167 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
168 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
169 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
170 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
171 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
172 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
173 }
174 };
175
176 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700177 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100178 mCarrierConfigManager =
179 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
180 mSubscriptionManager = (SubscriptionManager)
181 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700182 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700183 }
184
185 @Override
186 public int onCommand(String cmd) {
187 if (cmd == null) {
188 return handleDefaultCommands(null);
189 }
190
191 switch (cmd) {
192 case IMS_SUBCOMMAND: {
193 return handleImsCommand();
194 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800195 case RCS_UCE_COMMAND:
196 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800197 case NUMBER_VERIFICATION_SUBCOMMAND:
198 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800199 case EMERGENCY_CALLBACK_MODE:
200 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800201 case EMERGENCY_NUMBER_TEST_MODE:
202 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100203 case CARRIER_CONFIG_SUBCOMMAND: {
204 return handleCcCommand();
205 }
Shuo Qianf5125122019-12-16 17:03:07 -0800206 case DATA_TEST_MODE:
207 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700208 case END_BLOCK_SUPPRESSION:
209 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700210 case GBA_SUBCOMMAND:
211 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800212 case D2D_SUBCOMMAND:
213 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000214 case SINGLE_REGISTATION_CONFIG:
215 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000216 case RESTART_MODEM:
217 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800218 case CALL_COMPOSER_SUBCOMMAND:
219 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000220 case UNATTENDED_REBOOT:
221 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700222 default: {
223 return handleDefaultCommands(cmd);
224 }
225 }
226 }
227
228 @Override
229 public void onHelp() {
230 PrintWriter pw = getOutPrintWriter();
231 pw.println("Telephony Commands:");
232 pw.println(" help");
233 pw.println(" Print this help text.");
234 pw.println(" ims");
235 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800236 pw.println(" uce");
237 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800238 pw.println(" emergency-number-test-mode");
239 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700240 pw.println(" end-block-suppression");
241 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800242 pw.println(" data");
243 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100244 pw.println(" cc");
245 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700246 pw.println(" gba");
247 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000248 pw.println(" src");
249 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000250 pw.println(" restart-modem");
251 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000252 pw.println(" unattended-reboot");
253 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700254 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800255 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800256 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700257 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800258 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100259 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700260 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000261 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800262 onHelpD2D();
263 }
264
265 private void onHelpD2D() {
266 PrintWriter pw = getOutPrintWriter();
267 pw.println("D2D Comms Commands:");
268 pw.println(" d2d send TYPE VALUE");
269 pw.println(" Sends a D2D message of specified type and value.");
270 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
271 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
272 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
273 MESSAGE_CALL_AUDIO_CODEC));
274 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
275 + Communicator.messageToString(
276 MESSAGE_DEVICE_BATTERY_STATE));
277 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
278 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800279 pw.println(" d2d transport TYPE");
280 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
281 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700282 }
283
284 private void onHelpIms() {
285 PrintWriter pw = getOutPrintWriter();
286 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800287 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700288 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
289 pw.println(" ImsService. Options are:");
290 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
291 pw.println(" is specified, it will choose the default voice SIM slot.");
292 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
293 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800294 pw.println(" -f: Set the feature that this override if for, if no option is");
295 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700296 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
297 pw.println(" Gets the package name of the currently defined ImsService.");
298 pw.println(" Options are:");
299 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
300 pw.println(" is specified, it will choose the default voice SIM slot.");
301 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000302 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800303 pw.println(" -f: The feature type that the query will be requested for. If none is");
304 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800305 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
306 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
307 pw.println(" configuration overrides. Options are:");
308 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
309 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700310 pw.println(" ims enable [-s SLOT_ID]");
311 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
312 pw.println(" if none is specified.");
313 pw.println(" ims disable [-s SLOT_ID]");
314 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
315 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700316 pw.println(" ims conference-event-package [enable/disable]");
317 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700318 }
319
James.cf Linbcdf8b32021-01-14 16:44:13 +0800320 private void onHelpUce() {
321 PrintWriter pw = getOutPrintWriter();
322 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800323 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
324 pw.println(" Get the EAB contacts from the EAB database.");
325 pw.println(" Options are:");
326 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
327 pw.println(" Expected output format :");
328 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800329 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
330 pw.println(" Remove the EAB contacts from the EAB database.");
331 pw.println(" Options are:");
332 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
333 pw.println(" is specified, it will choose the default voice SIM slot.");
334 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800335 pw.println(" uce get-device-enabled");
336 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
337 pw.println(" uce set-device-enabled true|false");
338 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
339 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800340 }
341
Hall Liud892bec2018-11-30 14:51:45 -0800342 private void onHelpNumberVerification() {
343 PrintWriter pw = getOutPrintWriter();
344 pw.println("Number verification commands");
345 pw.println(" numverify override-package PACKAGE_NAME;");
346 pw.println(" Set the authorized package for number verification.");
347 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800348 pw.println(" numverify fake-call NUMBER;");
349 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
350 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800351 }
352
Shuo Qianf5125122019-12-16 17:03:07 -0800353 private void onHelpDataTestMode() {
354 PrintWriter pw = getOutPrintWriter();
355 pw.println("Mobile Data Test Mode Commands:");
356 pw.println(" data enable: enable mobile data connectivity");
357 pw.println(" data disable: disable mobile data connectivity");
358 }
359
sqian9d4df8b2019-01-15 18:32:07 -0800360 private void onHelpEmergencyNumber() {
361 PrintWriter pw = getOutPrintWriter();
362 pw.println("Emergency Number Test Mode Commands:");
363 pw.println(" emergency-number-test-mode ");
364 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
365 + " the test mode");
366 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700367 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800368 pw.println(" -c: clear the emergency number list in the test mode.");
369 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700370 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800371 pw.println(" -p: get the full emergency number list in the test mode.");
372 }
373
Shuo Qian489d9282020-07-09 11:30:03 -0700374 private void onHelpEndBlockSupperssion() {
375 PrintWriter pw = getOutPrintWriter();
376 pw.println("End Block Suppression command:");
377 pw.println(" end-block-suppression: disable suppressing blocking by contact");
378 pw.println(" with emergency services.");
379 }
380
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100381 private void onHelpCc() {
382 PrintWriter pw = getOutPrintWriter();
383 pw.println("Carrier Config Commands:");
384 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
385 pw.println(" Print carrier config values.");
386 pw.println(" Options are:");
387 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
388 pw.println(" is specified, it will choose the default voice SIM slot.");
389 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
390 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100391 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100392 pw.println(" Set carrier config KEY to NEW_VALUE.");
393 pw.println(" Options are:");
394 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
395 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100396 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100397 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
398 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
399 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
400 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
401 pw.println(" cc clear-values [-s SLOT_ID]");
402 pw.println(" Clear all carrier override values that has previously been set");
403 pw.println(" with set-value");
404 pw.println(" Options are:");
405 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
406 pw.println(" is specified, it will choose the default voice SIM slot.");
407 }
408
Hui Wang641e81c2020-10-12 12:14:23 -0700409 private void onHelpGba() {
410 PrintWriter pw = getOutPrintWriter();
411 pw.println("Gba Commands:");
412 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
413 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
414 pw.println(" Options are:");
415 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
416 pw.println(" is specified, it will choose the default voice SIM slot.");
417 pw.println(" gba get-service [-s SLOT_ID]");
418 pw.println(" Gets the package name of the currently defined GbaService.");
419 pw.println(" Options are:");
420 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
421 pw.println(" is specified, it will choose the default voice SIM slot.");
422 pw.println(" gba set-release [-s SLOT_ID] n");
423 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
424 pw.println(" Do not release/unbind if n is -1.");
425 pw.println(" Options are:");
426 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
427 pw.println(" is specified, it will choose the default voice SIM slot.");
428 pw.println(" gba get-release [-s SLOT_ID]");
429 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
430 pw.println(" Options are:");
431 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
432 pw.println(" is specified, it will choose the default voice SIM slot.");
433 }
434
Hui Wang761a6682020-10-31 05:12:53 +0000435 private void onHelpSrc() {
436 PrintWriter pw = getOutPrintWriter();
437 pw.println("RCS VoLTE Single Registration Config Commands:");
438 pw.println(" src set-device-enabled true|false|null");
439 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
440 pw.println(" The value could be true, false, or null(undefined).");
441 pw.println(" src get-device-enabled");
442 pw.println(" Gets the device config for RCS VoLTE single registration.");
443 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
444 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
445 pw.println(" The value could be true, false, or null(undefined).");
446 pw.println(" Options are:");
447 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
448 pw.println(" is specified, it will choose the default voice SIM slot.");
449 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
450 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
451 pw.println(" Options are:");
452 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
453 pw.println(" is specified, it will choose the default voice SIM slot.");
454 }
455
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700456 private int handleImsCommand() {
457 String arg = getNextArg();
458 if (arg == null) {
459 onHelpIms();
460 return 0;
461 }
462
463 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800464 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700465 return handleImsSetServiceCommand();
466 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800467 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700468 return handleImsGetServiceCommand();
469 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800470 case IMS_CLEAR_SERVICE_OVERRIDE: {
471 return handleImsClearCarrierServiceCommand();
472 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800473 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700474 return handleEnableIms();
475 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800476 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700477 return handleDisableIms();
478 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700479 case IMS_CEP: {
480 return handleCepChange();
481 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700482 }
483
484 return -1;
485 }
486
Shuo Qianf5125122019-12-16 17:03:07 -0800487 private int handleDataTestModeCommand() {
488 PrintWriter errPw = getErrPrintWriter();
489 String arg = getNextArgRequired();
490 if (arg == null) {
491 onHelpDataTestMode();
492 return 0;
493 }
494 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800495 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800496 try {
497 mInterface.enableDataConnectivity();
498 } catch (RemoteException ex) {
499 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
500 errPw.println("Exception: " + ex.getMessage());
501 return -1;
502 }
503 break;
504 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800505 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800506 try {
507 mInterface.disableDataConnectivity();
508 } catch (RemoteException ex) {
509 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
510 errPw.println("Exception: " + ex.getMessage());
511 return -1;
512 }
513 break;
514 }
515 default:
516 onHelpDataTestMode();
517 break;
518 }
519 return 0;
520 }
521
Shuo Qianccbaf742021-02-22 18:32:21 -0800522 private int handleEmergencyCallbackModeCommand() {
523 PrintWriter errPw = getErrPrintWriter();
524 try {
525 mInterface.startEmergencyCallbackMode();
526 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
527 } catch (RemoteException ex) {
528 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
529 errPw.println("Exception: " + ex.getMessage());
530 return -1;
531 }
532 return 0;
533 }
534
sqian9d4df8b2019-01-15 18:32:07 -0800535 private int handleEmergencyNumberTestModeCommand() {
536 PrintWriter errPw = getErrPrintWriter();
537 String opt = getNextOption();
538 if (opt == null) {
539 onHelpEmergencyNumber();
540 return 0;
541 }
542
543 switch (opt) {
544 case "-a": {
545 String emergencyNumberCmd = getNextArgRequired();
546 if (emergencyNumberCmd == null
547 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700548 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800549 + " to be specified after -a in the command ");
550 return -1;
551 }
552 try {
553 mInterface.updateEmergencyNumberListTestMode(
554 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
555 new EmergencyNumber(emergencyNumberCmd, "", "",
556 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
557 new ArrayList<String>(),
558 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
559 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
560 } catch (RemoteException ex) {
561 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
562 + ", error " + ex.getMessage());
563 errPw.println("Exception: " + ex.getMessage());
564 return -1;
565 }
566 break;
567 }
568 case "-c": {
569 try {
570 mInterface.updateEmergencyNumberListTestMode(
571 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
572 } catch (RemoteException ex) {
573 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
574 errPw.println("Exception: " + ex.getMessage());
575 return -1;
576 }
577 break;
578 }
579 case "-r": {
580 String emergencyNumberCmd = getNextArgRequired();
581 if (emergencyNumberCmd == null
582 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700583 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800584 + " to be specified after -r in the command ");
585 return -1;
586 }
587 try {
588 mInterface.updateEmergencyNumberListTestMode(
589 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
590 new EmergencyNumber(emergencyNumberCmd, "", "",
591 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
592 new ArrayList<String>(),
593 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
594 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
595 } catch (RemoteException ex) {
596 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
597 + ", error " + ex.getMessage());
598 errPw.println("Exception: " + ex.getMessage());
599 return -1;
600 }
601 break;
602 }
603 case "-p": {
604 try {
605 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
606 } catch (RemoteException ex) {
607 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
608 errPw.println("Exception: " + ex.getMessage());
609 return -1;
610 }
611 break;
612 }
613 default:
614 onHelpEmergencyNumber();
615 break;
616 }
617 return 0;
618 }
619
Hall Liud892bec2018-11-30 14:51:45 -0800620 private int handleNumberVerificationCommand() {
621 String arg = getNextArg();
622 if (arg == null) {
623 onHelpNumberVerification();
624 return 0;
625 }
626
Hall Liuca5af3a2018-12-04 16:58:23 -0800627 if (!checkShellUid()) {
628 return -1;
629 }
630
Hall Liud892bec2018-11-30 14:51:45 -0800631 switch (arg) {
632 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800633 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
634 return 0;
635 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800636 case NUMBER_VERIFICATION_FAKE_CALL: {
637 boolean val = NumberVerificationManager.getInstance()
638 .checkIncomingCall(getNextArg());
639 getOutPrintWriter().println(val ? "1" : "0");
640 return 0;
641 }
Hall Liud892bec2018-11-30 14:51:45 -0800642 }
643
644 return -1;
645 }
646
Tyler Gunn92479152021-01-20 16:30:10 -0800647 private int handleD2dCommand() {
648 String arg = getNextArg();
649 if (arg == null) {
650 onHelpD2D();
651 return 0;
652 }
653
654 switch (arg) {
655 case D2D_SEND: {
656 return handleD2dSendCommand();
657 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800658 case D2D_TRANSPORT: {
659 return handleD2dTransportCommand();
660 }
Tyler Gunn92479152021-01-20 16:30:10 -0800661 }
662
663 return -1;
664 }
665
666 private int handleD2dSendCommand() {
667 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800668 int messageType = -1;
669 int messageValue = -1;
670
Tyler Gunn92479152021-01-20 16:30:10 -0800671 String arg = getNextArg();
672 if (arg == null) {
673 onHelpD2D();
674 return 0;
675 }
676 try {
677 messageType = Integer.parseInt(arg);
678 } catch (NumberFormatException e) {
679 errPw.println("message type must be a valid integer");
680 return -1;
681 }
682
683 arg = getNextArg();
684 if (arg == null) {
685 onHelpD2D();
686 return 0;
687 }
688 try {
689 messageValue = Integer.parseInt(arg);
690 } catch (NumberFormatException e) {
691 errPw.println("message value must be a valid integer");
692 return -1;
693 }
694
695 try {
696 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
697 } catch (RemoteException e) {
698 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
699 errPw.println("Exception: " + e.getMessage());
700 return -1;
701 }
702
703 return 0;
704 }
705
Tyler Gunnbabbda02021-02-10 11:05:02 -0800706 private int handleD2dTransportCommand() {
707 PrintWriter errPw = getErrPrintWriter();
708
709 String arg = getNextArg();
710 if (arg == null) {
711 onHelpD2D();
712 return 0;
713 }
714
715 try {
716 mInterface.setActiveDeviceToDeviceTransport(arg);
717 } catch (RemoteException e) {
718 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
719 errPw.println("Exception: " + e.getMessage());
720 return -1;
721 }
722 return 0;
723 }
724
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700725 // ims set-ims-service
726 private int handleImsSetServiceCommand() {
727 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700728 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700729 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800730 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700731
732 String opt;
733 while ((opt = getNextOption()) != null) {
734 switch (opt) {
735 case "-s": {
736 try {
737 slotId = Integer.parseInt(getNextArgRequired());
738 } catch (NumberFormatException e) {
739 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
740 return -1;
741 }
742 break;
743 }
744 case "-c": {
745 isCarrierService = true;
746 break;
747 }
748 case "-d": {
749 isCarrierService = false;
750 break;
751 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800752 case "-f": {
753 String featureString = getNextArgRequired();
754 String[] features = featureString.split(",");
755 for (int i = 0; i < features.length; i++) {
756 try {
757 Integer result = Integer.parseInt(features[i]);
758 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
759 || result >= ImsFeature.FEATURE_MAX) {
760 errPw.println("ims set-ims-service -f " + result
761 + " is an invalid feature.");
762 return -1;
763 }
764 featuresList.add(result);
765 } catch (NumberFormatException e) {
766 errPw.println("ims set-ims-service -f tried to parse " + features[i]
767 + " as an integer.");
768 return -1;
769 }
770 }
771 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700772 }
773 }
774 // Mandatory param, either -c or -d
775 if (isCarrierService == null) {
776 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
777 return -1;
778 }
779
780 String packageName = getNextArg();
781
782 try {
783 if (packageName == null) {
784 packageName = "";
785 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800786 int[] featureArray = new int[featuresList.size()];
787 for (int i = 0; i < featuresList.size(); i++) {
788 featureArray[i] = featuresList.get(i);
789 }
790 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
791 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700792 if (VDBG) {
793 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800794 + (isCarrierService ? "-c " : "-d ")
795 + "-f " + featuresList + " "
796 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700797 }
798 getOutPrintWriter().println(result);
799 } catch (RemoteException e) {
800 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800801 + (isCarrierService ? "-c " : "-d ")
802 + "-f " + featuresList + " "
803 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700804 errPw.println("Exception: " + e.getMessage());
805 return -1;
806 }
807 return 0;
808 }
809
Brad Ebinger999d3302020-11-25 14:31:39 -0800810 // ims clear-ims-service-override
811 private int handleImsClearCarrierServiceCommand() {
812 PrintWriter errPw = getErrPrintWriter();
813 int slotId = getDefaultSlot();
814
815 String opt;
816 while ((opt = getNextOption()) != null) {
817 switch (opt) {
818 case "-s": {
819 try {
820 slotId = Integer.parseInt(getNextArgRequired());
821 } catch (NumberFormatException e) {
822 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
823 return -1;
824 }
825 break;
826 }
827 }
828 }
829
830 try {
831 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
832 if (VDBG) {
833 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
834 + ", result=" + result);
835 }
836 getOutPrintWriter().println(result);
837 } catch (RemoteException e) {
838 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
839 + ", error" + e.getMessage());
840 errPw.println("Exception: " + e.getMessage());
841 return -1;
842 }
843 return 0;
844 }
845
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700846 // ims get-ims-service
847 private int handleImsGetServiceCommand() {
848 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700849 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700850 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800851 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700852
853 String opt;
854 while ((opt = getNextOption()) != null) {
855 switch (opt) {
856 case "-s": {
857 try {
858 slotId = Integer.parseInt(getNextArgRequired());
859 } catch (NumberFormatException e) {
860 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
861 return -1;
862 }
863 break;
864 }
865 case "-c": {
866 isCarrierService = true;
867 break;
868 }
869 case "-d": {
870 isCarrierService = false;
871 break;
872 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800873 case "-f": {
874 try {
875 featureType = Integer.parseInt(getNextArg());
876 } catch (NumberFormatException e) {
877 errPw.println("ims get-ims-service -f requires valid integer as feature.");
878 return -1;
879 }
880 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
881 || featureType >= ImsFeature.FEATURE_MAX) {
882 errPw.println("ims get-ims-service -f invalid feature.");
883 return -1;
884 }
885 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700886 }
887 }
888 // Mandatory param, either -c or -d
889 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800890 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700891 return -1;
892 }
893
894 String result;
895 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800896 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700897 } catch (RemoteException e) {
898 return -1;
899 }
900 if (VDBG) {
901 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800902 + (isCarrierService ? "-c " : "-d ")
903 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
904 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700905 }
906 getOutPrintWriter().println(result);
907 return 0;
908 }
909
910 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700911 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700912 String opt;
913 while ((opt = getNextOption()) != null) {
914 switch (opt) {
915 case "-s": {
916 try {
917 slotId = Integer.parseInt(getNextArgRequired());
918 } catch (NumberFormatException e) {
919 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
920 return -1;
921 }
922 break;
923 }
924 }
925 }
926 try {
927 mInterface.enableIms(slotId);
928 } catch (RemoteException e) {
929 return -1;
930 }
931 if (VDBG) {
932 Log.v(LOG_TAG, "ims enable -s " + slotId);
933 }
934 return 0;
935 }
936
937 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700938 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700939 String opt;
940 while ((opt = getNextOption()) != null) {
941 switch (opt) {
942 case "-s": {
943 try {
944 slotId = Integer.parseInt(getNextArgRequired());
945 } catch (NumberFormatException e) {
946 getErrPrintWriter().println(
947 "ims disable requires an integer as a SLOT_ID.");
948 return -1;
949 }
950 break;
951 }
952 }
953 }
954 try {
955 mInterface.disableIms(slotId);
956 } catch (RemoteException e) {
957 return -1;
958 }
959 if (VDBG) {
960 Log.v(LOG_TAG, "ims disable -s " + slotId);
961 }
962 return 0;
963 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700964
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700965 private int handleCepChange() {
966 Log.i(LOG_TAG, "handleCepChange");
967 String opt = getNextArg();
968 if (opt == null) {
969 return -1;
970 }
971 boolean isCepEnabled = opt.equals("enable");
972
973 try {
974 mInterface.setCepEnabled(isCepEnabled);
975 } catch (RemoteException e) {
976 return -1;
977 }
978 return 0;
979 }
980
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700981 private int getDefaultSlot() {
982 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
983 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
984 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
985 // If there is no default, default to slot 0.
986 slotId = DEFAULT_PHONE_ID;
987 }
988 return slotId;
989 }
sqian2fff4a32018-11-05 14:18:37 -0800990
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100991 // Parse options related to Carrier Config Commands.
992 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100993 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100994 CcOptionParseResult result = new CcOptionParseResult();
995 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
996 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100997
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100998 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100999 while ((opt = getNextOption()) != null) {
1000 switch (opt) {
1001 case "-s": {
1002 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001003 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1004 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1005 errPw.println(tag + "No valid subscription found.");
1006 return null;
1007 }
1008
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001009 } catch (IllegalArgumentException e) {
1010 // Missing slot id
1011 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001012 return null;
1013 }
1014 break;
1015 }
1016 case "-p": {
1017 if (allowOptionPersistent) {
1018 result.mPersistent = true;
1019 } else {
1020 errPw.println(tag + "Unexpected option " + opt);
1021 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001022 }
1023 break;
1024 }
1025 default: {
1026 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001027 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001028 }
1029 }
1030 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001031 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001032 }
1033
1034 private int slotStringToSubId(String tag, String slotString) {
1035 int slotId = -1;
1036 try {
1037 slotId = Integer.parseInt(slotString);
1038 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001039 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1040 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1041 }
1042
1043 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001044 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1045 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1046 }
1047
Qiong Liuf25799b2020-09-10 10:13:46 +08001048 Phone phone = PhoneFactory.getPhone(slotId);
1049 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001050 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1051 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1052 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001053 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001054 }
1055
Hall Liud892bec2018-11-30 14:51:45 -08001056 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001057 // adb can run as root or as shell, depending on whether the device is rooted.
1058 return Binder.getCallingUid() == Process.SHELL_UID
1059 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001060 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001061
1062 private int handleCcCommand() {
1063 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1064 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001065 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001066 getErrPrintWriter().println("cc: Permission denied.");
1067 return -1;
1068 }
1069
1070 String arg = getNextArg();
1071 if (arg == null) {
1072 onHelpCc();
1073 return 0;
1074 }
1075
1076 switch (arg) {
1077 case CC_GET_VALUE: {
1078 return handleCcGetValue();
1079 }
1080 case CC_SET_VALUE: {
1081 return handleCcSetValue();
1082 }
1083 case CC_CLEAR_VALUES: {
1084 return handleCcClearValues();
1085 }
1086 default: {
1087 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1088 }
1089 }
1090 return -1;
1091 }
1092
1093 // cc get-value
1094 private int handleCcGetValue() {
1095 PrintWriter errPw = getErrPrintWriter();
1096 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1097 String key = null;
1098
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001099 // Parse all options
1100 CcOptionParseResult options = parseCcOptions(tag, false);
1101 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001102 return -1;
1103 }
1104
1105 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001106 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001107 if (bundle == 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 key = getNextArg();
1114 if (key != null) {
1115 // A key was provided. Verify if it is a valid key
1116 if (!bundle.containsKey(key)) {
1117 errPw.println(tag + key + " is not a valid key.");
1118 return -1;
1119 }
1120
1121 // Print the carrier config value for key.
1122 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1123 } else {
1124 // No key provided. Show all values.
1125 // Iterate over a sorted list of all carrier config keys and print them.
1126 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1127 for (String k : sortedSet) {
1128 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1129 }
1130 }
1131 return 0;
1132 }
1133
1134 // cc set-value
1135 private int handleCcSetValue() {
1136 PrintWriter errPw = getErrPrintWriter();
1137 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1138
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001139 // Parse all options
1140 CcOptionParseResult options = parseCcOptions(tag, true);
1141 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001142 return -1;
1143 }
1144
1145 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001146 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001147 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001148 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001149 return -1;
1150 }
1151
1152 // Get the key.
1153 String key = getNextArg();
1154 if (key == null || key.equals("")) {
1155 errPw.println(tag + "KEY is missing");
1156 return -1;
1157 }
1158
1159 // Verify if the key is valid
1160 if (!originalValues.containsKey(key)) {
1161 errPw.println(tag + key + " is not a valid key.");
1162 return -1;
1163 }
1164
1165 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1166 ArrayList<String> valueList = new ArrayList<String>();
1167 while (peekNextArg() != null) {
1168 valueList.add(getNextArg());
1169 }
1170
1171 // Find the type of the carrier config value
1172 CcType type = getType(tag, key, originalValues);
1173 if (type == CcType.UNKNOWN) {
1174 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1175 return -1;
1176 }
1177
1178 // Create an override bundle containing the key and value that should be overriden.
1179 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1180 if (overrideBundle == null) {
1181 return -1;
1182 }
1183
1184 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001185 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001186
1187 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001188 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001189 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001190 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001191 return -1;
1192 }
1193
1194 // Print the original and new value.
1195 String originalValueString = ccValueToString(key, type, originalValues);
1196 String newValueString = ccValueToString(key, type, newValues);
1197 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1198 getOutPrintWriter().println("New value: \n" + newValueString);
1199
1200 return 0;
1201 }
1202
1203 // cc clear-values
1204 private int handleCcClearValues() {
1205 PrintWriter errPw = getErrPrintWriter();
1206 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1207
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001208 // Parse all options
1209 CcOptionParseResult options = parseCcOptions(tag, false);
1210 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001211 return -1;
1212 }
1213
1214 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001215 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001216 getOutPrintWriter()
1217 .println("All previously set carrier config override values has been cleared");
1218 return 0;
1219 }
1220
1221 private CcType getType(String tag, String key, PersistableBundle bundle) {
1222 // Find the type by checking the type of the current value stored in the bundle.
1223 Object value = bundle.get(key);
1224
1225 if (CC_TYPE_MAP.containsKey(key)) {
1226 return CC_TYPE_MAP.get(key);
1227 } else if (value != null) {
1228 if (value instanceof Boolean) {
1229 return CcType.BOOLEAN;
1230 } else if (value instanceof Double) {
1231 return CcType.DOUBLE;
1232 } else if (value instanceof double[]) {
1233 return CcType.DOUBLE_ARRAY;
1234 } else if (value instanceof Integer) {
1235 return CcType.INT;
1236 } else if (value instanceof int[]) {
1237 return CcType.INT_ARRAY;
1238 } else if (value instanceof Long) {
1239 return CcType.LONG;
1240 } else if (value instanceof long[]) {
1241 return CcType.LONG_ARRAY;
1242 } else if (value instanceof String) {
1243 return CcType.STRING;
1244 } else if (value instanceof String[]) {
1245 return CcType.STRING_ARRAY;
1246 }
1247 } else {
1248 // Current value was null and can therefore not be used in order to find the type.
1249 // Check the name of the key to infer the type. This check is not needed for primitive
1250 // data types (boolean, double, int and long), since they can not be null.
1251 if (key.endsWith("double_array")) {
1252 return CcType.DOUBLE_ARRAY;
1253 }
1254 if (key.endsWith("int_array")) {
1255 return CcType.INT_ARRAY;
1256 }
1257 if (key.endsWith("long_array")) {
1258 return CcType.LONG_ARRAY;
1259 }
1260 if (key.endsWith("string")) {
1261 return CcType.STRING;
1262 }
1263 if (key.endsWith("string_array") || key.endsWith("strings")) {
1264 return CcType.STRING_ARRAY;
1265 }
1266 }
1267
1268 // Not possible to infer the type by looking at the current value or the key.
1269 PrintWriter errPw = getErrPrintWriter();
1270 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1271 return CcType.UNKNOWN;
1272 }
1273
1274 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1275 String result;
1276 StringBuilder valueString = new StringBuilder();
1277 String typeString = type.toString();
1278 Object value = bundle.get(key);
1279
1280 if (value == null) {
1281 valueString.append("null");
1282 } else {
1283 switch (type) {
1284 case DOUBLE_ARRAY: {
1285 // Format the string representation of the int array as value1 value2......
1286 double[] valueArray = (double[]) value;
1287 for (int i = 0; i < valueArray.length; i++) {
1288 if (i != 0) {
1289 valueString.append(" ");
1290 }
1291 valueString.append(valueArray[i]);
1292 }
1293 break;
1294 }
1295 case INT_ARRAY: {
1296 // Format the string representation of the int array as value1 value2......
1297 int[] valueArray = (int[]) value;
1298 for (int i = 0; i < valueArray.length; i++) {
1299 if (i != 0) {
1300 valueString.append(" ");
1301 }
1302 valueString.append(valueArray[i]);
1303 }
1304 break;
1305 }
1306 case LONG_ARRAY: {
1307 // Format the string representation of the int array as value1 value2......
1308 long[] valueArray = (long[]) value;
1309 for (int i = 0; i < valueArray.length; i++) {
1310 if (i != 0) {
1311 valueString.append(" ");
1312 }
1313 valueString.append(valueArray[i]);
1314 }
1315 break;
1316 }
1317 case STRING: {
1318 valueString.append("\"" + value.toString() + "\"");
1319 break;
1320 }
1321 case STRING_ARRAY: {
1322 // Format the string representation of the string array as "value1" "value2"....
1323 String[] valueArray = (String[]) value;
1324 for (int i = 0; i < valueArray.length; i++) {
1325 if (i != 0) {
1326 valueString.append(" ");
1327 }
1328 if (valueArray[i] != null) {
1329 valueString.append("\"" + valueArray[i] + "\"");
1330 } else {
1331 valueString.append("null");
1332 }
1333 }
1334 break;
1335 }
1336 default: {
1337 valueString.append(value.toString());
1338 }
1339 }
1340 }
1341 return String.format("%-70s %-15s %s", key, typeString, valueString);
1342 }
1343
1344 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1345 ArrayList<String> valueList) {
1346 PrintWriter errPw = getErrPrintWriter();
1347 PersistableBundle bundle = new PersistableBundle();
1348
1349 // First verify that a valid number of values has been provided for the type.
1350 switch (type) {
1351 case BOOLEAN:
1352 case DOUBLE:
1353 case INT:
1354 case LONG: {
1355 if (valueList.size() != 1) {
1356 errPw.println(tag + "Expected 1 value for type " + type
1357 + ". Found: " + valueList.size());
1358 return null;
1359 }
1360 break;
1361 }
1362 case STRING: {
1363 if (valueList.size() > 1) {
1364 errPw.println(tag + "Expected 0 or 1 values for type " + type
1365 + ". Found: " + valueList.size());
1366 return null;
1367 }
1368 break;
1369 }
1370 }
1371
1372 // Parse the value according to type and add it to the Bundle.
1373 switch (type) {
1374 case BOOLEAN: {
1375 if ("true".equalsIgnoreCase(valueList.get(0))) {
1376 bundle.putBoolean(key, true);
1377 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1378 bundle.putBoolean(key, false);
1379 } else {
1380 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1381 return null;
1382 }
1383 break;
1384 }
1385 case DOUBLE: {
1386 try {
1387 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1388 } catch (NumberFormatException nfe) {
1389 // Not a valid double
1390 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1391 return null;
1392 }
1393 break;
1394 }
1395 case DOUBLE_ARRAY: {
1396 double[] valueDoubleArray = null;
1397 if (valueList.size() > 0) {
1398 valueDoubleArray = new double[valueList.size()];
1399 for (int i = 0; i < valueList.size(); i++) {
1400 try {
1401 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1402 } catch (NumberFormatException nfe) {
1403 // Not a valid double
1404 errPw.println(
1405 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1406 return null;
1407 }
1408 }
1409 }
1410 bundle.putDoubleArray(key, valueDoubleArray);
1411 break;
1412 }
1413 case INT: {
1414 try {
1415 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1416 } catch (NumberFormatException nfe) {
1417 // Not a valid integer
1418 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1419 return null;
1420 }
1421 break;
1422 }
1423 case INT_ARRAY: {
1424 int[] valueIntArray = null;
1425 if (valueList.size() > 0) {
1426 valueIntArray = new int[valueList.size()];
1427 for (int i = 0; i < valueList.size(); i++) {
1428 try {
1429 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1430 } catch (NumberFormatException nfe) {
1431 // Not a valid integer
1432 errPw.println(tag
1433 + "Unable to parse " + valueList.get(i) + " as an integer.");
1434 return null;
1435 }
1436 }
1437 }
1438 bundle.putIntArray(key, valueIntArray);
1439 break;
1440 }
1441 case LONG: {
1442 try {
1443 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1444 } catch (NumberFormatException nfe) {
1445 // Not a valid long
1446 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1447 return null;
1448 }
1449 break;
1450 }
1451 case LONG_ARRAY: {
1452 long[] valueLongArray = null;
1453 if (valueList.size() > 0) {
1454 valueLongArray = new long[valueList.size()];
1455 for (int i = 0; i < valueList.size(); i++) {
1456 try {
1457 valueLongArray[i] = Long.parseLong(valueList.get(i));
1458 } catch (NumberFormatException nfe) {
1459 // Not a valid long
1460 errPw.println(
1461 tag + "Unable to parse " + valueList.get(i) + " as a long");
1462 return null;
1463 }
1464 }
1465 }
1466 bundle.putLongArray(key, valueLongArray);
1467 break;
1468 }
1469 case STRING: {
1470 String value = null;
1471 if (valueList.size() > 0) {
1472 value = valueList.get(0);
1473 }
1474 bundle.putString(key, value);
1475 break;
1476 }
1477 case STRING_ARRAY: {
1478 String[] valueStringArray = null;
1479 if (valueList.size() > 0) {
1480 valueStringArray = new String[valueList.size()];
1481 valueList.toArray(valueStringArray);
1482 }
1483 bundle.putStringArray(key, valueStringArray);
1484 break;
1485 }
1486 }
1487 return bundle;
1488 }
Shuo Qian489d9282020-07-09 11:30:03 -07001489
1490 private int handleEndBlockSuppressionCommand() {
1491 if (!checkShellUid()) {
1492 return -1;
1493 }
1494
1495 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1496 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1497 }
1498 return 0;
1499 }
Hui Wang641e81c2020-10-12 12:14:23 -07001500
Michele Berionne54af4632020-12-28 20:23:16 +00001501 private int handleRestartModemCommand() {
1502 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1503 // non user build.
1504 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1505 getErrPrintWriter().println("RestartModem: Permission denied.");
1506 return -1;
1507 }
1508
1509 boolean result = TelephonyManager.getDefault().rebootRadio();
1510 getOutPrintWriter().println(result);
1511
1512 return result ? 0 : -1;
1513 }
1514
Michele Berionne5e411512020-11-13 02:36:59 +00001515 private int handleUnattendedReboot() {
1516 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1517 // non user build.
1518 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1519 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1520 return -1;
1521 }
1522
1523 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1524 getOutPrintWriter().println("result: " + result);
1525
1526 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1527 }
1528
Hui Wang641e81c2020-10-12 12:14:23 -07001529 private int handleGbaCommand() {
1530 String arg = getNextArg();
1531 if (arg == null) {
1532 onHelpGba();
1533 return 0;
1534 }
1535
1536 switch (arg) {
1537 case GBA_SET_SERVICE: {
1538 return handleGbaSetServiceCommand();
1539 }
1540 case GBA_GET_SERVICE: {
1541 return handleGbaGetServiceCommand();
1542 }
1543 case GBA_SET_RELEASE_TIME: {
1544 return handleGbaSetReleaseCommand();
1545 }
1546 case GBA_GET_RELEASE_TIME: {
1547 return handleGbaGetReleaseCommand();
1548 }
1549 }
1550
1551 return -1;
1552 }
1553
1554 private int getSubId(String cmd) {
1555 int slotId = getDefaultSlot();
1556 String opt = getNextOption();
1557 if (opt != null && opt.equals("-s")) {
1558 try {
1559 slotId = Integer.parseInt(getNextArgRequired());
1560 } catch (NumberFormatException e) {
1561 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1562 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1563 }
1564 }
1565 int[] subIds = SubscriptionManager.getSubId(slotId);
1566 return subIds[0];
1567 }
1568
1569 private int handleGbaSetServiceCommand() {
1570 int subId = getSubId("gba set-service");
1571 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1572 return -1;
1573 }
1574
1575 String packageName = getNextArg();
1576 try {
1577 if (packageName == null) {
1578 packageName = "";
1579 }
1580 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1581 if (VDBG) {
1582 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1583 + packageName + ", result=" + result);
1584 }
1585 getOutPrintWriter().println(result);
1586 } catch (RemoteException e) {
1587 Log.w(LOG_TAG, "gba set-service " + subId + " "
1588 + packageName + ", error" + e.getMessage());
1589 getErrPrintWriter().println("Exception: " + e.getMessage());
1590 return -1;
1591 }
1592 return 0;
1593 }
1594
1595 private int handleGbaGetServiceCommand() {
1596 String result;
1597
1598 int subId = getSubId("gba get-service");
1599 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1600 return -1;
1601 }
1602
1603 try {
1604 result = mInterface.getBoundGbaService(subId);
1605 } catch (RemoteException e) {
1606 return -1;
1607 }
1608 if (VDBG) {
1609 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1610 }
1611 getOutPrintWriter().println(result);
1612 return 0;
1613 }
1614
1615 private int handleGbaSetReleaseCommand() {
1616 //the release time value could be -1
1617 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1618 : SubscriptionManager.getDefaultSubscriptionId();
1619 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1620 return -1;
1621 }
1622
1623 String intervalStr = getNextArg();
1624 if (intervalStr == null) {
1625 return -1;
1626 }
1627
1628 try {
1629 int interval = Integer.parseInt(intervalStr);
1630 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1631 if (VDBG) {
1632 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1633 + intervalStr + ", result=" + result);
1634 }
1635 getOutPrintWriter().println(result);
1636 } catch (NumberFormatException | RemoteException e) {
1637 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1638 + intervalStr + ", error" + e.getMessage());
1639 getErrPrintWriter().println("Exception: " + e.getMessage());
1640 return -1;
1641 }
1642 return 0;
1643 }
1644
1645 private int handleGbaGetReleaseCommand() {
1646 int subId = getSubId("gba get-release");
1647 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1648 return -1;
1649 }
1650
1651 int result = 0;
1652 try {
1653 result = mInterface.getGbaReleaseTime(subId);
1654 } catch (RemoteException e) {
1655 return -1;
1656 }
1657 if (VDBG) {
1658 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1659 }
1660 getOutPrintWriter().println(result);
1661 return 0;
1662 }
Hui Wang761a6682020-10-31 05:12:53 +00001663
1664 private int handleSingleRegistrationConfigCommand() {
1665 String arg = getNextArg();
1666 if (arg == null) {
1667 onHelpSrc();
1668 return 0;
1669 }
1670
1671 switch (arg) {
1672 case SRC_SET_DEVICE_ENABLED: {
1673 return handleSrcSetDeviceEnabledCommand();
1674 }
1675 case SRC_GET_DEVICE_ENABLED: {
1676 return handleSrcGetDeviceEnabledCommand();
1677 }
1678 case SRC_SET_CARRIER_ENABLED: {
1679 return handleSrcSetCarrierEnabledCommand();
1680 }
1681 case SRC_GET_CARRIER_ENABLED: {
1682 return handleSrcGetCarrierEnabledCommand();
1683 }
1684 }
1685
1686 return -1;
1687 }
1688
James.cf Linbcdf8b32021-01-14 16:44:13 +08001689 private int handleRcsUceCommand() {
1690 String arg = getNextArg();
1691 if (arg == null) {
1692 Log.w(LOG_TAG, "cannot get uce parameter");
1693 return -1;
1694 }
1695
1696 switch (arg) {
1697 case UCE_REMOVE_EAB_CONTACT:
1698 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001699 case UCE_GET_EAB_CONTACT:
1700 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001701 case UCE_GET_DEVICE_ENABLED:
1702 return handleUceGetDeviceEnabledCommand();
1703 case UCE_SET_DEVICE_ENABLED:
1704 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001705 }
1706 return -1;
1707 }
1708
1709 private int handleRemovingEabContactCommand() {
1710 int subId = getSubId("uce remove-eab-contact");
1711 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1712 return -1;
1713 }
1714
1715 String phoneNumber = getNextArgRequired();
1716 if (TextUtils.isEmpty(phoneNumber)) {
1717 return -1;
1718 }
1719 int result = 0;
1720 try {
1721 result = mInterface.removeContactFromEab(subId, phoneNumber);
1722 } catch (RemoteException e) {
1723 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1724 getErrPrintWriter().println("Exception: " + e.getMessage());
1725 return -1;
1726 }
1727
1728 if (VDBG) {
1729 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1730 }
calvinpan293ea1b2021-02-04 17:52:13 +08001731 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001732 }
1733
calvinpane4a8a1d2021-01-25 13:51:18 +08001734 private int handleGettingEabContactCommand() {
1735 String phoneNumber = getNextArgRequired();
1736 if (TextUtils.isEmpty(phoneNumber)) {
1737 return -1;
1738 }
1739 String result = "";
1740 try {
1741 result = mInterface.getContactFromEab(phoneNumber);
1742
1743 } catch (RemoteException e) {
1744 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1745 getErrPrintWriter().println("Exception: " + e.getMessage());
1746 return -1;
1747 }
1748
1749 if (VDBG) {
1750 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1751 }
calvinpan293ea1b2021-02-04 17:52:13 +08001752 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001753 return 0;
1754 }
1755
1756 private int handleUceGetDeviceEnabledCommand() {
1757 boolean result = false;
1758 try {
1759 result = mInterface.getDeviceUceEnabled();
1760 } catch (RemoteException e) {
1761 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1762 return -1;
1763 }
1764 if (VDBG) {
1765 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1766 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001767 getOutPrintWriter().println(result);
1768 return 0;
1769 }
1770
James.cf Lin4b784aa2021-01-31 03:25:15 +08001771 private int handleUceSetDeviceEnabledCommand() {
1772 String enabledStr = getNextArg();
1773 if (TextUtils.isEmpty(enabledStr)) {
1774 return -1;
1775 }
1776
1777 try {
1778 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1779 mInterface.setDeviceUceEnabled(isEnabled);
1780 if (VDBG) {
1781 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1782 }
1783 } catch (NumberFormatException | RemoteException e) {
1784 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1785 getErrPrintWriter().println("Exception: " + e.getMessage());
1786 return -1;
1787 }
1788 return 0;
1789 }
1790
Hui Wang761a6682020-10-31 05:12:53 +00001791 private int handleSrcSetDeviceEnabledCommand() {
1792 String enabledStr = getNextArg();
1793 if (enabledStr == null) {
1794 return -1;
1795 }
1796
1797 try {
1798 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1799 if (VDBG) {
1800 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1801 }
1802 getOutPrintWriter().println("Done");
1803 } catch (NumberFormatException | RemoteException e) {
1804 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1805 getErrPrintWriter().println("Exception: " + e.getMessage());
1806 return -1;
1807 }
1808 return 0;
1809 }
1810
1811 private int handleSrcGetDeviceEnabledCommand() {
1812 boolean result = false;
1813 try {
1814 result = mInterface.getDeviceSingleRegistrationEnabled();
1815 } catch (RemoteException e) {
1816 return -1;
1817 }
1818 if (VDBG) {
1819 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1820 }
1821 getOutPrintWriter().println(result);
1822 return 0;
1823 }
1824
1825 private int handleSrcSetCarrierEnabledCommand() {
1826 //the release time value could be -1
1827 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1828 : SubscriptionManager.getDefaultSubscriptionId();
1829 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1830 return -1;
1831 }
1832
1833 String enabledStr = getNextArg();
1834 if (enabledStr == null) {
1835 return -1;
1836 }
1837
1838 try {
1839 boolean result =
1840 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1841 if (VDBG) {
1842 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1843 + enabledStr + ", result=" + result);
1844 }
1845 getOutPrintWriter().println(result);
1846 } catch (NumberFormatException | RemoteException e) {
1847 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1848 + enabledStr + ", error" + e.getMessage());
1849 getErrPrintWriter().println("Exception: " + e.getMessage());
1850 return -1;
1851 }
1852 return 0;
1853 }
1854
1855 private int handleSrcGetCarrierEnabledCommand() {
1856 int subId = getSubId("src get-carrier-enabled");
1857 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1858 return -1;
1859 }
1860
1861 boolean result = false;
1862 try {
1863 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1864 } catch (RemoteException e) {
1865 return -1;
1866 }
1867 if (VDBG) {
1868 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1869 }
1870 getOutPrintWriter().println(result);
1871 return 0;
1872 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001873
1874 private void onHelpCallComposer() {
1875 PrintWriter pw = getOutPrintWriter();
1876 pw.println("Call composer commands");
1877 pw.println(" callcomposer test-mode enable|disable|query");
1878 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1879 pw.println(" upload/download from carrier servers is disabled, and operations are");
1880 pw.println(" performed using emulated local files instead.");
1881 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1882 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1883 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08001884 pw.println(" callcomposer user-setting [subId] enable|disable|query");
1885 pw.println(" Enables or disables the user setting for call composer, as set by");
1886 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08001887 }
1888
1889 private int handleCallComposerCommand() {
1890 String arg = getNextArg();
1891 if (arg == null) {
1892 onHelpCallComposer();
1893 return 0;
1894 }
1895
1896 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1897 "MODIFY_PHONE_STATE required for call composer shell cmds");
1898 switch (arg) {
1899 case CALL_COMPOSER_TEST_MODE: {
1900 String enabledStr = getNextArg();
1901 if (ENABLE.equals(enabledStr)) {
1902 CallComposerPictureManager.sTestMode = true;
1903 } else if (DISABLE.equals(enabledStr)) {
1904 CallComposerPictureManager.sTestMode = false;
1905 } else if (QUERY.equals(enabledStr)) {
1906 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1907 } else {
1908 onHelpCallComposer();
1909 return 1;
1910 }
1911 break;
1912 }
1913 case CALL_COMPOSER_SIMULATE_CALL: {
1914 int subscriptionId = Integer.valueOf(getNextArg());
1915 String uuidString = getNextArg();
1916 UUID uuid = UUID.fromString(uuidString);
1917 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1918 Binder.withCleanCallingIdentity(() -> {
1919 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1920 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1921 });
1922 try {
1923 Uri uri = storageUriFuture.get();
1924 getOutPrintWriter().println(String.valueOf(uri));
1925 } catch (Exception e) {
1926 throw new RuntimeException(e);
1927 }
1928 break;
1929 }
Hall Liu7917ecf2021-02-23 12:22:31 -08001930 case CALL_COMPOSER_USER_SETTING: {
1931 try {
1932 int subscriptionId = Integer.valueOf(getNextArg());
1933 String enabledStr = getNextArg();
1934 if (ENABLE.equals(enabledStr)) {
1935 mInterface.setCallComposerStatus(subscriptionId,
1936 TelephonyManager.CALL_COMPOSER_STATUS_ON);
1937 } else if (DISABLE.equals(enabledStr)) {
1938 mInterface.setCallComposerStatus(subscriptionId,
1939 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
1940 } else if (QUERY.equals(enabledStr)) {
1941 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
1942 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
1943 } else {
1944 onHelpCallComposer();
1945 return 1;
1946 }
1947 } catch (RemoteException e) {
1948 e.printStackTrace(getOutPrintWriter());
1949 return 1;
1950 }
1951 break;
1952 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001953 }
1954
1955 return 0;
1956 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001957}