blob: ba8dec92c650ba8c0ff53ab0a991799831bca83f [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 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";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800117 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800118
James.cf Linbcdf8b32021-01-14 16:44:13 +0800119 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800120 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800121 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800122 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
123 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800124
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700125 // Take advantage of existing methods that already contain permissions checks when possible.
126 private final ITelephony mInterface;
127
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100128 private SubscriptionManager mSubscriptionManager;
129 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700130 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100131
132 private enum CcType {
133 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
134 STRING_ARRAY, UNKNOWN
135 }
136
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100137 private class CcOptionParseResult {
138 public int mSubId;
139 public boolean mPersistent;
140 }
141
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100142 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
143 // keys by looking at the end of the string which usually tells the type.
144 // For instance: "xxxx_string", "xxxx_string_array", etc.
145 // The carrier config keys in this map does not follow this convention. It is therefore not
146 // possible to infer the type for these keys by looking at the string.
147 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
148 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
157 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
158 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
159 CcType.STRING);
160 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
161 CcType.STRING_ARRAY);
162 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
163 CcType.STRING_ARRAY);
164 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
165 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
167 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
168 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
169 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
170 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
171 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
172 }
173 };
174
175 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700176 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100177 mCarrierConfigManager =
178 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
179 mSubscriptionManager = (SubscriptionManager)
180 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700181 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700182 }
183
184 @Override
185 public int onCommand(String cmd) {
186 if (cmd == null) {
187 return handleDefaultCommands(null);
188 }
189
190 switch (cmd) {
191 case IMS_SUBCOMMAND: {
192 return handleImsCommand();
193 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800194 case RCS_UCE_COMMAND:
195 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800196 case NUMBER_VERIFICATION_SUBCOMMAND:
197 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800198 case EMERGENCY_CALLBACK_MODE:
199 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800200 case EMERGENCY_NUMBER_TEST_MODE:
201 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100202 case CARRIER_CONFIG_SUBCOMMAND: {
203 return handleCcCommand();
204 }
Shuo Qianf5125122019-12-16 17:03:07 -0800205 case DATA_TEST_MODE:
206 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700207 case END_BLOCK_SUPPRESSION:
208 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700209 case GBA_SUBCOMMAND:
210 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800211 case D2D_SUBCOMMAND:
212 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000213 case SINGLE_REGISTATION_CONFIG:
214 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000215 case RESTART_MODEM:
216 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800217 case CALL_COMPOSER_SUBCOMMAND:
218 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000219 case UNATTENDED_REBOOT:
220 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700221 default: {
222 return handleDefaultCommands(cmd);
223 }
224 }
225 }
226
227 @Override
228 public void onHelp() {
229 PrintWriter pw = getOutPrintWriter();
230 pw.println("Telephony Commands:");
231 pw.println(" help");
232 pw.println(" Print this help text.");
233 pw.println(" ims");
234 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800235 pw.println(" uce");
236 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800237 pw.println(" emergency-number-test-mode");
238 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700239 pw.println(" end-block-suppression");
240 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800241 pw.println(" data");
242 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100243 pw.println(" cc");
244 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700245 pw.println(" gba");
246 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000247 pw.println(" src");
248 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000249 pw.println(" restart-modem");
250 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000251 pw.println(" unattended-reboot");
252 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700253 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800254 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800255 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700256 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800257 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100258 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700259 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000260 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800261 onHelpD2D();
262 }
263
264 private void onHelpD2D() {
265 PrintWriter pw = getOutPrintWriter();
266 pw.println("D2D Comms Commands:");
267 pw.println(" d2d send TYPE VALUE");
268 pw.println(" Sends a D2D message of specified type and value.");
269 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
270 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
271 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
272 MESSAGE_CALL_AUDIO_CODEC));
273 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
274 + Communicator.messageToString(
275 MESSAGE_DEVICE_BATTERY_STATE));
276 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
277 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800278 pw.println(" d2d transport TYPE");
279 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
280 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700281 }
282
283 private void onHelpIms() {
284 PrintWriter pw = getOutPrintWriter();
285 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800286 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700287 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
288 pw.println(" ImsService. Options are:");
289 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
290 pw.println(" is specified, it will choose the default voice SIM slot.");
291 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
292 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800293 pw.println(" -f: Set the feature that this override if for, if no option is");
294 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700295 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
296 pw.println(" Gets the package name of the currently defined ImsService.");
297 pw.println(" Options are:");
298 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
299 pw.println(" is specified, it will choose the default voice SIM slot.");
300 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000301 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800302 pw.println(" -f: The feature type that the query will be requested for. If none is");
303 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800304 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
305 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
306 pw.println(" configuration overrides. Options are:");
307 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
308 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700309 pw.println(" ims enable [-s SLOT_ID]");
310 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
311 pw.println(" if none is specified.");
312 pw.println(" ims disable [-s SLOT_ID]");
313 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
314 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700315 pw.println(" ims conference-event-package [enable/disable]");
316 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700317 }
318
James.cf Linbcdf8b32021-01-14 16:44:13 +0800319 private void onHelpUce() {
320 PrintWriter pw = getOutPrintWriter();
321 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800322 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
323 pw.println(" Get the EAB contacts from the EAB database.");
324 pw.println(" Options are:");
325 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
326 pw.println(" Expected output format :");
327 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800328 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
329 pw.println(" Remove the EAB contacts from the EAB database.");
330 pw.println(" Options are:");
331 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
332 pw.println(" is specified, it will choose the default voice SIM slot.");
333 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800334 pw.println(" uce get-device-enabled");
335 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
336 pw.println(" uce set-device-enabled true|false");
337 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
338 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800339 }
340
Hall Liud892bec2018-11-30 14:51:45 -0800341 private void onHelpNumberVerification() {
342 PrintWriter pw = getOutPrintWriter();
343 pw.println("Number verification commands");
344 pw.println(" numverify override-package PACKAGE_NAME;");
345 pw.println(" Set the authorized package for number verification.");
346 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800347 pw.println(" numverify fake-call NUMBER;");
348 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
349 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800350 }
351
Shuo Qianf5125122019-12-16 17:03:07 -0800352 private void onHelpDataTestMode() {
353 PrintWriter pw = getOutPrintWriter();
354 pw.println("Mobile Data Test Mode Commands:");
355 pw.println(" data enable: enable mobile data connectivity");
356 pw.println(" data disable: disable mobile data connectivity");
357 }
358
sqian9d4df8b2019-01-15 18:32:07 -0800359 private void onHelpEmergencyNumber() {
360 PrintWriter pw = getOutPrintWriter();
361 pw.println("Emergency Number Test Mode Commands:");
362 pw.println(" emergency-number-test-mode ");
363 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
364 + " the test mode");
365 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700366 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800367 pw.println(" -c: clear the emergency number list in the test mode.");
368 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700369 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800370 pw.println(" -p: get the full emergency number list in the test mode.");
371 }
372
Shuo Qian489d9282020-07-09 11:30:03 -0700373 private void onHelpEndBlockSupperssion() {
374 PrintWriter pw = getOutPrintWriter();
375 pw.println("End Block Suppression command:");
376 pw.println(" end-block-suppression: disable suppressing blocking by contact");
377 pw.println(" with emergency services.");
378 }
379
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100380 private void onHelpCc() {
381 PrintWriter pw = getOutPrintWriter();
382 pw.println("Carrier Config Commands:");
383 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
384 pw.println(" Print carrier config values.");
385 pw.println(" Options are:");
386 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
387 pw.println(" is specified, it will choose the default voice SIM slot.");
388 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
389 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100390 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100391 pw.println(" Set carrier config KEY to NEW_VALUE.");
392 pw.println(" Options are:");
393 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
394 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100395 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100396 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
397 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
398 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
399 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
400 pw.println(" cc clear-values [-s SLOT_ID]");
401 pw.println(" Clear all carrier override values that has previously been set");
402 pw.println(" with set-value");
403 pw.println(" Options are:");
404 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
405 pw.println(" is specified, it will choose the default voice SIM slot.");
406 }
407
Hui Wang641e81c2020-10-12 12:14:23 -0700408 private void onHelpGba() {
409 PrintWriter pw = getOutPrintWriter();
410 pw.println("Gba Commands:");
411 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
412 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
413 pw.println(" Options are:");
414 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
415 pw.println(" is specified, it will choose the default voice SIM slot.");
416 pw.println(" gba get-service [-s SLOT_ID]");
417 pw.println(" Gets the package name of the currently defined GbaService.");
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 set-release [-s SLOT_ID] n");
422 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
423 pw.println(" Do not release/unbind if n is -1.");
424 pw.println(" Options are:");
425 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
426 pw.println(" is specified, it will choose the default voice SIM slot.");
427 pw.println(" gba get-release [-s SLOT_ID]");
428 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
429 pw.println(" Options are:");
430 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
431 pw.println(" is specified, it will choose the default voice SIM slot.");
432 }
433
Hui Wang761a6682020-10-31 05:12:53 +0000434 private void onHelpSrc() {
435 PrintWriter pw = getOutPrintWriter();
436 pw.println("RCS VoLTE Single Registration Config Commands:");
437 pw.println(" src set-device-enabled true|false|null");
438 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
439 pw.println(" The value could be true, false, or null(undefined).");
440 pw.println(" src get-device-enabled");
441 pw.println(" Gets the device config for RCS VoLTE single registration.");
442 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
443 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
444 pw.println(" The value could be true, false, or null(undefined).");
445 pw.println(" Options are:");
446 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
447 pw.println(" is specified, it will choose the default voice SIM slot.");
448 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
449 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
450 pw.println(" Options are:");
451 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
452 pw.println(" is specified, it will choose the default voice SIM slot.");
453 }
454
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700455 private int handleImsCommand() {
456 String arg = getNextArg();
457 if (arg == null) {
458 onHelpIms();
459 return 0;
460 }
461
462 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800463 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700464 return handleImsSetServiceCommand();
465 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800466 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700467 return handleImsGetServiceCommand();
468 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800469 case IMS_CLEAR_SERVICE_OVERRIDE: {
470 return handleImsClearCarrierServiceCommand();
471 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800472 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700473 return handleEnableIms();
474 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800475 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700476 return handleDisableIms();
477 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700478 case IMS_CEP: {
479 return handleCepChange();
480 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700481 }
482
483 return -1;
484 }
485
Shuo Qianf5125122019-12-16 17:03:07 -0800486 private int handleDataTestModeCommand() {
487 PrintWriter errPw = getErrPrintWriter();
488 String arg = getNextArgRequired();
489 if (arg == null) {
490 onHelpDataTestMode();
491 return 0;
492 }
493 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800494 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800495 try {
496 mInterface.enableDataConnectivity();
497 } catch (RemoteException ex) {
498 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
499 errPw.println("Exception: " + ex.getMessage());
500 return -1;
501 }
502 break;
503 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800504 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800505 try {
506 mInterface.disableDataConnectivity();
507 } catch (RemoteException ex) {
508 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
509 errPw.println("Exception: " + ex.getMessage());
510 return -1;
511 }
512 break;
513 }
514 default:
515 onHelpDataTestMode();
516 break;
517 }
518 return 0;
519 }
520
Shuo Qianccbaf742021-02-22 18:32:21 -0800521 private int handleEmergencyCallbackModeCommand() {
522 PrintWriter errPw = getErrPrintWriter();
523 try {
524 mInterface.startEmergencyCallbackMode();
525 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
526 } catch (RemoteException ex) {
527 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
528 errPw.println("Exception: " + ex.getMessage());
529 return -1;
530 }
531 return 0;
532 }
533
sqian9d4df8b2019-01-15 18:32:07 -0800534 private int handleEmergencyNumberTestModeCommand() {
535 PrintWriter errPw = getErrPrintWriter();
536 String opt = getNextOption();
537 if (opt == null) {
538 onHelpEmergencyNumber();
539 return 0;
540 }
541
542 switch (opt) {
543 case "-a": {
544 String emergencyNumberCmd = getNextArgRequired();
545 if (emergencyNumberCmd == null
546 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700547 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800548 + " to be specified after -a in the command ");
549 return -1;
550 }
551 try {
552 mInterface.updateEmergencyNumberListTestMode(
553 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
554 new EmergencyNumber(emergencyNumberCmd, "", "",
555 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
556 new ArrayList<String>(),
557 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
558 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
559 } catch (RemoteException ex) {
560 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
561 + ", error " + ex.getMessage());
562 errPw.println("Exception: " + ex.getMessage());
563 return -1;
564 }
565 break;
566 }
567 case "-c": {
568 try {
569 mInterface.updateEmergencyNumberListTestMode(
570 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
571 } catch (RemoteException ex) {
572 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
573 errPw.println("Exception: " + ex.getMessage());
574 return -1;
575 }
576 break;
577 }
578 case "-r": {
579 String emergencyNumberCmd = getNextArgRequired();
580 if (emergencyNumberCmd == null
581 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700582 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800583 + " to be specified after -r in the command ");
584 return -1;
585 }
586 try {
587 mInterface.updateEmergencyNumberListTestMode(
588 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
589 new EmergencyNumber(emergencyNumberCmd, "", "",
590 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
591 new ArrayList<String>(),
592 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
593 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
594 } catch (RemoteException ex) {
595 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
596 + ", error " + ex.getMessage());
597 errPw.println("Exception: " + ex.getMessage());
598 return -1;
599 }
600 break;
601 }
602 case "-p": {
603 try {
604 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
605 } catch (RemoteException ex) {
606 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
607 errPw.println("Exception: " + ex.getMessage());
608 return -1;
609 }
610 break;
611 }
612 default:
613 onHelpEmergencyNumber();
614 break;
615 }
616 return 0;
617 }
618
Hall Liud892bec2018-11-30 14:51:45 -0800619 private int handleNumberVerificationCommand() {
620 String arg = getNextArg();
621 if (arg == null) {
622 onHelpNumberVerification();
623 return 0;
624 }
625
Hall Liuca5af3a2018-12-04 16:58:23 -0800626 if (!checkShellUid()) {
627 return -1;
628 }
629
Hall Liud892bec2018-11-30 14:51:45 -0800630 switch (arg) {
631 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800632 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
633 return 0;
634 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800635 case NUMBER_VERIFICATION_FAKE_CALL: {
636 boolean val = NumberVerificationManager.getInstance()
637 .checkIncomingCall(getNextArg());
638 getOutPrintWriter().println(val ? "1" : "0");
639 return 0;
640 }
Hall Liud892bec2018-11-30 14:51:45 -0800641 }
642
643 return -1;
644 }
645
Tyler Gunn92479152021-01-20 16:30:10 -0800646 private int handleD2dCommand() {
647 String arg = getNextArg();
648 if (arg == null) {
649 onHelpD2D();
650 return 0;
651 }
652
653 switch (arg) {
654 case D2D_SEND: {
655 return handleD2dSendCommand();
656 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800657 case D2D_TRANSPORT: {
658 return handleD2dTransportCommand();
659 }
Tyler Gunn92479152021-01-20 16:30:10 -0800660 }
661
662 return -1;
663 }
664
665 private int handleD2dSendCommand() {
666 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800667 int messageType = -1;
668 int messageValue = -1;
669
Tyler Gunn92479152021-01-20 16:30:10 -0800670 String arg = getNextArg();
671 if (arg == null) {
672 onHelpD2D();
673 return 0;
674 }
675 try {
676 messageType = Integer.parseInt(arg);
677 } catch (NumberFormatException e) {
678 errPw.println("message type must be a valid integer");
679 return -1;
680 }
681
682 arg = getNextArg();
683 if (arg == null) {
684 onHelpD2D();
685 return 0;
686 }
687 try {
688 messageValue = Integer.parseInt(arg);
689 } catch (NumberFormatException e) {
690 errPw.println("message value must be a valid integer");
691 return -1;
692 }
693
694 try {
695 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
696 } catch (RemoteException e) {
697 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
698 errPw.println("Exception: " + e.getMessage());
699 return -1;
700 }
701
702 return 0;
703 }
704
Tyler Gunnbabbda02021-02-10 11:05:02 -0800705 private int handleD2dTransportCommand() {
706 PrintWriter errPw = getErrPrintWriter();
707
708 String arg = getNextArg();
709 if (arg == null) {
710 onHelpD2D();
711 return 0;
712 }
713
714 try {
715 mInterface.setActiveDeviceToDeviceTransport(arg);
716 } catch (RemoteException e) {
717 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
718 errPw.println("Exception: " + e.getMessage());
719 return -1;
720 }
721 return 0;
722 }
723
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700724 // ims set-ims-service
725 private int handleImsSetServiceCommand() {
726 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700727 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700728 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800729 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700730
731 String opt;
732 while ((opt = getNextOption()) != null) {
733 switch (opt) {
734 case "-s": {
735 try {
736 slotId = Integer.parseInt(getNextArgRequired());
737 } catch (NumberFormatException e) {
738 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
739 return -1;
740 }
741 break;
742 }
743 case "-c": {
744 isCarrierService = true;
745 break;
746 }
747 case "-d": {
748 isCarrierService = false;
749 break;
750 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800751 case "-f": {
752 String featureString = getNextArgRequired();
753 String[] features = featureString.split(",");
754 for (int i = 0; i < features.length; i++) {
755 try {
756 Integer result = Integer.parseInt(features[i]);
757 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
758 || result >= ImsFeature.FEATURE_MAX) {
759 errPw.println("ims set-ims-service -f " + result
760 + " is an invalid feature.");
761 return -1;
762 }
763 featuresList.add(result);
764 } catch (NumberFormatException e) {
765 errPw.println("ims set-ims-service -f tried to parse " + features[i]
766 + " as an integer.");
767 return -1;
768 }
769 }
770 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700771 }
772 }
773 // Mandatory param, either -c or -d
774 if (isCarrierService == null) {
775 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
776 return -1;
777 }
778
779 String packageName = getNextArg();
780
781 try {
782 if (packageName == null) {
783 packageName = "";
784 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800785 int[] featureArray = new int[featuresList.size()];
786 for (int i = 0; i < featuresList.size(); i++) {
787 featureArray[i] = featuresList.get(i);
788 }
789 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
790 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700791 if (VDBG) {
792 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800793 + (isCarrierService ? "-c " : "-d ")
794 + "-f " + featuresList + " "
795 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700796 }
797 getOutPrintWriter().println(result);
798 } catch (RemoteException e) {
799 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800800 + (isCarrierService ? "-c " : "-d ")
801 + "-f " + featuresList + " "
802 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700803 errPw.println("Exception: " + e.getMessage());
804 return -1;
805 }
806 return 0;
807 }
808
Brad Ebinger999d3302020-11-25 14:31:39 -0800809 // ims clear-ims-service-override
810 private int handleImsClearCarrierServiceCommand() {
811 PrintWriter errPw = getErrPrintWriter();
812 int slotId = getDefaultSlot();
813
814 String opt;
815 while ((opt = getNextOption()) != null) {
816 switch (opt) {
817 case "-s": {
818 try {
819 slotId = Integer.parseInt(getNextArgRequired());
820 } catch (NumberFormatException e) {
821 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
822 return -1;
823 }
824 break;
825 }
826 }
827 }
828
829 try {
830 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
831 if (VDBG) {
832 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
833 + ", result=" + result);
834 }
835 getOutPrintWriter().println(result);
836 } catch (RemoteException e) {
837 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
838 + ", error" + e.getMessage());
839 errPw.println("Exception: " + e.getMessage());
840 return -1;
841 }
842 return 0;
843 }
844
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700845 // ims get-ims-service
846 private int handleImsGetServiceCommand() {
847 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700848 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700849 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800850 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700851
852 String opt;
853 while ((opt = getNextOption()) != null) {
854 switch (opt) {
855 case "-s": {
856 try {
857 slotId = Integer.parseInt(getNextArgRequired());
858 } catch (NumberFormatException e) {
859 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
860 return -1;
861 }
862 break;
863 }
864 case "-c": {
865 isCarrierService = true;
866 break;
867 }
868 case "-d": {
869 isCarrierService = false;
870 break;
871 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800872 case "-f": {
873 try {
874 featureType = Integer.parseInt(getNextArg());
875 } catch (NumberFormatException e) {
876 errPw.println("ims get-ims-service -f requires valid integer as feature.");
877 return -1;
878 }
879 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
880 || featureType >= ImsFeature.FEATURE_MAX) {
881 errPw.println("ims get-ims-service -f invalid feature.");
882 return -1;
883 }
884 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700885 }
886 }
887 // Mandatory param, either -c or -d
888 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800889 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700890 return -1;
891 }
892
893 String result;
894 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800895 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700896 } catch (RemoteException e) {
897 return -1;
898 }
899 if (VDBG) {
900 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800901 + (isCarrierService ? "-c " : "-d ")
902 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
903 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700904 }
905 getOutPrintWriter().println(result);
906 return 0;
907 }
908
909 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700910 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700911 String opt;
912 while ((opt = getNextOption()) != null) {
913 switch (opt) {
914 case "-s": {
915 try {
916 slotId = Integer.parseInt(getNextArgRequired());
917 } catch (NumberFormatException e) {
918 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
919 return -1;
920 }
921 break;
922 }
923 }
924 }
925 try {
926 mInterface.enableIms(slotId);
927 } catch (RemoteException e) {
928 return -1;
929 }
930 if (VDBG) {
931 Log.v(LOG_TAG, "ims enable -s " + slotId);
932 }
933 return 0;
934 }
935
936 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700937 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700938 String opt;
939 while ((opt = getNextOption()) != null) {
940 switch (opt) {
941 case "-s": {
942 try {
943 slotId = Integer.parseInt(getNextArgRequired());
944 } catch (NumberFormatException e) {
945 getErrPrintWriter().println(
946 "ims disable requires an integer as a SLOT_ID.");
947 return -1;
948 }
949 break;
950 }
951 }
952 }
953 try {
954 mInterface.disableIms(slotId);
955 } catch (RemoteException e) {
956 return -1;
957 }
958 if (VDBG) {
959 Log.v(LOG_TAG, "ims disable -s " + slotId);
960 }
961 return 0;
962 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700963
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700964 private int handleCepChange() {
965 Log.i(LOG_TAG, "handleCepChange");
966 String opt = getNextArg();
967 if (opt == null) {
968 return -1;
969 }
970 boolean isCepEnabled = opt.equals("enable");
971
972 try {
973 mInterface.setCepEnabled(isCepEnabled);
974 } catch (RemoteException e) {
975 return -1;
976 }
977 return 0;
978 }
979
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700980 private int getDefaultSlot() {
981 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
982 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
983 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
984 // If there is no default, default to slot 0.
985 slotId = DEFAULT_PHONE_ID;
986 }
987 return slotId;
988 }
sqian2fff4a32018-11-05 14:18:37 -0800989
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100990 // Parse options related to Carrier Config Commands.
991 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100992 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100993 CcOptionParseResult result = new CcOptionParseResult();
994 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
995 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100996
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100997 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100998 while ((opt = getNextOption()) != null) {
999 switch (opt) {
1000 case "-s": {
1001 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001002 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1003 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1004 errPw.println(tag + "No valid subscription found.");
1005 return null;
1006 }
1007
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001008 } catch (IllegalArgumentException e) {
1009 // Missing slot id
1010 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001011 return null;
1012 }
1013 break;
1014 }
1015 case "-p": {
1016 if (allowOptionPersistent) {
1017 result.mPersistent = true;
1018 } else {
1019 errPw.println(tag + "Unexpected option " + opt);
1020 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001021 }
1022 break;
1023 }
1024 default: {
1025 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001026 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001027 }
1028 }
1029 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001030 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001031 }
1032
1033 private int slotStringToSubId(String tag, String slotString) {
1034 int slotId = -1;
1035 try {
1036 slotId = Integer.parseInt(slotString);
1037 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001038 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1039 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1040 }
1041
1042 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001043 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1044 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1045 }
1046
Qiong Liuf25799b2020-09-10 10:13:46 +08001047 Phone phone = PhoneFactory.getPhone(slotId);
1048 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001049 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1050 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1051 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001052 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001053 }
1054
Hall Liud892bec2018-11-30 14:51:45 -08001055 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001056 // adb can run as root or as shell, depending on whether the device is rooted.
1057 return Binder.getCallingUid() == Process.SHELL_UID
1058 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001059 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001060
1061 private int handleCcCommand() {
1062 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1063 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001064 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001065 getErrPrintWriter().println("cc: Permission denied.");
1066 return -1;
1067 }
1068
1069 String arg = getNextArg();
1070 if (arg == null) {
1071 onHelpCc();
1072 return 0;
1073 }
1074
1075 switch (arg) {
1076 case CC_GET_VALUE: {
1077 return handleCcGetValue();
1078 }
1079 case CC_SET_VALUE: {
1080 return handleCcSetValue();
1081 }
1082 case CC_CLEAR_VALUES: {
1083 return handleCcClearValues();
1084 }
1085 default: {
1086 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1087 }
1088 }
1089 return -1;
1090 }
1091
1092 // cc get-value
1093 private int handleCcGetValue() {
1094 PrintWriter errPw = getErrPrintWriter();
1095 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1096 String key = null;
1097
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001098 // Parse all options
1099 CcOptionParseResult options = parseCcOptions(tag, false);
1100 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001101 return -1;
1102 }
1103
1104 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001105 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001106 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001107 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001108 return -1;
1109 }
1110
1111 // Get the key.
1112 key = getNextArg();
1113 if (key != null) {
1114 // A key was provided. Verify if it is a valid key
1115 if (!bundle.containsKey(key)) {
1116 errPw.println(tag + key + " is not a valid key.");
1117 return -1;
1118 }
1119
1120 // Print the carrier config value for key.
1121 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1122 } else {
1123 // No key provided. Show all values.
1124 // Iterate over a sorted list of all carrier config keys and print them.
1125 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1126 for (String k : sortedSet) {
1127 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1128 }
1129 }
1130 return 0;
1131 }
1132
1133 // cc set-value
1134 private int handleCcSetValue() {
1135 PrintWriter errPw = getErrPrintWriter();
1136 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1137
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001138 // Parse all options
1139 CcOptionParseResult options = parseCcOptions(tag, true);
1140 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001141 return -1;
1142 }
1143
1144 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001145 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001146 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001147 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001148 return -1;
1149 }
1150
1151 // Get the key.
1152 String key = getNextArg();
1153 if (key == null || key.equals("")) {
1154 errPw.println(tag + "KEY is missing");
1155 return -1;
1156 }
1157
1158 // Verify if the key is valid
1159 if (!originalValues.containsKey(key)) {
1160 errPw.println(tag + key + " is not a valid key.");
1161 return -1;
1162 }
1163
1164 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1165 ArrayList<String> valueList = new ArrayList<String>();
1166 while (peekNextArg() != null) {
1167 valueList.add(getNextArg());
1168 }
1169
1170 // Find the type of the carrier config value
1171 CcType type = getType(tag, key, originalValues);
1172 if (type == CcType.UNKNOWN) {
1173 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1174 return -1;
1175 }
1176
1177 // Create an override bundle containing the key and value that should be overriden.
1178 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1179 if (overrideBundle == null) {
1180 return -1;
1181 }
1182
1183 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001184 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001185
1186 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001187 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001188 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001189 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001190 return -1;
1191 }
1192
1193 // Print the original and new value.
1194 String originalValueString = ccValueToString(key, type, originalValues);
1195 String newValueString = ccValueToString(key, type, newValues);
1196 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1197 getOutPrintWriter().println("New value: \n" + newValueString);
1198
1199 return 0;
1200 }
1201
1202 // cc clear-values
1203 private int handleCcClearValues() {
1204 PrintWriter errPw = getErrPrintWriter();
1205 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1206
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001207 // Parse all options
1208 CcOptionParseResult options = parseCcOptions(tag, false);
1209 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001210 return -1;
1211 }
1212
1213 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001214 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001215 getOutPrintWriter()
1216 .println("All previously set carrier config override values has been cleared");
1217 return 0;
1218 }
1219
1220 private CcType getType(String tag, String key, PersistableBundle bundle) {
1221 // Find the type by checking the type of the current value stored in the bundle.
1222 Object value = bundle.get(key);
1223
1224 if (CC_TYPE_MAP.containsKey(key)) {
1225 return CC_TYPE_MAP.get(key);
1226 } else if (value != null) {
1227 if (value instanceof Boolean) {
1228 return CcType.BOOLEAN;
1229 } else if (value instanceof Double) {
1230 return CcType.DOUBLE;
1231 } else if (value instanceof double[]) {
1232 return CcType.DOUBLE_ARRAY;
1233 } else if (value instanceof Integer) {
1234 return CcType.INT;
1235 } else if (value instanceof int[]) {
1236 return CcType.INT_ARRAY;
1237 } else if (value instanceof Long) {
1238 return CcType.LONG;
1239 } else if (value instanceof long[]) {
1240 return CcType.LONG_ARRAY;
1241 } else if (value instanceof String) {
1242 return CcType.STRING;
1243 } else if (value instanceof String[]) {
1244 return CcType.STRING_ARRAY;
1245 }
1246 } else {
1247 // Current value was null and can therefore not be used in order to find the type.
1248 // Check the name of the key to infer the type. This check is not needed for primitive
1249 // data types (boolean, double, int and long), since they can not be null.
1250 if (key.endsWith("double_array")) {
1251 return CcType.DOUBLE_ARRAY;
1252 }
1253 if (key.endsWith("int_array")) {
1254 return CcType.INT_ARRAY;
1255 }
1256 if (key.endsWith("long_array")) {
1257 return CcType.LONG_ARRAY;
1258 }
1259 if (key.endsWith("string")) {
1260 return CcType.STRING;
1261 }
1262 if (key.endsWith("string_array") || key.endsWith("strings")) {
1263 return CcType.STRING_ARRAY;
1264 }
1265 }
1266
1267 // Not possible to infer the type by looking at the current value or the key.
1268 PrintWriter errPw = getErrPrintWriter();
1269 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1270 return CcType.UNKNOWN;
1271 }
1272
1273 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1274 String result;
1275 StringBuilder valueString = new StringBuilder();
1276 String typeString = type.toString();
1277 Object value = bundle.get(key);
1278
1279 if (value == null) {
1280 valueString.append("null");
1281 } else {
1282 switch (type) {
1283 case DOUBLE_ARRAY: {
1284 // Format the string representation of the int array as value1 value2......
1285 double[] valueArray = (double[]) value;
1286 for (int i = 0; i < valueArray.length; i++) {
1287 if (i != 0) {
1288 valueString.append(" ");
1289 }
1290 valueString.append(valueArray[i]);
1291 }
1292 break;
1293 }
1294 case INT_ARRAY: {
1295 // Format the string representation of the int array as value1 value2......
1296 int[] valueArray = (int[]) value;
1297 for (int i = 0; i < valueArray.length; i++) {
1298 if (i != 0) {
1299 valueString.append(" ");
1300 }
1301 valueString.append(valueArray[i]);
1302 }
1303 break;
1304 }
1305 case LONG_ARRAY: {
1306 // Format the string representation of the int array as value1 value2......
1307 long[] valueArray = (long[]) value;
1308 for (int i = 0; i < valueArray.length; i++) {
1309 if (i != 0) {
1310 valueString.append(" ");
1311 }
1312 valueString.append(valueArray[i]);
1313 }
1314 break;
1315 }
1316 case STRING: {
1317 valueString.append("\"" + value.toString() + "\"");
1318 break;
1319 }
1320 case STRING_ARRAY: {
1321 // Format the string representation of the string array as "value1" "value2"....
1322 String[] valueArray = (String[]) value;
1323 for (int i = 0; i < valueArray.length; i++) {
1324 if (i != 0) {
1325 valueString.append(" ");
1326 }
1327 if (valueArray[i] != null) {
1328 valueString.append("\"" + valueArray[i] + "\"");
1329 } else {
1330 valueString.append("null");
1331 }
1332 }
1333 break;
1334 }
1335 default: {
1336 valueString.append(value.toString());
1337 }
1338 }
1339 }
1340 return String.format("%-70s %-15s %s", key, typeString, valueString);
1341 }
1342
1343 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1344 ArrayList<String> valueList) {
1345 PrintWriter errPw = getErrPrintWriter();
1346 PersistableBundle bundle = new PersistableBundle();
1347
1348 // First verify that a valid number of values has been provided for the type.
1349 switch (type) {
1350 case BOOLEAN:
1351 case DOUBLE:
1352 case INT:
1353 case LONG: {
1354 if (valueList.size() != 1) {
1355 errPw.println(tag + "Expected 1 value for type " + type
1356 + ". Found: " + valueList.size());
1357 return null;
1358 }
1359 break;
1360 }
1361 case STRING: {
1362 if (valueList.size() > 1) {
1363 errPw.println(tag + "Expected 0 or 1 values for type " + type
1364 + ". Found: " + valueList.size());
1365 return null;
1366 }
1367 break;
1368 }
1369 }
1370
1371 // Parse the value according to type and add it to the Bundle.
1372 switch (type) {
1373 case BOOLEAN: {
1374 if ("true".equalsIgnoreCase(valueList.get(0))) {
1375 bundle.putBoolean(key, true);
1376 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1377 bundle.putBoolean(key, false);
1378 } else {
1379 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1380 return null;
1381 }
1382 break;
1383 }
1384 case DOUBLE: {
1385 try {
1386 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1387 } catch (NumberFormatException nfe) {
1388 // Not a valid double
1389 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1390 return null;
1391 }
1392 break;
1393 }
1394 case DOUBLE_ARRAY: {
1395 double[] valueDoubleArray = null;
1396 if (valueList.size() > 0) {
1397 valueDoubleArray = new double[valueList.size()];
1398 for (int i = 0; i < valueList.size(); i++) {
1399 try {
1400 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1401 } catch (NumberFormatException nfe) {
1402 // Not a valid double
1403 errPw.println(
1404 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1405 return null;
1406 }
1407 }
1408 }
1409 bundle.putDoubleArray(key, valueDoubleArray);
1410 break;
1411 }
1412 case INT: {
1413 try {
1414 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1415 } catch (NumberFormatException nfe) {
1416 // Not a valid integer
1417 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1418 return null;
1419 }
1420 break;
1421 }
1422 case INT_ARRAY: {
1423 int[] valueIntArray = null;
1424 if (valueList.size() > 0) {
1425 valueIntArray = new int[valueList.size()];
1426 for (int i = 0; i < valueList.size(); i++) {
1427 try {
1428 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1429 } catch (NumberFormatException nfe) {
1430 // Not a valid integer
1431 errPw.println(tag
1432 + "Unable to parse " + valueList.get(i) + " as an integer.");
1433 return null;
1434 }
1435 }
1436 }
1437 bundle.putIntArray(key, valueIntArray);
1438 break;
1439 }
1440 case LONG: {
1441 try {
1442 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1443 } catch (NumberFormatException nfe) {
1444 // Not a valid long
1445 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1446 return null;
1447 }
1448 break;
1449 }
1450 case LONG_ARRAY: {
1451 long[] valueLongArray = null;
1452 if (valueList.size() > 0) {
1453 valueLongArray = new long[valueList.size()];
1454 for (int i = 0; i < valueList.size(); i++) {
1455 try {
1456 valueLongArray[i] = Long.parseLong(valueList.get(i));
1457 } catch (NumberFormatException nfe) {
1458 // Not a valid long
1459 errPw.println(
1460 tag + "Unable to parse " + valueList.get(i) + " as a long");
1461 return null;
1462 }
1463 }
1464 }
1465 bundle.putLongArray(key, valueLongArray);
1466 break;
1467 }
1468 case STRING: {
1469 String value = null;
1470 if (valueList.size() > 0) {
1471 value = valueList.get(0);
1472 }
1473 bundle.putString(key, value);
1474 break;
1475 }
1476 case STRING_ARRAY: {
1477 String[] valueStringArray = null;
1478 if (valueList.size() > 0) {
1479 valueStringArray = new String[valueList.size()];
1480 valueList.toArray(valueStringArray);
1481 }
1482 bundle.putStringArray(key, valueStringArray);
1483 break;
1484 }
1485 }
1486 return bundle;
1487 }
Shuo Qian489d9282020-07-09 11:30:03 -07001488
1489 private int handleEndBlockSuppressionCommand() {
1490 if (!checkShellUid()) {
1491 return -1;
1492 }
1493
1494 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1495 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1496 }
1497 return 0;
1498 }
Hui Wang641e81c2020-10-12 12:14:23 -07001499
Michele Berionne54af4632020-12-28 20:23:16 +00001500 private int handleRestartModemCommand() {
1501 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1502 // non user build.
1503 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1504 getErrPrintWriter().println("RestartModem: Permission denied.");
1505 return -1;
1506 }
1507
1508 boolean result = TelephonyManager.getDefault().rebootRadio();
1509 getOutPrintWriter().println(result);
1510
1511 return result ? 0 : -1;
1512 }
1513
Michele Berionne5e411512020-11-13 02:36:59 +00001514 private int handleUnattendedReboot() {
1515 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1516 // non user build.
1517 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1518 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1519 return -1;
1520 }
1521
1522 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1523 getOutPrintWriter().println("result: " + result);
1524
1525 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1526 }
1527
Hui Wang641e81c2020-10-12 12:14:23 -07001528 private int handleGbaCommand() {
1529 String arg = getNextArg();
1530 if (arg == null) {
1531 onHelpGba();
1532 return 0;
1533 }
1534
1535 switch (arg) {
1536 case GBA_SET_SERVICE: {
1537 return handleGbaSetServiceCommand();
1538 }
1539 case GBA_GET_SERVICE: {
1540 return handleGbaGetServiceCommand();
1541 }
1542 case GBA_SET_RELEASE_TIME: {
1543 return handleGbaSetReleaseCommand();
1544 }
1545 case GBA_GET_RELEASE_TIME: {
1546 return handleGbaGetReleaseCommand();
1547 }
1548 }
1549
1550 return -1;
1551 }
1552
1553 private int getSubId(String cmd) {
1554 int slotId = getDefaultSlot();
1555 String opt = getNextOption();
1556 if (opt != null && opt.equals("-s")) {
1557 try {
1558 slotId = Integer.parseInt(getNextArgRequired());
1559 } catch (NumberFormatException e) {
1560 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1561 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1562 }
1563 }
1564 int[] subIds = SubscriptionManager.getSubId(slotId);
1565 return subIds[0];
1566 }
1567
1568 private int handleGbaSetServiceCommand() {
1569 int subId = getSubId("gba set-service");
1570 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1571 return -1;
1572 }
1573
1574 String packageName = getNextArg();
1575 try {
1576 if (packageName == null) {
1577 packageName = "";
1578 }
1579 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1580 if (VDBG) {
1581 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1582 + packageName + ", result=" + result);
1583 }
1584 getOutPrintWriter().println(result);
1585 } catch (RemoteException e) {
1586 Log.w(LOG_TAG, "gba set-service " + subId + " "
1587 + packageName + ", error" + e.getMessage());
1588 getErrPrintWriter().println("Exception: " + e.getMessage());
1589 return -1;
1590 }
1591 return 0;
1592 }
1593
1594 private int handleGbaGetServiceCommand() {
1595 String result;
1596
1597 int subId = getSubId("gba get-service");
1598 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1599 return -1;
1600 }
1601
1602 try {
1603 result = mInterface.getBoundGbaService(subId);
1604 } catch (RemoteException e) {
1605 return -1;
1606 }
1607 if (VDBG) {
1608 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1609 }
1610 getOutPrintWriter().println(result);
1611 return 0;
1612 }
1613
1614 private int handleGbaSetReleaseCommand() {
1615 //the release time value could be -1
1616 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1617 : SubscriptionManager.getDefaultSubscriptionId();
1618 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1619 return -1;
1620 }
1621
1622 String intervalStr = getNextArg();
1623 if (intervalStr == null) {
1624 return -1;
1625 }
1626
1627 try {
1628 int interval = Integer.parseInt(intervalStr);
1629 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1630 if (VDBG) {
1631 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1632 + intervalStr + ", result=" + result);
1633 }
1634 getOutPrintWriter().println(result);
1635 } catch (NumberFormatException | RemoteException e) {
1636 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1637 + intervalStr + ", error" + e.getMessage());
1638 getErrPrintWriter().println("Exception: " + e.getMessage());
1639 return -1;
1640 }
1641 return 0;
1642 }
1643
1644 private int handleGbaGetReleaseCommand() {
1645 int subId = getSubId("gba get-release");
1646 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1647 return -1;
1648 }
1649
1650 int result = 0;
1651 try {
1652 result = mInterface.getGbaReleaseTime(subId);
1653 } catch (RemoteException e) {
1654 return -1;
1655 }
1656 if (VDBG) {
1657 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1658 }
1659 getOutPrintWriter().println(result);
1660 return 0;
1661 }
Hui Wang761a6682020-10-31 05:12:53 +00001662
1663 private int handleSingleRegistrationConfigCommand() {
1664 String arg = getNextArg();
1665 if (arg == null) {
1666 onHelpSrc();
1667 return 0;
1668 }
1669
1670 switch (arg) {
1671 case SRC_SET_DEVICE_ENABLED: {
1672 return handleSrcSetDeviceEnabledCommand();
1673 }
1674 case SRC_GET_DEVICE_ENABLED: {
1675 return handleSrcGetDeviceEnabledCommand();
1676 }
1677 case SRC_SET_CARRIER_ENABLED: {
1678 return handleSrcSetCarrierEnabledCommand();
1679 }
1680 case SRC_GET_CARRIER_ENABLED: {
1681 return handleSrcGetCarrierEnabledCommand();
1682 }
1683 }
1684
1685 return -1;
1686 }
1687
James.cf Linbcdf8b32021-01-14 16:44:13 +08001688 private int handleRcsUceCommand() {
1689 String arg = getNextArg();
1690 if (arg == null) {
1691 Log.w(LOG_TAG, "cannot get uce parameter");
1692 return -1;
1693 }
1694
1695 switch (arg) {
1696 case UCE_REMOVE_EAB_CONTACT:
1697 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001698 case UCE_GET_EAB_CONTACT:
1699 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001700 case UCE_GET_DEVICE_ENABLED:
1701 return handleUceGetDeviceEnabledCommand();
1702 case UCE_SET_DEVICE_ENABLED:
1703 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001704 }
1705 return -1;
1706 }
1707
1708 private int handleRemovingEabContactCommand() {
1709 int subId = getSubId("uce remove-eab-contact");
1710 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1711 return -1;
1712 }
1713
1714 String phoneNumber = getNextArgRequired();
1715 if (TextUtils.isEmpty(phoneNumber)) {
1716 return -1;
1717 }
1718 int result = 0;
1719 try {
1720 result = mInterface.removeContactFromEab(subId, phoneNumber);
1721 } catch (RemoteException e) {
1722 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1723 getErrPrintWriter().println("Exception: " + e.getMessage());
1724 return -1;
1725 }
1726
1727 if (VDBG) {
1728 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1729 }
calvinpan293ea1b2021-02-04 17:52:13 +08001730 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001731 }
1732
calvinpane4a8a1d2021-01-25 13:51:18 +08001733 private int handleGettingEabContactCommand() {
1734 String phoneNumber = getNextArgRequired();
1735 if (TextUtils.isEmpty(phoneNumber)) {
1736 return -1;
1737 }
1738 String result = "";
1739 try {
1740 result = mInterface.getContactFromEab(phoneNumber);
1741
1742 } catch (RemoteException e) {
1743 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1744 getErrPrintWriter().println("Exception: " + e.getMessage());
1745 return -1;
1746 }
1747
1748 if (VDBG) {
1749 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1750 }
calvinpan293ea1b2021-02-04 17:52:13 +08001751 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001752 return 0;
1753 }
1754
1755 private int handleUceGetDeviceEnabledCommand() {
1756 boolean result = false;
1757 try {
1758 result = mInterface.getDeviceUceEnabled();
1759 } catch (RemoteException e) {
1760 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1761 return -1;
1762 }
1763 if (VDBG) {
1764 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1765 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001766 getOutPrintWriter().println(result);
1767 return 0;
1768 }
1769
James.cf Lin4b784aa2021-01-31 03:25:15 +08001770 private int handleUceSetDeviceEnabledCommand() {
1771 String enabledStr = getNextArg();
1772 if (TextUtils.isEmpty(enabledStr)) {
1773 return -1;
1774 }
1775
1776 try {
1777 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1778 mInterface.setDeviceUceEnabled(isEnabled);
1779 if (VDBG) {
1780 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1781 }
1782 } catch (NumberFormatException | RemoteException e) {
1783 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1784 getErrPrintWriter().println("Exception: " + e.getMessage());
1785 return -1;
1786 }
1787 return 0;
1788 }
1789
Hui Wang761a6682020-10-31 05:12:53 +00001790 private int handleSrcSetDeviceEnabledCommand() {
1791 String enabledStr = getNextArg();
1792 if (enabledStr == null) {
1793 return -1;
1794 }
1795
1796 try {
1797 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1798 if (VDBG) {
1799 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1800 }
1801 getOutPrintWriter().println("Done");
1802 } catch (NumberFormatException | RemoteException e) {
1803 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1804 getErrPrintWriter().println("Exception: " + e.getMessage());
1805 return -1;
1806 }
1807 return 0;
1808 }
1809
1810 private int handleSrcGetDeviceEnabledCommand() {
1811 boolean result = false;
1812 try {
1813 result = mInterface.getDeviceSingleRegistrationEnabled();
1814 } catch (RemoteException e) {
1815 return -1;
1816 }
1817 if (VDBG) {
1818 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1819 }
1820 getOutPrintWriter().println(result);
1821 return 0;
1822 }
1823
1824 private int handleSrcSetCarrierEnabledCommand() {
1825 //the release time value could be -1
1826 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1827 : SubscriptionManager.getDefaultSubscriptionId();
1828 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1829 return -1;
1830 }
1831
1832 String enabledStr = getNextArg();
1833 if (enabledStr == null) {
1834 return -1;
1835 }
1836
1837 try {
1838 boolean result =
1839 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1840 if (VDBG) {
1841 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1842 + enabledStr + ", result=" + result);
1843 }
1844 getOutPrintWriter().println(result);
1845 } catch (NumberFormatException | RemoteException e) {
1846 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1847 + enabledStr + ", error" + e.getMessage());
1848 getErrPrintWriter().println("Exception: " + e.getMessage());
1849 return -1;
1850 }
1851 return 0;
1852 }
1853
1854 private int handleSrcGetCarrierEnabledCommand() {
1855 int subId = getSubId("src get-carrier-enabled");
1856 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1857 return -1;
1858 }
1859
1860 boolean result = false;
1861 try {
1862 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1863 } catch (RemoteException e) {
1864 return -1;
1865 }
1866 if (VDBG) {
1867 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1868 }
1869 getOutPrintWriter().println(result);
1870 return 0;
1871 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001872
1873 private void onHelpCallComposer() {
1874 PrintWriter pw = getOutPrintWriter();
1875 pw.println("Call composer commands");
1876 pw.println(" callcomposer test-mode enable|disable|query");
1877 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1878 pw.println(" upload/download from carrier servers is disabled, and operations are");
1879 pw.println(" performed using emulated local files instead.");
1880 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1881 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1882 pw.println(" the provided UUID. This triggers storage to the call log.");
1883 }
1884
1885 private int handleCallComposerCommand() {
1886 String arg = getNextArg();
1887 if (arg == null) {
1888 onHelpCallComposer();
1889 return 0;
1890 }
1891
1892 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1893 "MODIFY_PHONE_STATE required for call composer shell cmds");
1894 switch (arg) {
1895 case CALL_COMPOSER_TEST_MODE: {
1896 String enabledStr = getNextArg();
1897 if (ENABLE.equals(enabledStr)) {
1898 CallComposerPictureManager.sTestMode = true;
1899 } else if (DISABLE.equals(enabledStr)) {
1900 CallComposerPictureManager.sTestMode = false;
1901 } else if (QUERY.equals(enabledStr)) {
1902 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1903 } else {
1904 onHelpCallComposer();
1905 return 1;
1906 }
1907 break;
1908 }
1909 case CALL_COMPOSER_SIMULATE_CALL: {
1910 int subscriptionId = Integer.valueOf(getNextArg());
1911 String uuidString = getNextArg();
1912 UUID uuid = UUID.fromString(uuidString);
1913 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1914 Binder.withCleanCallingIdentity(() -> {
1915 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1916 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1917 });
1918 try {
1919 Uri uri = storageUriFuture.get();
1920 getOutPrintWriter().println(String.valueOf(uri));
1921 } catch (Exception e) {
1922 throw new RuntimeException(e);
1923 }
1924 break;
1925 }
1926 }
1927
1928 return 0;
1929 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001930}