blob: d395aa2cd0e9876efa570fa6677c5c9a0b084d0d [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";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800115 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
116 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wang761a6682020-10-31 05:12:53 +0000117
Tyler Gunn92479152021-01-20 16:30:10 -0800118 private static final String D2D_SUBCOMMAND = "d2d";
119 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800120 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800121
James.cf Linbcdf8b32021-01-14 16:44:13 +0800122 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800123 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800124 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800125 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
126 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800127
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700128 // Take advantage of existing methods that already contain permissions checks when possible.
129 private final ITelephony mInterface;
130
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100131 private SubscriptionManager mSubscriptionManager;
132 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700133 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100134
135 private enum CcType {
136 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
137 STRING_ARRAY, UNKNOWN
138 }
139
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100140 private class CcOptionParseResult {
141 public int mSubId;
142 public boolean mPersistent;
143 }
144
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100145 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
146 // keys by looking at the end of the string which usually tells the type.
147 // For instance: "xxxx_string", "xxxx_string_array", etc.
148 // The carrier config keys in this map does not follow this convention. It is therefore not
149 // possible to infer the type for these keys by looking at the string.
150 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
151 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
157 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
158 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
159 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
160 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
161 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
162 CcType.STRING);
163 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
164 CcType.STRING_ARRAY);
165 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
166 CcType.STRING_ARRAY);
167 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
168 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
169 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
170 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
171 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
172 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
173 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
174 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
175 }
176 };
177
178 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700179 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100180 mCarrierConfigManager =
181 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
182 mSubscriptionManager = (SubscriptionManager)
183 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700184 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700185 }
186
187 @Override
188 public int onCommand(String cmd) {
189 if (cmd == null) {
190 return handleDefaultCommands(null);
191 }
192
193 switch (cmd) {
194 case IMS_SUBCOMMAND: {
195 return handleImsCommand();
196 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800197 case RCS_UCE_COMMAND:
198 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800199 case NUMBER_VERIFICATION_SUBCOMMAND:
200 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800201 case EMERGENCY_CALLBACK_MODE:
202 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800203 case EMERGENCY_NUMBER_TEST_MODE:
204 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100205 case CARRIER_CONFIG_SUBCOMMAND: {
206 return handleCcCommand();
207 }
Shuo Qianf5125122019-12-16 17:03:07 -0800208 case DATA_TEST_MODE:
209 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700210 case END_BLOCK_SUPPRESSION:
211 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700212 case GBA_SUBCOMMAND:
213 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800214 case D2D_SUBCOMMAND:
215 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000216 case SINGLE_REGISTATION_CONFIG:
217 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000218 case RESTART_MODEM:
219 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800220 case CALL_COMPOSER_SUBCOMMAND:
221 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000222 case UNATTENDED_REBOOT:
223 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700224 default: {
225 return handleDefaultCommands(cmd);
226 }
227 }
228 }
229
230 @Override
231 public void onHelp() {
232 PrintWriter pw = getOutPrintWriter();
233 pw.println("Telephony Commands:");
234 pw.println(" help");
235 pw.println(" Print this help text.");
236 pw.println(" ims");
237 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800238 pw.println(" uce");
239 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800240 pw.println(" emergency-number-test-mode");
241 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700242 pw.println(" end-block-suppression");
243 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800244 pw.println(" data");
245 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100246 pw.println(" cc");
247 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700248 pw.println(" gba");
249 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000250 pw.println(" src");
251 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000252 pw.println(" restart-modem");
253 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000254 pw.println(" unattended-reboot");
255 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700256 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800257 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800258 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700259 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800260 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100261 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700262 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000263 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800264 onHelpD2D();
265 }
266
267 private void onHelpD2D() {
268 PrintWriter pw = getOutPrintWriter();
269 pw.println("D2D Comms Commands:");
270 pw.println(" d2d send TYPE VALUE");
271 pw.println(" Sends a D2D message of specified type and value.");
272 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
273 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
274 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
275 MESSAGE_CALL_AUDIO_CODEC));
276 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
277 + Communicator.messageToString(
278 MESSAGE_DEVICE_BATTERY_STATE));
279 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
280 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800281 pw.println(" d2d transport TYPE");
282 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
283 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700284 }
285
286 private void onHelpIms() {
287 PrintWriter pw = getOutPrintWriter();
288 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800289 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700290 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
291 pw.println(" ImsService. Options are:");
292 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
293 pw.println(" is specified, it will choose the default voice SIM slot.");
294 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
295 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800296 pw.println(" -f: Set the feature that this override if for, if no option is");
297 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700298 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
299 pw.println(" Gets the package name of the currently defined ImsService.");
300 pw.println(" Options are:");
301 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
302 pw.println(" is specified, it will choose the default voice SIM slot.");
303 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000304 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800305 pw.println(" -f: The feature type that the query will be requested for. If none is");
306 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800307 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
308 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
309 pw.println(" configuration overrides. Options are:");
310 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
311 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700312 pw.println(" ims enable [-s SLOT_ID]");
313 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
314 pw.println(" if none is specified.");
315 pw.println(" ims disable [-s SLOT_ID]");
316 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
317 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700318 pw.println(" ims conference-event-package [enable/disable]");
319 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700320 }
321
James.cf Linbcdf8b32021-01-14 16:44:13 +0800322 private void onHelpUce() {
323 PrintWriter pw = getOutPrintWriter();
324 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800325 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
326 pw.println(" Get the EAB contacts from the EAB database.");
327 pw.println(" Options are:");
328 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
329 pw.println(" Expected output format :");
330 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800331 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
332 pw.println(" Remove the EAB contacts from the EAB database.");
333 pw.println(" Options are:");
334 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
335 pw.println(" is specified, it will choose the default voice SIM slot.");
336 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800337 pw.println(" uce get-device-enabled");
338 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
339 pw.println(" uce set-device-enabled true|false");
340 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
341 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800342 }
343
Hall Liud892bec2018-11-30 14:51:45 -0800344 private void onHelpNumberVerification() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("Number verification commands");
347 pw.println(" numverify override-package PACKAGE_NAME;");
348 pw.println(" Set the authorized package for number verification.");
349 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800350 pw.println(" numverify fake-call NUMBER;");
351 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
352 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800353 }
354
Shuo Qianf5125122019-12-16 17:03:07 -0800355 private void onHelpDataTestMode() {
356 PrintWriter pw = getOutPrintWriter();
357 pw.println("Mobile Data Test Mode Commands:");
358 pw.println(" data enable: enable mobile data connectivity");
359 pw.println(" data disable: disable mobile data connectivity");
360 }
361
sqian9d4df8b2019-01-15 18:32:07 -0800362 private void onHelpEmergencyNumber() {
363 PrintWriter pw = getOutPrintWriter();
364 pw.println("Emergency Number Test Mode Commands:");
365 pw.println(" emergency-number-test-mode ");
366 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
367 + " the test mode");
368 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700369 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800370 pw.println(" -c: clear the emergency number list in the test mode.");
371 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700372 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800373 pw.println(" -p: get the full emergency number list in the test mode.");
374 }
375
Shuo Qian489d9282020-07-09 11:30:03 -0700376 private void onHelpEndBlockSupperssion() {
377 PrintWriter pw = getOutPrintWriter();
378 pw.println("End Block Suppression command:");
379 pw.println(" end-block-suppression: disable suppressing blocking by contact");
380 pw.println(" with emergency services.");
381 }
382
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100383 private void onHelpCc() {
384 PrintWriter pw = getOutPrintWriter();
385 pw.println("Carrier Config Commands:");
386 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
387 pw.println(" Print carrier config values.");
388 pw.println(" Options are:");
389 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
390 pw.println(" is specified, it will choose the default voice SIM slot.");
391 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
392 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100393 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100394 pw.println(" Set carrier config KEY to NEW_VALUE.");
395 pw.println(" Options are:");
396 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
397 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100398 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100399 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
400 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
401 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
402 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
403 pw.println(" cc clear-values [-s SLOT_ID]");
404 pw.println(" Clear all carrier override values that has previously been set");
405 pw.println(" with set-value");
406 pw.println(" Options are:");
407 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
408 pw.println(" is specified, it will choose the default voice SIM slot.");
409 }
410
Hui Wang641e81c2020-10-12 12:14:23 -0700411 private void onHelpGba() {
412 PrintWriter pw = getOutPrintWriter();
413 pw.println("Gba Commands:");
414 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
415 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
416 pw.println(" Options are:");
417 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
418 pw.println(" is specified, it will choose the default voice SIM slot.");
419 pw.println(" gba get-service [-s SLOT_ID]");
420 pw.println(" Gets the package name of the currently defined GbaService.");
421 pw.println(" Options are:");
422 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
423 pw.println(" is specified, it will choose the default voice SIM slot.");
424 pw.println(" gba set-release [-s SLOT_ID] n");
425 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
426 pw.println(" Do not release/unbind if n is -1.");
427 pw.println(" Options are:");
428 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
429 pw.println(" is specified, it will choose the default voice SIM slot.");
430 pw.println(" gba get-release [-s SLOT_ID]");
431 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
432 pw.println(" Options are:");
433 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
434 pw.println(" is specified, it will choose the default voice SIM slot.");
435 }
436
Hui Wang761a6682020-10-31 05:12:53 +0000437 private void onHelpSrc() {
438 PrintWriter pw = getOutPrintWriter();
439 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800440 pw.println(" src set-test-enabled true|false");
441 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
442 pw.println(" The value could be true, false, or null(undefined).");
443 pw.println(" src get-test-enabled");
444 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000445 pw.println(" src set-device-enabled true|false|null");
446 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
447 pw.println(" The value could be true, false, or null(undefined).");
448 pw.println(" src get-device-enabled");
449 pw.println(" Gets the device config for RCS VoLTE single registration.");
450 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
451 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
452 pw.println(" The value could be true, false, or null(undefined).");
453 pw.println(" Options are:");
454 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
455 pw.println(" is specified, it will choose the default voice SIM slot.");
456 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
457 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
458 pw.println(" Options are:");
459 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
460 pw.println(" is specified, it will choose the default voice SIM slot.");
461 }
462
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700463 private int handleImsCommand() {
464 String arg = getNextArg();
465 if (arg == null) {
466 onHelpIms();
467 return 0;
468 }
469
470 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800471 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700472 return handleImsSetServiceCommand();
473 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800474 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700475 return handleImsGetServiceCommand();
476 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800477 case IMS_CLEAR_SERVICE_OVERRIDE: {
478 return handleImsClearCarrierServiceCommand();
479 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800480 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700481 return handleEnableIms();
482 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800483 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700484 return handleDisableIms();
485 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700486 case IMS_CEP: {
487 return handleCepChange();
488 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700489 }
490
491 return -1;
492 }
493
Shuo Qianf5125122019-12-16 17:03:07 -0800494 private int handleDataTestModeCommand() {
495 PrintWriter errPw = getErrPrintWriter();
496 String arg = getNextArgRequired();
497 if (arg == null) {
498 onHelpDataTestMode();
499 return 0;
500 }
501 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800502 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800503 try {
504 mInterface.enableDataConnectivity();
505 } catch (RemoteException ex) {
506 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
507 errPw.println("Exception: " + ex.getMessage());
508 return -1;
509 }
510 break;
511 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800512 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800513 try {
514 mInterface.disableDataConnectivity();
515 } catch (RemoteException ex) {
516 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
517 errPw.println("Exception: " + ex.getMessage());
518 return -1;
519 }
520 break;
521 }
522 default:
523 onHelpDataTestMode();
524 break;
525 }
526 return 0;
527 }
528
Shuo Qianccbaf742021-02-22 18:32:21 -0800529 private int handleEmergencyCallbackModeCommand() {
530 PrintWriter errPw = getErrPrintWriter();
531 try {
532 mInterface.startEmergencyCallbackMode();
533 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
534 } catch (RemoteException ex) {
535 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
536 errPw.println("Exception: " + ex.getMessage());
537 return -1;
538 }
539 return 0;
540 }
541
sqian9d4df8b2019-01-15 18:32:07 -0800542 private int handleEmergencyNumberTestModeCommand() {
543 PrintWriter errPw = getErrPrintWriter();
544 String opt = getNextOption();
545 if (opt == null) {
546 onHelpEmergencyNumber();
547 return 0;
548 }
549
550 switch (opt) {
551 case "-a": {
552 String emergencyNumberCmd = getNextArgRequired();
553 if (emergencyNumberCmd == null
554 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700555 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800556 + " to be specified after -a in the command ");
557 return -1;
558 }
559 try {
560 mInterface.updateEmergencyNumberListTestMode(
561 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
562 new EmergencyNumber(emergencyNumberCmd, "", "",
563 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
564 new ArrayList<String>(),
565 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
566 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
567 } catch (RemoteException ex) {
568 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
569 + ", error " + ex.getMessage());
570 errPw.println("Exception: " + ex.getMessage());
571 return -1;
572 }
573 break;
574 }
575 case "-c": {
576 try {
577 mInterface.updateEmergencyNumberListTestMode(
578 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
579 } catch (RemoteException ex) {
580 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
581 errPw.println("Exception: " + ex.getMessage());
582 return -1;
583 }
584 break;
585 }
586 case "-r": {
587 String emergencyNumberCmd = getNextArgRequired();
588 if (emergencyNumberCmd == null
589 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700590 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800591 + " to be specified after -r in the command ");
592 return -1;
593 }
594 try {
595 mInterface.updateEmergencyNumberListTestMode(
596 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
597 new EmergencyNumber(emergencyNumberCmd, "", "",
598 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
599 new ArrayList<String>(),
600 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
601 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
602 } catch (RemoteException ex) {
603 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
604 + ", error " + ex.getMessage());
605 errPw.println("Exception: " + ex.getMessage());
606 return -1;
607 }
608 break;
609 }
610 case "-p": {
611 try {
612 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
613 } catch (RemoteException ex) {
614 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
615 errPw.println("Exception: " + ex.getMessage());
616 return -1;
617 }
618 break;
619 }
620 default:
621 onHelpEmergencyNumber();
622 break;
623 }
624 return 0;
625 }
626
Hall Liud892bec2018-11-30 14:51:45 -0800627 private int handleNumberVerificationCommand() {
628 String arg = getNextArg();
629 if (arg == null) {
630 onHelpNumberVerification();
631 return 0;
632 }
633
Hall Liuca5af3a2018-12-04 16:58:23 -0800634 if (!checkShellUid()) {
635 return -1;
636 }
637
Hall Liud892bec2018-11-30 14:51:45 -0800638 switch (arg) {
639 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800640 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
641 return 0;
642 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800643 case NUMBER_VERIFICATION_FAKE_CALL: {
644 boolean val = NumberVerificationManager.getInstance()
645 .checkIncomingCall(getNextArg());
646 getOutPrintWriter().println(val ? "1" : "0");
647 return 0;
648 }
Hall Liud892bec2018-11-30 14:51:45 -0800649 }
650
651 return -1;
652 }
653
Tyler Gunn92479152021-01-20 16:30:10 -0800654 private int handleD2dCommand() {
655 String arg = getNextArg();
656 if (arg == null) {
657 onHelpD2D();
658 return 0;
659 }
660
661 switch (arg) {
662 case D2D_SEND: {
663 return handleD2dSendCommand();
664 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800665 case D2D_TRANSPORT: {
666 return handleD2dTransportCommand();
667 }
Tyler Gunn92479152021-01-20 16:30:10 -0800668 }
669
670 return -1;
671 }
672
673 private int handleD2dSendCommand() {
674 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800675 int messageType = -1;
676 int messageValue = -1;
677
Tyler Gunn92479152021-01-20 16:30:10 -0800678 String arg = getNextArg();
679 if (arg == null) {
680 onHelpD2D();
681 return 0;
682 }
683 try {
684 messageType = Integer.parseInt(arg);
685 } catch (NumberFormatException e) {
686 errPw.println("message type must be a valid integer");
687 return -1;
688 }
689
690 arg = getNextArg();
691 if (arg == null) {
692 onHelpD2D();
693 return 0;
694 }
695 try {
696 messageValue = Integer.parseInt(arg);
697 } catch (NumberFormatException e) {
698 errPw.println("message value must be a valid integer");
699 return -1;
700 }
701
702 try {
703 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
704 } catch (RemoteException e) {
705 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
706 errPw.println("Exception: " + e.getMessage());
707 return -1;
708 }
709
710 return 0;
711 }
712
Tyler Gunnbabbda02021-02-10 11:05:02 -0800713 private int handleD2dTransportCommand() {
714 PrintWriter errPw = getErrPrintWriter();
715
716 String arg = getNextArg();
717 if (arg == null) {
718 onHelpD2D();
719 return 0;
720 }
721
722 try {
723 mInterface.setActiveDeviceToDeviceTransport(arg);
724 } catch (RemoteException e) {
725 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
726 errPw.println("Exception: " + e.getMessage());
727 return -1;
728 }
729 return 0;
730 }
731
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700732 // ims set-ims-service
733 private int handleImsSetServiceCommand() {
734 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700735 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700736 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800737 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700738
739 String opt;
740 while ((opt = getNextOption()) != null) {
741 switch (opt) {
742 case "-s": {
743 try {
744 slotId = Integer.parseInt(getNextArgRequired());
745 } catch (NumberFormatException e) {
746 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
747 return -1;
748 }
749 break;
750 }
751 case "-c": {
752 isCarrierService = true;
753 break;
754 }
755 case "-d": {
756 isCarrierService = false;
757 break;
758 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800759 case "-f": {
760 String featureString = getNextArgRequired();
761 String[] features = featureString.split(",");
762 for (int i = 0; i < features.length; i++) {
763 try {
764 Integer result = Integer.parseInt(features[i]);
765 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
766 || result >= ImsFeature.FEATURE_MAX) {
767 errPw.println("ims set-ims-service -f " + result
768 + " is an invalid feature.");
769 return -1;
770 }
771 featuresList.add(result);
772 } catch (NumberFormatException e) {
773 errPw.println("ims set-ims-service -f tried to parse " + features[i]
774 + " as an integer.");
775 return -1;
776 }
777 }
778 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700779 }
780 }
781 // Mandatory param, either -c or -d
782 if (isCarrierService == null) {
783 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
784 return -1;
785 }
786
787 String packageName = getNextArg();
788
789 try {
790 if (packageName == null) {
791 packageName = "";
792 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800793 int[] featureArray = new int[featuresList.size()];
794 for (int i = 0; i < featuresList.size(); i++) {
795 featureArray[i] = featuresList.get(i);
796 }
797 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
798 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700799 if (VDBG) {
800 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800801 + (isCarrierService ? "-c " : "-d ")
802 + "-f " + featuresList + " "
803 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700804 }
805 getOutPrintWriter().println(result);
806 } catch (RemoteException e) {
807 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800808 + (isCarrierService ? "-c " : "-d ")
809 + "-f " + featuresList + " "
810 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700811 errPw.println("Exception: " + e.getMessage());
812 return -1;
813 }
814 return 0;
815 }
816
Brad Ebinger999d3302020-11-25 14:31:39 -0800817 // ims clear-ims-service-override
818 private int handleImsClearCarrierServiceCommand() {
819 PrintWriter errPw = getErrPrintWriter();
820 int slotId = getDefaultSlot();
821
822 String opt;
823 while ((opt = getNextOption()) != null) {
824 switch (opt) {
825 case "-s": {
826 try {
827 slotId = Integer.parseInt(getNextArgRequired());
828 } catch (NumberFormatException e) {
829 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
830 return -1;
831 }
832 break;
833 }
834 }
835 }
836
837 try {
838 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
839 if (VDBG) {
840 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
841 + ", result=" + result);
842 }
843 getOutPrintWriter().println(result);
844 } catch (RemoteException e) {
845 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
846 + ", error" + e.getMessage());
847 errPw.println("Exception: " + e.getMessage());
848 return -1;
849 }
850 return 0;
851 }
852
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700853 // ims get-ims-service
854 private int handleImsGetServiceCommand() {
855 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700856 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700857 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800858 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700859
860 String opt;
861 while ((opt = getNextOption()) != null) {
862 switch (opt) {
863 case "-s": {
864 try {
865 slotId = Integer.parseInt(getNextArgRequired());
866 } catch (NumberFormatException e) {
867 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
868 return -1;
869 }
870 break;
871 }
872 case "-c": {
873 isCarrierService = true;
874 break;
875 }
876 case "-d": {
877 isCarrierService = false;
878 break;
879 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800880 case "-f": {
881 try {
882 featureType = Integer.parseInt(getNextArg());
883 } catch (NumberFormatException e) {
884 errPw.println("ims get-ims-service -f requires valid integer as feature.");
885 return -1;
886 }
887 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
888 || featureType >= ImsFeature.FEATURE_MAX) {
889 errPw.println("ims get-ims-service -f invalid feature.");
890 return -1;
891 }
892 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700893 }
894 }
895 // Mandatory param, either -c or -d
896 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800897 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700898 return -1;
899 }
900
901 String result;
902 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800903 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700904 } catch (RemoteException e) {
905 return -1;
906 }
907 if (VDBG) {
908 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800909 + (isCarrierService ? "-c " : "-d ")
910 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
911 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700912 }
913 getOutPrintWriter().println(result);
914 return 0;
915 }
916
917 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700918 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700919 String opt;
920 while ((opt = getNextOption()) != null) {
921 switch (opt) {
922 case "-s": {
923 try {
924 slotId = Integer.parseInt(getNextArgRequired());
925 } catch (NumberFormatException e) {
926 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
927 return -1;
928 }
929 break;
930 }
931 }
932 }
933 try {
934 mInterface.enableIms(slotId);
935 } catch (RemoteException e) {
936 return -1;
937 }
938 if (VDBG) {
939 Log.v(LOG_TAG, "ims enable -s " + slotId);
940 }
941 return 0;
942 }
943
944 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700945 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700946 String opt;
947 while ((opt = getNextOption()) != null) {
948 switch (opt) {
949 case "-s": {
950 try {
951 slotId = Integer.parseInt(getNextArgRequired());
952 } catch (NumberFormatException e) {
953 getErrPrintWriter().println(
954 "ims disable requires an integer as a SLOT_ID.");
955 return -1;
956 }
957 break;
958 }
959 }
960 }
961 try {
962 mInterface.disableIms(slotId);
963 } catch (RemoteException e) {
964 return -1;
965 }
966 if (VDBG) {
967 Log.v(LOG_TAG, "ims disable -s " + slotId);
968 }
969 return 0;
970 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700971
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700972 private int handleCepChange() {
973 Log.i(LOG_TAG, "handleCepChange");
974 String opt = getNextArg();
975 if (opt == null) {
976 return -1;
977 }
978 boolean isCepEnabled = opt.equals("enable");
979
980 try {
981 mInterface.setCepEnabled(isCepEnabled);
982 } catch (RemoteException e) {
983 return -1;
984 }
985 return 0;
986 }
987
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700988 private int getDefaultSlot() {
989 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
990 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
991 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
992 // If there is no default, default to slot 0.
993 slotId = DEFAULT_PHONE_ID;
994 }
995 return slotId;
996 }
sqian2fff4a32018-11-05 14:18:37 -0800997
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100998 // Parse options related to Carrier Config Commands.
999 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001000 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001001 CcOptionParseResult result = new CcOptionParseResult();
1002 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1003 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001004
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001005 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001006 while ((opt = getNextOption()) != null) {
1007 switch (opt) {
1008 case "-s": {
1009 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001010 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1011 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1012 errPw.println(tag + "No valid subscription found.");
1013 return null;
1014 }
1015
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001016 } catch (IllegalArgumentException e) {
1017 // Missing slot id
1018 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001019 return null;
1020 }
1021 break;
1022 }
1023 case "-p": {
1024 if (allowOptionPersistent) {
1025 result.mPersistent = true;
1026 } else {
1027 errPw.println(tag + "Unexpected option " + opt);
1028 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001029 }
1030 break;
1031 }
1032 default: {
1033 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001034 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001035 }
1036 }
1037 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001038 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001039 }
1040
1041 private int slotStringToSubId(String tag, String slotString) {
1042 int slotId = -1;
1043 try {
1044 slotId = Integer.parseInt(slotString);
1045 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001046 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1047 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1048 }
1049
1050 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001051 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1052 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1053 }
1054
Qiong Liuf25799b2020-09-10 10:13:46 +08001055 Phone phone = PhoneFactory.getPhone(slotId);
1056 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001057 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1058 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1059 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001060 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001061 }
1062
Hall Liud892bec2018-11-30 14:51:45 -08001063 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001064 // adb can run as root or as shell, depending on whether the device is rooted.
1065 return Binder.getCallingUid() == Process.SHELL_UID
1066 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001067 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001068
1069 private int handleCcCommand() {
1070 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1071 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001072 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001073 getErrPrintWriter().println("cc: Permission denied.");
1074 return -1;
1075 }
1076
1077 String arg = getNextArg();
1078 if (arg == null) {
1079 onHelpCc();
1080 return 0;
1081 }
1082
1083 switch (arg) {
1084 case CC_GET_VALUE: {
1085 return handleCcGetValue();
1086 }
1087 case CC_SET_VALUE: {
1088 return handleCcSetValue();
1089 }
1090 case CC_CLEAR_VALUES: {
1091 return handleCcClearValues();
1092 }
1093 default: {
1094 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1095 }
1096 }
1097 return -1;
1098 }
1099
1100 // cc get-value
1101 private int handleCcGetValue() {
1102 PrintWriter errPw = getErrPrintWriter();
1103 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1104 String key = null;
1105
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001106 // Parse all options
1107 CcOptionParseResult options = parseCcOptions(tag, false);
1108 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001109 return -1;
1110 }
1111
1112 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001113 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001114 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001115 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001116 return -1;
1117 }
1118
1119 // Get the key.
1120 key = getNextArg();
1121 if (key != null) {
1122 // A key was provided. Verify if it is a valid key
1123 if (!bundle.containsKey(key)) {
1124 errPw.println(tag + key + " is not a valid key.");
1125 return -1;
1126 }
1127
1128 // Print the carrier config value for key.
1129 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1130 } else {
1131 // No key provided. Show all values.
1132 // Iterate over a sorted list of all carrier config keys and print them.
1133 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1134 for (String k : sortedSet) {
1135 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1136 }
1137 }
1138 return 0;
1139 }
1140
1141 // cc set-value
1142 private int handleCcSetValue() {
1143 PrintWriter errPw = getErrPrintWriter();
1144 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1145
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001146 // Parse all options
1147 CcOptionParseResult options = parseCcOptions(tag, true);
1148 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001149 return -1;
1150 }
1151
1152 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001153 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001154 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001155 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001156 return -1;
1157 }
1158
1159 // Get the key.
1160 String key = getNextArg();
1161 if (key == null || key.equals("")) {
1162 errPw.println(tag + "KEY is missing");
1163 return -1;
1164 }
1165
1166 // Verify if the key is valid
1167 if (!originalValues.containsKey(key)) {
1168 errPw.println(tag + key + " is not a valid key.");
1169 return -1;
1170 }
1171
1172 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1173 ArrayList<String> valueList = new ArrayList<String>();
1174 while (peekNextArg() != null) {
1175 valueList.add(getNextArg());
1176 }
1177
1178 // Find the type of the carrier config value
1179 CcType type = getType(tag, key, originalValues);
1180 if (type == CcType.UNKNOWN) {
1181 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1182 return -1;
1183 }
1184
1185 // Create an override bundle containing the key and value that should be overriden.
1186 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1187 if (overrideBundle == null) {
1188 return -1;
1189 }
1190
1191 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001192 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001193
1194 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001195 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001196 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001197 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001198 return -1;
1199 }
1200
1201 // Print the original and new value.
1202 String originalValueString = ccValueToString(key, type, originalValues);
1203 String newValueString = ccValueToString(key, type, newValues);
1204 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1205 getOutPrintWriter().println("New value: \n" + newValueString);
1206
1207 return 0;
1208 }
1209
1210 // cc clear-values
1211 private int handleCcClearValues() {
1212 PrintWriter errPw = getErrPrintWriter();
1213 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1214
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001215 // Parse all options
1216 CcOptionParseResult options = parseCcOptions(tag, false);
1217 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001218 return -1;
1219 }
1220
1221 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001222 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001223 getOutPrintWriter()
1224 .println("All previously set carrier config override values has been cleared");
1225 return 0;
1226 }
1227
1228 private CcType getType(String tag, String key, PersistableBundle bundle) {
1229 // Find the type by checking the type of the current value stored in the bundle.
1230 Object value = bundle.get(key);
1231
1232 if (CC_TYPE_MAP.containsKey(key)) {
1233 return CC_TYPE_MAP.get(key);
1234 } else if (value != null) {
1235 if (value instanceof Boolean) {
1236 return CcType.BOOLEAN;
1237 } else if (value instanceof Double) {
1238 return CcType.DOUBLE;
1239 } else if (value instanceof double[]) {
1240 return CcType.DOUBLE_ARRAY;
1241 } else if (value instanceof Integer) {
1242 return CcType.INT;
1243 } else if (value instanceof int[]) {
1244 return CcType.INT_ARRAY;
1245 } else if (value instanceof Long) {
1246 return CcType.LONG;
1247 } else if (value instanceof long[]) {
1248 return CcType.LONG_ARRAY;
1249 } else if (value instanceof String) {
1250 return CcType.STRING;
1251 } else if (value instanceof String[]) {
1252 return CcType.STRING_ARRAY;
1253 }
1254 } else {
1255 // Current value was null and can therefore not be used in order to find the type.
1256 // Check the name of the key to infer the type. This check is not needed for primitive
1257 // data types (boolean, double, int and long), since they can not be null.
1258 if (key.endsWith("double_array")) {
1259 return CcType.DOUBLE_ARRAY;
1260 }
1261 if (key.endsWith("int_array")) {
1262 return CcType.INT_ARRAY;
1263 }
1264 if (key.endsWith("long_array")) {
1265 return CcType.LONG_ARRAY;
1266 }
1267 if (key.endsWith("string")) {
1268 return CcType.STRING;
1269 }
1270 if (key.endsWith("string_array") || key.endsWith("strings")) {
1271 return CcType.STRING_ARRAY;
1272 }
1273 }
1274
1275 // Not possible to infer the type by looking at the current value or the key.
1276 PrintWriter errPw = getErrPrintWriter();
1277 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1278 return CcType.UNKNOWN;
1279 }
1280
1281 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1282 String result;
1283 StringBuilder valueString = new StringBuilder();
1284 String typeString = type.toString();
1285 Object value = bundle.get(key);
1286
1287 if (value == null) {
1288 valueString.append("null");
1289 } else {
1290 switch (type) {
1291 case DOUBLE_ARRAY: {
1292 // Format the string representation of the int array as value1 value2......
1293 double[] valueArray = (double[]) value;
1294 for (int i = 0; i < valueArray.length; i++) {
1295 if (i != 0) {
1296 valueString.append(" ");
1297 }
1298 valueString.append(valueArray[i]);
1299 }
1300 break;
1301 }
1302 case INT_ARRAY: {
1303 // Format the string representation of the int array as value1 value2......
1304 int[] valueArray = (int[]) value;
1305 for (int i = 0; i < valueArray.length; i++) {
1306 if (i != 0) {
1307 valueString.append(" ");
1308 }
1309 valueString.append(valueArray[i]);
1310 }
1311 break;
1312 }
1313 case LONG_ARRAY: {
1314 // Format the string representation of the int array as value1 value2......
1315 long[] valueArray = (long[]) value;
1316 for (int i = 0; i < valueArray.length; i++) {
1317 if (i != 0) {
1318 valueString.append(" ");
1319 }
1320 valueString.append(valueArray[i]);
1321 }
1322 break;
1323 }
1324 case STRING: {
1325 valueString.append("\"" + value.toString() + "\"");
1326 break;
1327 }
1328 case STRING_ARRAY: {
1329 // Format the string representation of the string array as "value1" "value2"....
1330 String[] valueArray = (String[]) value;
1331 for (int i = 0; i < valueArray.length; i++) {
1332 if (i != 0) {
1333 valueString.append(" ");
1334 }
1335 if (valueArray[i] != null) {
1336 valueString.append("\"" + valueArray[i] + "\"");
1337 } else {
1338 valueString.append("null");
1339 }
1340 }
1341 break;
1342 }
1343 default: {
1344 valueString.append(value.toString());
1345 }
1346 }
1347 }
1348 return String.format("%-70s %-15s %s", key, typeString, valueString);
1349 }
1350
1351 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1352 ArrayList<String> valueList) {
1353 PrintWriter errPw = getErrPrintWriter();
1354 PersistableBundle bundle = new PersistableBundle();
1355
1356 // First verify that a valid number of values has been provided for the type.
1357 switch (type) {
1358 case BOOLEAN:
1359 case DOUBLE:
1360 case INT:
1361 case LONG: {
1362 if (valueList.size() != 1) {
1363 errPw.println(tag + "Expected 1 value for type " + type
1364 + ". Found: " + valueList.size());
1365 return null;
1366 }
1367 break;
1368 }
1369 case STRING: {
1370 if (valueList.size() > 1) {
1371 errPw.println(tag + "Expected 0 or 1 values for type " + type
1372 + ". Found: " + valueList.size());
1373 return null;
1374 }
1375 break;
1376 }
1377 }
1378
1379 // Parse the value according to type and add it to the Bundle.
1380 switch (type) {
1381 case BOOLEAN: {
1382 if ("true".equalsIgnoreCase(valueList.get(0))) {
1383 bundle.putBoolean(key, true);
1384 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1385 bundle.putBoolean(key, false);
1386 } else {
1387 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1388 return null;
1389 }
1390 break;
1391 }
1392 case DOUBLE: {
1393 try {
1394 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1395 } catch (NumberFormatException nfe) {
1396 // Not a valid double
1397 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1398 return null;
1399 }
1400 break;
1401 }
1402 case DOUBLE_ARRAY: {
1403 double[] valueDoubleArray = null;
1404 if (valueList.size() > 0) {
1405 valueDoubleArray = new double[valueList.size()];
1406 for (int i = 0; i < valueList.size(); i++) {
1407 try {
1408 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1409 } catch (NumberFormatException nfe) {
1410 // Not a valid double
1411 errPw.println(
1412 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1413 return null;
1414 }
1415 }
1416 }
1417 bundle.putDoubleArray(key, valueDoubleArray);
1418 break;
1419 }
1420 case INT: {
1421 try {
1422 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1423 } catch (NumberFormatException nfe) {
1424 // Not a valid integer
1425 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1426 return null;
1427 }
1428 break;
1429 }
1430 case INT_ARRAY: {
1431 int[] valueIntArray = null;
1432 if (valueList.size() > 0) {
1433 valueIntArray = new int[valueList.size()];
1434 for (int i = 0; i < valueList.size(); i++) {
1435 try {
1436 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1437 } catch (NumberFormatException nfe) {
1438 // Not a valid integer
1439 errPw.println(tag
1440 + "Unable to parse " + valueList.get(i) + " as an integer.");
1441 return null;
1442 }
1443 }
1444 }
1445 bundle.putIntArray(key, valueIntArray);
1446 break;
1447 }
1448 case LONG: {
1449 try {
1450 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1451 } catch (NumberFormatException nfe) {
1452 // Not a valid long
1453 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1454 return null;
1455 }
1456 break;
1457 }
1458 case LONG_ARRAY: {
1459 long[] valueLongArray = null;
1460 if (valueList.size() > 0) {
1461 valueLongArray = new long[valueList.size()];
1462 for (int i = 0; i < valueList.size(); i++) {
1463 try {
1464 valueLongArray[i] = Long.parseLong(valueList.get(i));
1465 } catch (NumberFormatException nfe) {
1466 // Not a valid long
1467 errPw.println(
1468 tag + "Unable to parse " + valueList.get(i) + " as a long");
1469 return null;
1470 }
1471 }
1472 }
1473 bundle.putLongArray(key, valueLongArray);
1474 break;
1475 }
1476 case STRING: {
1477 String value = null;
1478 if (valueList.size() > 0) {
1479 value = valueList.get(0);
1480 }
1481 bundle.putString(key, value);
1482 break;
1483 }
1484 case STRING_ARRAY: {
1485 String[] valueStringArray = null;
1486 if (valueList.size() > 0) {
1487 valueStringArray = new String[valueList.size()];
1488 valueList.toArray(valueStringArray);
1489 }
1490 bundle.putStringArray(key, valueStringArray);
1491 break;
1492 }
1493 }
1494 return bundle;
1495 }
Shuo Qian489d9282020-07-09 11:30:03 -07001496
1497 private int handleEndBlockSuppressionCommand() {
1498 if (!checkShellUid()) {
1499 return -1;
1500 }
1501
1502 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1503 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1504 }
1505 return 0;
1506 }
Hui Wang641e81c2020-10-12 12:14:23 -07001507
Michele Berionne54af4632020-12-28 20:23:16 +00001508 private int handleRestartModemCommand() {
1509 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1510 // non user build.
1511 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1512 getErrPrintWriter().println("RestartModem: Permission denied.");
1513 return -1;
1514 }
1515
1516 boolean result = TelephonyManager.getDefault().rebootRadio();
1517 getOutPrintWriter().println(result);
1518
1519 return result ? 0 : -1;
1520 }
1521
Michele Berionne5e411512020-11-13 02:36:59 +00001522 private int handleUnattendedReboot() {
1523 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1524 // non user build.
1525 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1526 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1527 return -1;
1528 }
1529
1530 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1531 getOutPrintWriter().println("result: " + result);
1532
1533 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1534 }
1535
Hui Wang641e81c2020-10-12 12:14:23 -07001536 private int handleGbaCommand() {
1537 String arg = getNextArg();
1538 if (arg == null) {
1539 onHelpGba();
1540 return 0;
1541 }
1542
1543 switch (arg) {
1544 case GBA_SET_SERVICE: {
1545 return handleGbaSetServiceCommand();
1546 }
1547 case GBA_GET_SERVICE: {
1548 return handleGbaGetServiceCommand();
1549 }
1550 case GBA_SET_RELEASE_TIME: {
1551 return handleGbaSetReleaseCommand();
1552 }
1553 case GBA_GET_RELEASE_TIME: {
1554 return handleGbaGetReleaseCommand();
1555 }
1556 }
1557
1558 return -1;
1559 }
1560
1561 private int getSubId(String cmd) {
1562 int slotId = getDefaultSlot();
1563 String opt = getNextOption();
1564 if (opt != null && opt.equals("-s")) {
1565 try {
1566 slotId = Integer.parseInt(getNextArgRequired());
1567 } catch (NumberFormatException e) {
1568 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1569 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1570 }
1571 }
1572 int[] subIds = SubscriptionManager.getSubId(slotId);
1573 return subIds[0];
1574 }
1575
1576 private int handleGbaSetServiceCommand() {
1577 int subId = getSubId("gba set-service");
1578 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1579 return -1;
1580 }
1581
1582 String packageName = getNextArg();
1583 try {
1584 if (packageName == null) {
1585 packageName = "";
1586 }
1587 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1588 if (VDBG) {
1589 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1590 + packageName + ", result=" + result);
1591 }
1592 getOutPrintWriter().println(result);
1593 } catch (RemoteException e) {
1594 Log.w(LOG_TAG, "gba set-service " + subId + " "
1595 + packageName + ", error" + e.getMessage());
1596 getErrPrintWriter().println("Exception: " + e.getMessage());
1597 return -1;
1598 }
1599 return 0;
1600 }
1601
1602 private int handleGbaGetServiceCommand() {
1603 String result;
1604
1605 int subId = getSubId("gba get-service");
1606 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1607 return -1;
1608 }
1609
1610 try {
1611 result = mInterface.getBoundGbaService(subId);
1612 } catch (RemoteException e) {
1613 return -1;
1614 }
1615 if (VDBG) {
1616 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1617 }
1618 getOutPrintWriter().println(result);
1619 return 0;
1620 }
1621
1622 private int handleGbaSetReleaseCommand() {
1623 //the release time value could be -1
1624 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1625 : SubscriptionManager.getDefaultSubscriptionId();
1626 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1627 return -1;
1628 }
1629
1630 String intervalStr = getNextArg();
1631 if (intervalStr == null) {
1632 return -1;
1633 }
1634
1635 try {
1636 int interval = Integer.parseInt(intervalStr);
1637 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1638 if (VDBG) {
1639 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1640 + intervalStr + ", result=" + result);
1641 }
1642 getOutPrintWriter().println(result);
1643 } catch (NumberFormatException | RemoteException e) {
1644 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1645 + intervalStr + ", error" + e.getMessage());
1646 getErrPrintWriter().println("Exception: " + e.getMessage());
1647 return -1;
1648 }
1649 return 0;
1650 }
1651
1652 private int handleGbaGetReleaseCommand() {
1653 int subId = getSubId("gba get-release");
1654 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1655 return -1;
1656 }
1657
1658 int result = 0;
1659 try {
1660 result = mInterface.getGbaReleaseTime(subId);
1661 } catch (RemoteException e) {
1662 return -1;
1663 }
1664 if (VDBG) {
1665 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1666 }
1667 getOutPrintWriter().println(result);
1668 return 0;
1669 }
Hui Wang761a6682020-10-31 05:12:53 +00001670
1671 private int handleSingleRegistrationConfigCommand() {
1672 String arg = getNextArg();
1673 if (arg == null) {
1674 onHelpSrc();
1675 return 0;
1676 }
1677
1678 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001679 case SRC_SET_TEST_ENABLED: {
1680 return handleSrcSetTestEnabledCommand();
1681 }
1682 case SRC_GET_TEST_ENABLED: {
1683 return handleSrcGetTestEnabledCommand();
1684 }
Hui Wang761a6682020-10-31 05:12:53 +00001685 case SRC_SET_DEVICE_ENABLED: {
1686 return handleSrcSetDeviceEnabledCommand();
1687 }
1688 case SRC_GET_DEVICE_ENABLED: {
1689 return handleSrcGetDeviceEnabledCommand();
1690 }
1691 case SRC_SET_CARRIER_ENABLED: {
1692 return handleSrcSetCarrierEnabledCommand();
1693 }
1694 case SRC_GET_CARRIER_ENABLED: {
1695 return handleSrcGetCarrierEnabledCommand();
1696 }
1697 }
1698
1699 return -1;
1700 }
1701
James.cf Linbcdf8b32021-01-14 16:44:13 +08001702 private int handleRcsUceCommand() {
1703 String arg = getNextArg();
1704 if (arg == null) {
1705 Log.w(LOG_TAG, "cannot get uce parameter");
1706 return -1;
1707 }
1708
1709 switch (arg) {
1710 case UCE_REMOVE_EAB_CONTACT:
1711 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001712 case UCE_GET_EAB_CONTACT:
1713 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001714 case UCE_GET_DEVICE_ENABLED:
1715 return handleUceGetDeviceEnabledCommand();
1716 case UCE_SET_DEVICE_ENABLED:
1717 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001718 }
1719 return -1;
1720 }
1721
1722 private int handleRemovingEabContactCommand() {
1723 int subId = getSubId("uce remove-eab-contact");
1724 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1725 return -1;
1726 }
1727
1728 String phoneNumber = getNextArgRequired();
1729 if (TextUtils.isEmpty(phoneNumber)) {
1730 return -1;
1731 }
1732 int result = 0;
1733 try {
1734 result = mInterface.removeContactFromEab(subId, phoneNumber);
1735 } catch (RemoteException e) {
1736 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1737 getErrPrintWriter().println("Exception: " + e.getMessage());
1738 return -1;
1739 }
1740
1741 if (VDBG) {
1742 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1743 }
calvinpan293ea1b2021-02-04 17:52:13 +08001744 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001745 }
1746
calvinpane4a8a1d2021-01-25 13:51:18 +08001747 private int handleGettingEabContactCommand() {
1748 String phoneNumber = getNextArgRequired();
1749 if (TextUtils.isEmpty(phoneNumber)) {
1750 return -1;
1751 }
1752 String result = "";
1753 try {
1754 result = mInterface.getContactFromEab(phoneNumber);
1755
1756 } catch (RemoteException e) {
1757 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1758 getErrPrintWriter().println("Exception: " + e.getMessage());
1759 return -1;
1760 }
1761
1762 if (VDBG) {
1763 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1764 }
calvinpan293ea1b2021-02-04 17:52:13 +08001765 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001766 return 0;
1767 }
1768
1769 private int handleUceGetDeviceEnabledCommand() {
1770 boolean result = false;
1771 try {
1772 result = mInterface.getDeviceUceEnabled();
1773 } catch (RemoteException e) {
1774 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1775 return -1;
1776 }
1777 if (VDBG) {
1778 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1779 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001780 getOutPrintWriter().println(result);
1781 return 0;
1782 }
1783
James.cf Lin4b784aa2021-01-31 03:25:15 +08001784 private int handleUceSetDeviceEnabledCommand() {
1785 String enabledStr = getNextArg();
1786 if (TextUtils.isEmpty(enabledStr)) {
1787 return -1;
1788 }
1789
1790 try {
1791 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1792 mInterface.setDeviceUceEnabled(isEnabled);
1793 if (VDBG) {
1794 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1795 }
1796 } catch (NumberFormatException | RemoteException e) {
1797 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1798 getErrPrintWriter().println("Exception: " + e.getMessage());
1799 return -1;
1800 }
1801 return 0;
1802 }
1803
Hui Wangbaaee6a2021-02-19 20:45:36 -08001804 private int handleSrcSetTestEnabledCommand() {
1805 String enabledStr = getNextArg();
1806 if (enabledStr == null) {
1807 return -1;
1808 }
1809
1810 try {
1811 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1812 if (VDBG) {
1813 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1814 }
1815 getOutPrintWriter().println("Done");
1816 } catch (NumberFormatException | RemoteException e) {
1817 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1818 getErrPrintWriter().println("Exception: " + e.getMessage());
1819 return -1;
1820 }
1821 return 0;
1822 }
1823
1824 private int handleSrcGetTestEnabledCommand() {
1825 boolean result = false;
1826 try {
1827 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1828 } catch (RemoteException e) {
1829 return -1;
1830 }
1831 if (VDBG) {
1832 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1833 }
1834 getOutPrintWriter().println(result);
1835 return 0;
1836 }
1837
Hui Wang761a6682020-10-31 05:12:53 +00001838 private int handleSrcSetDeviceEnabledCommand() {
1839 String enabledStr = getNextArg();
1840 if (enabledStr == null) {
1841 return -1;
1842 }
1843
1844 try {
1845 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1846 if (VDBG) {
1847 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1848 }
1849 getOutPrintWriter().println("Done");
1850 } catch (NumberFormatException | RemoteException e) {
1851 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1852 getErrPrintWriter().println("Exception: " + e.getMessage());
1853 return -1;
1854 }
1855 return 0;
1856 }
1857
1858 private int handleSrcGetDeviceEnabledCommand() {
1859 boolean result = false;
1860 try {
1861 result = mInterface.getDeviceSingleRegistrationEnabled();
1862 } catch (RemoteException e) {
1863 return -1;
1864 }
1865 if (VDBG) {
1866 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1867 }
1868 getOutPrintWriter().println(result);
1869 return 0;
1870 }
1871
1872 private int handleSrcSetCarrierEnabledCommand() {
1873 //the release time value could be -1
1874 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1875 : SubscriptionManager.getDefaultSubscriptionId();
1876 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1877 return -1;
1878 }
1879
1880 String enabledStr = getNextArg();
1881 if (enabledStr == null) {
1882 return -1;
1883 }
1884
1885 try {
1886 boolean result =
1887 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1888 if (VDBG) {
1889 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1890 + enabledStr + ", result=" + result);
1891 }
1892 getOutPrintWriter().println(result);
1893 } catch (NumberFormatException | RemoteException e) {
1894 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1895 + enabledStr + ", error" + e.getMessage());
1896 getErrPrintWriter().println("Exception: " + e.getMessage());
1897 return -1;
1898 }
1899 return 0;
1900 }
1901
1902 private int handleSrcGetCarrierEnabledCommand() {
1903 int subId = getSubId("src get-carrier-enabled");
1904 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1905 return -1;
1906 }
1907
1908 boolean result = false;
1909 try {
1910 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1911 } catch (RemoteException e) {
1912 return -1;
1913 }
1914 if (VDBG) {
1915 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1916 }
1917 getOutPrintWriter().println(result);
1918 return 0;
1919 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001920
1921 private void onHelpCallComposer() {
1922 PrintWriter pw = getOutPrintWriter();
1923 pw.println("Call composer commands");
1924 pw.println(" callcomposer test-mode enable|disable|query");
1925 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1926 pw.println(" upload/download from carrier servers is disabled, and operations are");
1927 pw.println(" performed using emulated local files instead.");
1928 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1929 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1930 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08001931 pw.println(" callcomposer user-setting [subId] enable|disable|query");
1932 pw.println(" Enables or disables the user setting for call composer, as set by");
1933 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08001934 }
1935
1936 private int handleCallComposerCommand() {
1937 String arg = getNextArg();
1938 if (arg == null) {
1939 onHelpCallComposer();
1940 return 0;
1941 }
1942
1943 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1944 "MODIFY_PHONE_STATE required for call composer shell cmds");
1945 switch (arg) {
1946 case CALL_COMPOSER_TEST_MODE: {
1947 String enabledStr = getNextArg();
1948 if (ENABLE.equals(enabledStr)) {
1949 CallComposerPictureManager.sTestMode = true;
1950 } else if (DISABLE.equals(enabledStr)) {
1951 CallComposerPictureManager.sTestMode = false;
1952 } else if (QUERY.equals(enabledStr)) {
1953 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1954 } else {
1955 onHelpCallComposer();
1956 return 1;
1957 }
1958 break;
1959 }
1960 case CALL_COMPOSER_SIMULATE_CALL: {
1961 int subscriptionId = Integer.valueOf(getNextArg());
1962 String uuidString = getNextArg();
1963 UUID uuid = UUID.fromString(uuidString);
1964 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1965 Binder.withCleanCallingIdentity(() -> {
1966 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1967 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1968 });
1969 try {
1970 Uri uri = storageUriFuture.get();
1971 getOutPrintWriter().println(String.valueOf(uri));
1972 } catch (Exception e) {
1973 throw new RuntimeException(e);
1974 }
1975 break;
1976 }
Hall Liu7917ecf2021-02-23 12:22:31 -08001977 case CALL_COMPOSER_USER_SETTING: {
1978 try {
1979 int subscriptionId = Integer.valueOf(getNextArg());
1980 String enabledStr = getNextArg();
1981 if (ENABLE.equals(enabledStr)) {
1982 mInterface.setCallComposerStatus(subscriptionId,
1983 TelephonyManager.CALL_COMPOSER_STATUS_ON);
1984 } else if (DISABLE.equals(enabledStr)) {
1985 mInterface.setCallComposerStatus(subscriptionId,
1986 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
1987 } else if (QUERY.equals(enabledStr)) {
1988 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
1989 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
1990 } else {
1991 onHelpCallComposer();
1992 return 1;
1993 }
1994 } catch (RemoteException e) {
1995 e.printStackTrace(getOutPrintWriter());
1996 return 1;
1997 }
1998 break;
1999 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002000 }
2001
2002 return 0;
2003 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002004}