blob: 47666ef26bce6aab31958731909553a37a5094ca [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
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800128 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
129 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
130
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700131 // Take advantage of existing methods that already contain permissions checks when possible.
132 private final ITelephony mInterface;
133
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100134 private SubscriptionManager mSubscriptionManager;
135 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700136 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100137
138 private enum CcType {
139 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
140 STRING_ARRAY, UNKNOWN
141 }
142
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100143 private class CcOptionParseResult {
144 public int mSubId;
145 public boolean mPersistent;
146 }
147
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100148 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
149 // keys by looking at the end of the string which usually tells the type.
150 // For instance: "xxxx_string", "xxxx_string_array", etc.
151 // The carrier config keys in this map does not follow this convention. It is therefore not
152 // possible to infer the type for these keys by looking at the string.
153 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
154 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
157 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
158 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
159 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
160 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
161 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
162 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
163 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
164 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
165 CcType.STRING);
166 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
167 CcType.STRING_ARRAY);
168 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
169 CcType.STRING_ARRAY);
170 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
171 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
172 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
173 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
174 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
175 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
176 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
177 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
178 }
179 };
180
181 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700182 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100183 mCarrierConfigManager =
184 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
185 mSubscriptionManager = (SubscriptionManager)
186 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700187 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700188 }
189
190 @Override
191 public int onCommand(String cmd) {
192 if (cmd == null) {
193 return handleDefaultCommands(null);
194 }
195
196 switch (cmd) {
197 case IMS_SUBCOMMAND: {
198 return handleImsCommand();
199 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800200 case RCS_UCE_COMMAND:
201 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800202 case NUMBER_VERIFICATION_SUBCOMMAND:
203 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800204 case EMERGENCY_CALLBACK_MODE:
205 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800206 case EMERGENCY_NUMBER_TEST_MODE:
207 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100208 case CARRIER_CONFIG_SUBCOMMAND: {
209 return handleCcCommand();
210 }
Shuo Qianf5125122019-12-16 17:03:07 -0800211 case DATA_TEST_MODE:
212 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700213 case END_BLOCK_SUPPRESSION:
214 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700215 case GBA_SUBCOMMAND:
216 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800217 case D2D_SUBCOMMAND:
218 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000219 case SINGLE_REGISTATION_CONFIG:
220 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000221 case RESTART_MODEM:
222 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800223 case CALL_COMPOSER_SUBCOMMAND:
224 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000225 case UNATTENDED_REBOOT:
226 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800227 case HAS_CARRIER_PRIVILEGES_COMMAND:
228 return handleHasCarrierPrivilegesCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700229 default: {
230 return handleDefaultCommands(cmd);
231 }
232 }
233 }
234
235 @Override
236 public void onHelp() {
237 PrintWriter pw = getOutPrintWriter();
238 pw.println("Telephony Commands:");
239 pw.println(" help");
240 pw.println(" Print this help text.");
241 pw.println(" ims");
242 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800243 pw.println(" uce");
244 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800245 pw.println(" emergency-number-test-mode");
246 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700247 pw.println(" end-block-suppression");
248 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800249 pw.println(" data");
250 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100251 pw.println(" cc");
252 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700253 pw.println(" gba");
254 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000255 pw.println(" src");
256 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000257 pw.println(" restart-modem");
258 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000259 pw.println(" unattended-reboot");
260 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800261 pw.println(" has-carrier-privileges [package]");
262 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700263 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800264 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800265 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700266 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800267 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100268 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700269 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000270 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800271 onHelpD2D();
272 }
273
274 private void onHelpD2D() {
275 PrintWriter pw = getOutPrintWriter();
276 pw.println("D2D Comms Commands:");
277 pw.println(" d2d send TYPE VALUE");
278 pw.println(" Sends a D2D message of specified type and value.");
279 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
280 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
281 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
282 MESSAGE_CALL_AUDIO_CODEC));
283 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
284 + Communicator.messageToString(
285 MESSAGE_DEVICE_BATTERY_STATE));
286 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
287 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800288 pw.println(" d2d transport TYPE");
289 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
290 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700291 }
292
293 private void onHelpIms() {
294 PrintWriter pw = getOutPrintWriter();
295 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800296 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700297 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
298 pw.println(" ImsService. Options are:");
299 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
300 pw.println(" is specified, it will choose the default voice SIM slot.");
301 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
302 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800303 pw.println(" -f: Set the feature that this override if for, if no option is");
304 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700305 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
306 pw.println(" Gets the package name of the currently defined ImsService.");
307 pw.println(" Options are:");
308 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
309 pw.println(" is specified, it will choose the default voice SIM slot.");
310 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000311 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800312 pw.println(" -f: The feature type that the query will be requested for. If none is");
313 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800314 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
315 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
316 pw.println(" configuration overrides. Options are:");
317 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
318 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700319 pw.println(" ims enable [-s SLOT_ID]");
320 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
321 pw.println(" if none is specified.");
322 pw.println(" ims disable [-s SLOT_ID]");
323 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
324 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700325 pw.println(" ims conference-event-package [enable/disable]");
326 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700327 }
328
James.cf Linbcdf8b32021-01-14 16:44:13 +0800329 private void onHelpUce() {
330 PrintWriter pw = getOutPrintWriter();
331 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800332 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
333 pw.println(" Get the EAB contacts from the EAB database.");
334 pw.println(" Options are:");
335 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
336 pw.println(" Expected output format :");
337 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800338 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
339 pw.println(" Remove the EAB contacts from the EAB database.");
340 pw.println(" Options are:");
341 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
342 pw.println(" is specified, it will choose the default voice SIM slot.");
343 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800344 pw.println(" uce get-device-enabled");
345 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
346 pw.println(" uce set-device-enabled true|false");
347 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
348 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800349 }
350
Hall Liud892bec2018-11-30 14:51:45 -0800351 private void onHelpNumberVerification() {
352 PrintWriter pw = getOutPrintWriter();
353 pw.println("Number verification commands");
354 pw.println(" numverify override-package PACKAGE_NAME;");
355 pw.println(" Set the authorized package for number verification.");
356 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800357 pw.println(" numverify fake-call NUMBER;");
358 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
359 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800360 }
361
Shuo Qianf5125122019-12-16 17:03:07 -0800362 private void onHelpDataTestMode() {
363 PrintWriter pw = getOutPrintWriter();
364 pw.println("Mobile Data Test Mode Commands:");
365 pw.println(" data enable: enable mobile data connectivity");
366 pw.println(" data disable: disable mobile data connectivity");
367 }
368
sqian9d4df8b2019-01-15 18:32:07 -0800369 private void onHelpEmergencyNumber() {
370 PrintWriter pw = getOutPrintWriter();
371 pw.println("Emergency Number Test Mode Commands:");
372 pw.println(" emergency-number-test-mode ");
373 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
374 + " the test mode");
375 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700376 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800377 pw.println(" -c: clear the emergency number list in the test mode.");
378 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700379 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800380 pw.println(" -p: get the full emergency number list in the test mode.");
381 }
382
Shuo Qian489d9282020-07-09 11:30:03 -0700383 private void onHelpEndBlockSupperssion() {
384 PrintWriter pw = getOutPrintWriter();
385 pw.println("End Block Suppression command:");
386 pw.println(" end-block-suppression: disable suppressing blocking by contact");
387 pw.println(" with emergency services.");
388 }
389
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100390 private void onHelpCc() {
391 PrintWriter pw = getOutPrintWriter();
392 pw.println("Carrier Config Commands:");
393 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
394 pw.println(" Print carrier config values.");
395 pw.println(" Options are:");
396 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
397 pw.println(" is specified, it will choose the default voice SIM slot.");
398 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
399 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100400 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100401 pw.println(" Set carrier config KEY to NEW_VALUE.");
402 pw.println(" Options are:");
403 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
404 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100405 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100406 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
407 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
408 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
409 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
410 pw.println(" cc clear-values [-s SLOT_ID]");
411 pw.println(" Clear all carrier override values that has previously been set");
412 pw.println(" with set-value");
413 pw.println(" Options are:");
414 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
415 pw.println(" is specified, it will choose the default voice SIM slot.");
416 }
417
Hui Wang641e81c2020-10-12 12:14:23 -0700418 private void onHelpGba() {
419 PrintWriter pw = getOutPrintWriter();
420 pw.println("Gba Commands:");
421 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
422 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
423 pw.println(" Options are:");
424 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
425 pw.println(" is specified, it will choose the default voice SIM slot.");
426 pw.println(" gba get-service [-s SLOT_ID]");
427 pw.println(" Gets the package name of the currently defined GbaService.");
428 pw.println(" Options are:");
429 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
430 pw.println(" is specified, it will choose the default voice SIM slot.");
431 pw.println(" gba set-release [-s SLOT_ID] n");
432 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
433 pw.println(" Do not release/unbind if n is -1.");
434 pw.println(" Options are:");
435 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
436 pw.println(" is specified, it will choose the default voice SIM slot.");
437 pw.println(" gba get-release [-s SLOT_ID]");
438 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
439 pw.println(" Options are:");
440 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
441 pw.println(" is specified, it will choose the default voice SIM slot.");
442 }
443
Hui Wang761a6682020-10-31 05:12:53 +0000444 private void onHelpSrc() {
445 PrintWriter pw = getOutPrintWriter();
446 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800447 pw.println(" src set-test-enabled true|false");
448 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
449 pw.println(" The value could be true, false, or null(undefined).");
450 pw.println(" src get-test-enabled");
451 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000452 pw.println(" src set-device-enabled true|false|null");
453 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
454 pw.println(" The value could be true, false, or null(undefined).");
455 pw.println(" src get-device-enabled");
456 pw.println(" Gets the device config for RCS VoLTE single registration.");
457 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
458 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
459 pw.println(" The value could be true, false, or null(undefined).");
460 pw.println(" Options are:");
461 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
462 pw.println(" is specified, it will choose the default voice SIM slot.");
463 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
464 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
465 pw.println(" Options are:");
466 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
467 pw.println(" is specified, it will choose the default voice SIM slot.");
468 }
469
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700470 private int handleImsCommand() {
471 String arg = getNextArg();
472 if (arg == null) {
473 onHelpIms();
474 return 0;
475 }
476
477 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800478 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700479 return handleImsSetServiceCommand();
480 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800481 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700482 return handleImsGetServiceCommand();
483 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800484 case IMS_CLEAR_SERVICE_OVERRIDE: {
485 return handleImsClearCarrierServiceCommand();
486 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800487 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700488 return handleEnableIms();
489 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800490 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700491 return handleDisableIms();
492 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700493 case IMS_CEP: {
494 return handleCepChange();
495 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700496 }
497
498 return -1;
499 }
500
Shuo Qianf5125122019-12-16 17:03:07 -0800501 private int handleDataTestModeCommand() {
502 PrintWriter errPw = getErrPrintWriter();
503 String arg = getNextArgRequired();
504 if (arg == null) {
505 onHelpDataTestMode();
506 return 0;
507 }
508 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800509 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800510 try {
511 mInterface.enableDataConnectivity();
512 } catch (RemoteException ex) {
513 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
514 errPw.println("Exception: " + ex.getMessage());
515 return -1;
516 }
517 break;
518 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800519 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800520 try {
521 mInterface.disableDataConnectivity();
522 } catch (RemoteException ex) {
523 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
524 errPw.println("Exception: " + ex.getMessage());
525 return -1;
526 }
527 break;
528 }
529 default:
530 onHelpDataTestMode();
531 break;
532 }
533 return 0;
534 }
535
Shuo Qianccbaf742021-02-22 18:32:21 -0800536 private int handleEmergencyCallbackModeCommand() {
537 PrintWriter errPw = getErrPrintWriter();
538 try {
539 mInterface.startEmergencyCallbackMode();
540 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
541 } catch (RemoteException ex) {
542 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
543 errPw.println("Exception: " + ex.getMessage());
544 return -1;
545 }
546 return 0;
547 }
548
sqian9d4df8b2019-01-15 18:32:07 -0800549 private int handleEmergencyNumberTestModeCommand() {
550 PrintWriter errPw = getErrPrintWriter();
551 String opt = getNextOption();
552 if (opt == null) {
553 onHelpEmergencyNumber();
554 return 0;
555 }
556
557 switch (opt) {
558 case "-a": {
559 String emergencyNumberCmd = getNextArgRequired();
560 if (emergencyNumberCmd == null
561 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700562 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800563 + " to be specified after -a in the command ");
564 return -1;
565 }
566 try {
567 mInterface.updateEmergencyNumberListTestMode(
568 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
569 new EmergencyNumber(emergencyNumberCmd, "", "",
570 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
571 new ArrayList<String>(),
572 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
573 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
574 } catch (RemoteException ex) {
575 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
576 + ", error " + ex.getMessage());
577 errPw.println("Exception: " + ex.getMessage());
578 return -1;
579 }
580 break;
581 }
582 case "-c": {
583 try {
584 mInterface.updateEmergencyNumberListTestMode(
585 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
586 } catch (RemoteException ex) {
587 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
588 errPw.println("Exception: " + ex.getMessage());
589 return -1;
590 }
591 break;
592 }
593 case "-r": {
594 String emergencyNumberCmd = getNextArgRequired();
595 if (emergencyNumberCmd == null
596 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700597 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800598 + " to be specified after -r in the command ");
599 return -1;
600 }
601 try {
602 mInterface.updateEmergencyNumberListTestMode(
603 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
604 new EmergencyNumber(emergencyNumberCmd, "", "",
605 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
606 new ArrayList<String>(),
607 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
608 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
609 } catch (RemoteException ex) {
610 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
611 + ", error " + ex.getMessage());
612 errPw.println("Exception: " + ex.getMessage());
613 return -1;
614 }
615 break;
616 }
617 case "-p": {
618 try {
619 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
620 } catch (RemoteException ex) {
621 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
622 errPw.println("Exception: " + ex.getMessage());
623 return -1;
624 }
625 break;
626 }
627 default:
628 onHelpEmergencyNumber();
629 break;
630 }
631 return 0;
632 }
633
Hall Liud892bec2018-11-30 14:51:45 -0800634 private int handleNumberVerificationCommand() {
635 String arg = getNextArg();
636 if (arg == null) {
637 onHelpNumberVerification();
638 return 0;
639 }
640
Hall Liuca5af3a2018-12-04 16:58:23 -0800641 if (!checkShellUid()) {
642 return -1;
643 }
644
Hall Liud892bec2018-11-30 14:51:45 -0800645 switch (arg) {
646 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800647 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
648 return 0;
649 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800650 case NUMBER_VERIFICATION_FAKE_CALL: {
651 boolean val = NumberVerificationManager.getInstance()
652 .checkIncomingCall(getNextArg());
653 getOutPrintWriter().println(val ? "1" : "0");
654 return 0;
655 }
Hall Liud892bec2018-11-30 14:51:45 -0800656 }
657
658 return -1;
659 }
660
Tyler Gunn92479152021-01-20 16:30:10 -0800661 private int handleD2dCommand() {
662 String arg = getNextArg();
663 if (arg == null) {
664 onHelpD2D();
665 return 0;
666 }
667
668 switch (arg) {
669 case D2D_SEND: {
670 return handleD2dSendCommand();
671 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800672 case D2D_TRANSPORT: {
673 return handleD2dTransportCommand();
674 }
Tyler Gunn92479152021-01-20 16:30:10 -0800675 }
676
677 return -1;
678 }
679
680 private int handleD2dSendCommand() {
681 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800682 int messageType = -1;
683 int messageValue = -1;
684
Tyler Gunn92479152021-01-20 16:30:10 -0800685 String arg = getNextArg();
686 if (arg == null) {
687 onHelpD2D();
688 return 0;
689 }
690 try {
691 messageType = Integer.parseInt(arg);
692 } catch (NumberFormatException e) {
693 errPw.println("message type must be a valid integer");
694 return -1;
695 }
696
697 arg = getNextArg();
698 if (arg == null) {
699 onHelpD2D();
700 return 0;
701 }
702 try {
703 messageValue = Integer.parseInt(arg);
704 } catch (NumberFormatException e) {
705 errPw.println("message value must be a valid integer");
706 return -1;
707 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800708
Tyler Gunn92479152021-01-20 16:30:10 -0800709 try {
710 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
711 } catch (RemoteException e) {
712 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
713 errPw.println("Exception: " + e.getMessage());
714 return -1;
715 }
716
717 return 0;
718 }
719
Tyler Gunnbabbda02021-02-10 11:05:02 -0800720 private int handleD2dTransportCommand() {
721 PrintWriter errPw = getErrPrintWriter();
722
723 String arg = getNextArg();
724 if (arg == null) {
725 onHelpD2D();
726 return 0;
727 }
728
729 try {
730 mInterface.setActiveDeviceToDeviceTransport(arg);
731 } catch (RemoteException e) {
732 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
733 errPw.println("Exception: " + e.getMessage());
734 return -1;
735 }
736 return 0;
737 }
738
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700739 // ims set-ims-service
740 private int handleImsSetServiceCommand() {
741 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700742 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700743 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800744 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700745
746 String opt;
747 while ((opt = getNextOption()) != null) {
748 switch (opt) {
749 case "-s": {
750 try {
751 slotId = Integer.parseInt(getNextArgRequired());
752 } catch (NumberFormatException e) {
753 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
754 return -1;
755 }
756 break;
757 }
758 case "-c": {
759 isCarrierService = true;
760 break;
761 }
762 case "-d": {
763 isCarrierService = false;
764 break;
765 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800766 case "-f": {
767 String featureString = getNextArgRequired();
768 String[] features = featureString.split(",");
769 for (int i = 0; i < features.length; i++) {
770 try {
771 Integer result = Integer.parseInt(features[i]);
772 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
773 || result >= ImsFeature.FEATURE_MAX) {
774 errPw.println("ims set-ims-service -f " + result
775 + " is an invalid feature.");
776 return -1;
777 }
778 featuresList.add(result);
779 } catch (NumberFormatException e) {
780 errPw.println("ims set-ims-service -f tried to parse " + features[i]
781 + " as an integer.");
782 return -1;
783 }
784 }
785 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700786 }
787 }
788 // Mandatory param, either -c or -d
789 if (isCarrierService == null) {
790 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
791 return -1;
792 }
793
794 String packageName = getNextArg();
795
796 try {
797 if (packageName == null) {
798 packageName = "";
799 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800800 int[] featureArray = new int[featuresList.size()];
801 for (int i = 0; i < featuresList.size(); i++) {
802 featureArray[i] = featuresList.get(i);
803 }
804 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
805 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700806 if (VDBG) {
807 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800808 + (isCarrierService ? "-c " : "-d ")
809 + "-f " + featuresList + " "
810 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700811 }
812 getOutPrintWriter().println(result);
813 } catch (RemoteException e) {
814 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800815 + (isCarrierService ? "-c " : "-d ")
816 + "-f " + featuresList + " "
817 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700818 errPw.println("Exception: " + e.getMessage());
819 return -1;
820 }
821 return 0;
822 }
823
Brad Ebinger999d3302020-11-25 14:31:39 -0800824 // ims clear-ims-service-override
825 private int handleImsClearCarrierServiceCommand() {
826 PrintWriter errPw = getErrPrintWriter();
827 int slotId = getDefaultSlot();
828
829 String opt;
830 while ((opt = getNextOption()) != null) {
831 switch (opt) {
832 case "-s": {
833 try {
834 slotId = Integer.parseInt(getNextArgRequired());
835 } catch (NumberFormatException e) {
836 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
837 return -1;
838 }
839 break;
840 }
841 }
842 }
843
844 try {
845 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
846 if (VDBG) {
847 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
848 + ", result=" + result);
849 }
850 getOutPrintWriter().println(result);
851 } catch (RemoteException e) {
852 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
853 + ", error" + e.getMessage());
854 errPw.println("Exception: " + e.getMessage());
855 return -1;
856 }
857 return 0;
858 }
859
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700860 // ims get-ims-service
861 private int handleImsGetServiceCommand() {
862 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700863 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700864 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800865 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700866
867 String opt;
868 while ((opt = getNextOption()) != null) {
869 switch (opt) {
870 case "-s": {
871 try {
872 slotId = Integer.parseInt(getNextArgRequired());
873 } catch (NumberFormatException e) {
874 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
875 return -1;
876 }
877 break;
878 }
879 case "-c": {
880 isCarrierService = true;
881 break;
882 }
883 case "-d": {
884 isCarrierService = false;
885 break;
886 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800887 case "-f": {
888 try {
889 featureType = Integer.parseInt(getNextArg());
890 } catch (NumberFormatException e) {
891 errPw.println("ims get-ims-service -f requires valid integer as feature.");
892 return -1;
893 }
894 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
895 || featureType >= ImsFeature.FEATURE_MAX) {
896 errPw.println("ims get-ims-service -f invalid feature.");
897 return -1;
898 }
899 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700900 }
901 }
902 // Mandatory param, either -c or -d
903 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800904 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700905 return -1;
906 }
907
908 String result;
909 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800910 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700911 } catch (RemoteException e) {
912 return -1;
913 }
914 if (VDBG) {
915 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800916 + (isCarrierService ? "-c " : "-d ")
917 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
918 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700919 }
920 getOutPrintWriter().println(result);
921 return 0;
922 }
923
924 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700925 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700926 String opt;
927 while ((opt = getNextOption()) != null) {
928 switch (opt) {
929 case "-s": {
930 try {
931 slotId = Integer.parseInt(getNextArgRequired());
932 } catch (NumberFormatException e) {
933 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
934 return -1;
935 }
936 break;
937 }
938 }
939 }
940 try {
941 mInterface.enableIms(slotId);
942 } catch (RemoteException e) {
943 return -1;
944 }
945 if (VDBG) {
946 Log.v(LOG_TAG, "ims enable -s " + slotId);
947 }
948 return 0;
949 }
950
951 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700952 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700953 String opt;
954 while ((opt = getNextOption()) != null) {
955 switch (opt) {
956 case "-s": {
957 try {
958 slotId = Integer.parseInt(getNextArgRequired());
959 } catch (NumberFormatException e) {
960 getErrPrintWriter().println(
961 "ims disable requires an integer as a SLOT_ID.");
962 return -1;
963 }
964 break;
965 }
966 }
967 }
968 try {
969 mInterface.disableIms(slotId);
970 } catch (RemoteException e) {
971 return -1;
972 }
973 if (VDBG) {
974 Log.v(LOG_TAG, "ims disable -s " + slotId);
975 }
976 return 0;
977 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700978
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700979 private int handleCepChange() {
980 Log.i(LOG_TAG, "handleCepChange");
981 String opt = getNextArg();
982 if (opt == null) {
983 return -1;
984 }
985 boolean isCepEnabled = opt.equals("enable");
986
987 try {
988 mInterface.setCepEnabled(isCepEnabled);
989 } catch (RemoteException e) {
990 return -1;
991 }
992 return 0;
993 }
994
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700995 private int getDefaultSlot() {
996 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
997 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
998 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
999 // If there is no default, default to slot 0.
1000 slotId = DEFAULT_PHONE_ID;
1001 }
1002 return slotId;
1003 }
sqian2fff4a32018-11-05 14:18:37 -08001004
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001005 // Parse options related to Carrier Config Commands.
1006 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001007 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001008 CcOptionParseResult result = new CcOptionParseResult();
1009 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1010 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001011
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001012 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001013 while ((opt = getNextOption()) != null) {
1014 switch (opt) {
1015 case "-s": {
1016 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001017 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1018 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1019 errPw.println(tag + "No valid subscription found.");
1020 return null;
1021 }
1022
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001023 } catch (IllegalArgumentException e) {
1024 // Missing slot id
1025 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001026 return null;
1027 }
1028 break;
1029 }
1030 case "-p": {
1031 if (allowOptionPersistent) {
1032 result.mPersistent = true;
1033 } else {
1034 errPw.println(tag + "Unexpected option " + opt);
1035 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001036 }
1037 break;
1038 }
1039 default: {
1040 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001041 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001042 }
1043 }
1044 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001045 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001046 }
1047
1048 private int slotStringToSubId(String tag, String slotString) {
1049 int slotId = -1;
1050 try {
1051 slotId = Integer.parseInt(slotString);
1052 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001053 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1054 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1055 }
1056
1057 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001058 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1059 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1060 }
1061
Qiong Liuf25799b2020-09-10 10:13:46 +08001062 Phone phone = PhoneFactory.getPhone(slotId);
1063 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001064 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1065 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1066 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001067 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001068 }
1069
Hall Liud892bec2018-11-30 14:51:45 -08001070 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001071 // adb can run as root or as shell, depending on whether the device is rooted.
1072 return Binder.getCallingUid() == Process.SHELL_UID
1073 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001074 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001075
1076 private int handleCcCommand() {
1077 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1078 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001079 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001080 getErrPrintWriter().println("cc: Permission denied.");
1081 return -1;
1082 }
1083
1084 String arg = getNextArg();
1085 if (arg == null) {
1086 onHelpCc();
1087 return 0;
1088 }
1089
1090 switch (arg) {
1091 case CC_GET_VALUE: {
1092 return handleCcGetValue();
1093 }
1094 case CC_SET_VALUE: {
1095 return handleCcSetValue();
1096 }
1097 case CC_CLEAR_VALUES: {
1098 return handleCcClearValues();
1099 }
1100 default: {
1101 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1102 }
1103 }
1104 return -1;
1105 }
1106
1107 // cc get-value
1108 private int handleCcGetValue() {
1109 PrintWriter errPw = getErrPrintWriter();
1110 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1111 String key = null;
1112
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001113 // Parse all options
1114 CcOptionParseResult options = parseCcOptions(tag, false);
1115 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001116 return -1;
1117 }
1118
1119 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001120 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001121 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001122 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001123 return -1;
1124 }
1125
1126 // Get the key.
1127 key = getNextArg();
1128 if (key != null) {
1129 // A key was provided. Verify if it is a valid key
1130 if (!bundle.containsKey(key)) {
1131 errPw.println(tag + key + " is not a valid key.");
1132 return -1;
1133 }
1134
1135 // Print the carrier config value for key.
1136 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1137 } else {
1138 // No key provided. Show all values.
1139 // Iterate over a sorted list of all carrier config keys and print them.
1140 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1141 for (String k : sortedSet) {
1142 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1143 }
1144 }
1145 return 0;
1146 }
1147
1148 // cc set-value
1149 private int handleCcSetValue() {
1150 PrintWriter errPw = getErrPrintWriter();
1151 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1152
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001153 // Parse all options
1154 CcOptionParseResult options = parseCcOptions(tag, true);
1155 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001156 return -1;
1157 }
1158
1159 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001160 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001161 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001162 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001163 return -1;
1164 }
1165
1166 // Get the key.
1167 String key = getNextArg();
1168 if (key == null || key.equals("")) {
1169 errPw.println(tag + "KEY is missing");
1170 return -1;
1171 }
1172
1173 // Verify if the key is valid
1174 if (!originalValues.containsKey(key)) {
1175 errPw.println(tag + key + " is not a valid key.");
1176 return -1;
1177 }
1178
1179 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1180 ArrayList<String> valueList = new ArrayList<String>();
1181 while (peekNextArg() != null) {
1182 valueList.add(getNextArg());
1183 }
1184
1185 // Find the type of the carrier config value
1186 CcType type = getType(tag, key, originalValues);
1187 if (type == CcType.UNKNOWN) {
1188 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1189 return -1;
1190 }
1191
1192 // Create an override bundle containing the key and value that should be overriden.
1193 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1194 if (overrideBundle == null) {
1195 return -1;
1196 }
1197
1198 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001199 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001200
1201 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001202 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001203 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001204 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001205 return -1;
1206 }
1207
1208 // Print the original and new value.
1209 String originalValueString = ccValueToString(key, type, originalValues);
1210 String newValueString = ccValueToString(key, type, newValues);
1211 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1212 getOutPrintWriter().println("New value: \n" + newValueString);
1213
1214 return 0;
1215 }
1216
1217 // cc clear-values
1218 private int handleCcClearValues() {
1219 PrintWriter errPw = getErrPrintWriter();
1220 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1221
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001222 // Parse all options
1223 CcOptionParseResult options = parseCcOptions(tag, false);
1224 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001225 return -1;
1226 }
1227
1228 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001229 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001230 getOutPrintWriter()
1231 .println("All previously set carrier config override values has been cleared");
1232 return 0;
1233 }
1234
1235 private CcType getType(String tag, String key, PersistableBundle bundle) {
1236 // Find the type by checking the type of the current value stored in the bundle.
1237 Object value = bundle.get(key);
1238
1239 if (CC_TYPE_MAP.containsKey(key)) {
1240 return CC_TYPE_MAP.get(key);
1241 } else if (value != null) {
1242 if (value instanceof Boolean) {
1243 return CcType.BOOLEAN;
1244 } else if (value instanceof Double) {
1245 return CcType.DOUBLE;
1246 } else if (value instanceof double[]) {
1247 return CcType.DOUBLE_ARRAY;
1248 } else if (value instanceof Integer) {
1249 return CcType.INT;
1250 } else if (value instanceof int[]) {
1251 return CcType.INT_ARRAY;
1252 } else if (value instanceof Long) {
1253 return CcType.LONG;
1254 } else if (value instanceof long[]) {
1255 return CcType.LONG_ARRAY;
1256 } else if (value instanceof String) {
1257 return CcType.STRING;
1258 } else if (value instanceof String[]) {
1259 return CcType.STRING_ARRAY;
1260 }
1261 } else {
1262 // Current value was null and can therefore not be used in order to find the type.
1263 // Check the name of the key to infer the type. This check is not needed for primitive
1264 // data types (boolean, double, int and long), since they can not be null.
1265 if (key.endsWith("double_array")) {
1266 return CcType.DOUBLE_ARRAY;
1267 }
1268 if (key.endsWith("int_array")) {
1269 return CcType.INT_ARRAY;
1270 }
1271 if (key.endsWith("long_array")) {
1272 return CcType.LONG_ARRAY;
1273 }
1274 if (key.endsWith("string")) {
1275 return CcType.STRING;
1276 }
1277 if (key.endsWith("string_array") || key.endsWith("strings")) {
1278 return CcType.STRING_ARRAY;
1279 }
1280 }
1281
1282 // Not possible to infer the type by looking at the current value or the key.
1283 PrintWriter errPw = getErrPrintWriter();
1284 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1285 return CcType.UNKNOWN;
1286 }
1287
1288 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1289 String result;
1290 StringBuilder valueString = new StringBuilder();
1291 String typeString = type.toString();
1292 Object value = bundle.get(key);
1293
1294 if (value == null) {
1295 valueString.append("null");
1296 } else {
1297 switch (type) {
1298 case DOUBLE_ARRAY: {
1299 // Format the string representation of the int array as value1 value2......
1300 double[] valueArray = (double[]) value;
1301 for (int i = 0; i < valueArray.length; i++) {
1302 if (i != 0) {
1303 valueString.append(" ");
1304 }
1305 valueString.append(valueArray[i]);
1306 }
1307 break;
1308 }
1309 case INT_ARRAY: {
1310 // Format the string representation of the int array as value1 value2......
1311 int[] valueArray = (int[]) value;
1312 for (int i = 0; i < valueArray.length; i++) {
1313 if (i != 0) {
1314 valueString.append(" ");
1315 }
1316 valueString.append(valueArray[i]);
1317 }
1318 break;
1319 }
1320 case LONG_ARRAY: {
1321 // Format the string representation of the int array as value1 value2......
1322 long[] valueArray = (long[]) value;
1323 for (int i = 0; i < valueArray.length; i++) {
1324 if (i != 0) {
1325 valueString.append(" ");
1326 }
1327 valueString.append(valueArray[i]);
1328 }
1329 break;
1330 }
1331 case STRING: {
1332 valueString.append("\"" + value.toString() + "\"");
1333 break;
1334 }
1335 case STRING_ARRAY: {
1336 // Format the string representation of the string array as "value1" "value2"....
1337 String[] valueArray = (String[]) value;
1338 for (int i = 0; i < valueArray.length; i++) {
1339 if (i != 0) {
1340 valueString.append(" ");
1341 }
1342 if (valueArray[i] != null) {
1343 valueString.append("\"" + valueArray[i] + "\"");
1344 } else {
1345 valueString.append("null");
1346 }
1347 }
1348 break;
1349 }
1350 default: {
1351 valueString.append(value.toString());
1352 }
1353 }
1354 }
1355 return String.format("%-70s %-15s %s", key, typeString, valueString);
1356 }
1357
1358 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1359 ArrayList<String> valueList) {
1360 PrintWriter errPw = getErrPrintWriter();
1361 PersistableBundle bundle = new PersistableBundle();
1362
1363 // First verify that a valid number of values has been provided for the type.
1364 switch (type) {
1365 case BOOLEAN:
1366 case DOUBLE:
1367 case INT:
1368 case LONG: {
1369 if (valueList.size() != 1) {
1370 errPw.println(tag + "Expected 1 value for type " + type
1371 + ". Found: " + valueList.size());
1372 return null;
1373 }
1374 break;
1375 }
1376 case STRING: {
1377 if (valueList.size() > 1) {
1378 errPw.println(tag + "Expected 0 or 1 values for type " + type
1379 + ". Found: " + valueList.size());
1380 return null;
1381 }
1382 break;
1383 }
1384 }
1385
1386 // Parse the value according to type and add it to the Bundle.
1387 switch (type) {
1388 case BOOLEAN: {
1389 if ("true".equalsIgnoreCase(valueList.get(0))) {
1390 bundle.putBoolean(key, true);
1391 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1392 bundle.putBoolean(key, false);
1393 } else {
1394 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1395 return null;
1396 }
1397 break;
1398 }
1399 case DOUBLE: {
1400 try {
1401 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1402 } catch (NumberFormatException nfe) {
1403 // Not a valid double
1404 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1405 return null;
1406 }
1407 break;
1408 }
1409 case DOUBLE_ARRAY: {
1410 double[] valueDoubleArray = null;
1411 if (valueList.size() > 0) {
1412 valueDoubleArray = new double[valueList.size()];
1413 for (int i = 0; i < valueList.size(); i++) {
1414 try {
1415 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1416 } catch (NumberFormatException nfe) {
1417 // Not a valid double
1418 errPw.println(
1419 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1420 return null;
1421 }
1422 }
1423 }
1424 bundle.putDoubleArray(key, valueDoubleArray);
1425 break;
1426 }
1427 case INT: {
1428 try {
1429 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1430 } catch (NumberFormatException nfe) {
1431 // Not a valid integer
1432 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1433 return null;
1434 }
1435 break;
1436 }
1437 case INT_ARRAY: {
1438 int[] valueIntArray = null;
1439 if (valueList.size() > 0) {
1440 valueIntArray = new int[valueList.size()];
1441 for (int i = 0; i < valueList.size(); i++) {
1442 try {
1443 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1444 } catch (NumberFormatException nfe) {
1445 // Not a valid integer
1446 errPw.println(tag
1447 + "Unable to parse " + valueList.get(i) + " as an integer.");
1448 return null;
1449 }
1450 }
1451 }
1452 bundle.putIntArray(key, valueIntArray);
1453 break;
1454 }
1455 case LONG: {
1456 try {
1457 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1458 } catch (NumberFormatException nfe) {
1459 // Not a valid long
1460 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1461 return null;
1462 }
1463 break;
1464 }
1465 case LONG_ARRAY: {
1466 long[] valueLongArray = null;
1467 if (valueList.size() > 0) {
1468 valueLongArray = new long[valueList.size()];
1469 for (int i = 0; i < valueList.size(); i++) {
1470 try {
1471 valueLongArray[i] = Long.parseLong(valueList.get(i));
1472 } catch (NumberFormatException nfe) {
1473 // Not a valid long
1474 errPw.println(
1475 tag + "Unable to parse " + valueList.get(i) + " as a long");
1476 return null;
1477 }
1478 }
1479 }
1480 bundle.putLongArray(key, valueLongArray);
1481 break;
1482 }
1483 case STRING: {
1484 String value = null;
1485 if (valueList.size() > 0) {
1486 value = valueList.get(0);
1487 }
1488 bundle.putString(key, value);
1489 break;
1490 }
1491 case STRING_ARRAY: {
1492 String[] valueStringArray = null;
1493 if (valueList.size() > 0) {
1494 valueStringArray = new String[valueList.size()];
1495 valueList.toArray(valueStringArray);
1496 }
1497 bundle.putStringArray(key, valueStringArray);
1498 break;
1499 }
1500 }
1501 return bundle;
1502 }
Shuo Qian489d9282020-07-09 11:30:03 -07001503
1504 private int handleEndBlockSuppressionCommand() {
1505 if (!checkShellUid()) {
1506 return -1;
1507 }
1508
1509 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1510 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1511 }
1512 return 0;
1513 }
Hui Wang641e81c2020-10-12 12:14:23 -07001514
Michele Berionne54af4632020-12-28 20:23:16 +00001515 private int handleRestartModemCommand() {
1516 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1517 // non user build.
1518 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1519 getErrPrintWriter().println("RestartModem: Permission denied.");
1520 return -1;
1521 }
1522
1523 boolean result = TelephonyManager.getDefault().rebootRadio();
1524 getOutPrintWriter().println(result);
1525
1526 return result ? 0 : -1;
1527 }
1528
Michele Berionne5e411512020-11-13 02:36:59 +00001529 private int handleUnattendedReboot() {
1530 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1531 // non user build.
1532 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1533 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1534 return -1;
1535 }
1536
1537 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1538 getOutPrintWriter().println("result: " + result);
1539
1540 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1541 }
1542
Hui Wang641e81c2020-10-12 12:14:23 -07001543 private int handleGbaCommand() {
1544 String arg = getNextArg();
1545 if (arg == null) {
1546 onHelpGba();
1547 return 0;
1548 }
1549
1550 switch (arg) {
1551 case GBA_SET_SERVICE: {
1552 return handleGbaSetServiceCommand();
1553 }
1554 case GBA_GET_SERVICE: {
1555 return handleGbaGetServiceCommand();
1556 }
1557 case GBA_SET_RELEASE_TIME: {
1558 return handleGbaSetReleaseCommand();
1559 }
1560 case GBA_GET_RELEASE_TIME: {
1561 return handleGbaGetReleaseCommand();
1562 }
1563 }
1564
1565 return -1;
1566 }
1567
1568 private int getSubId(String cmd) {
1569 int slotId = getDefaultSlot();
1570 String opt = getNextOption();
1571 if (opt != null && opt.equals("-s")) {
1572 try {
1573 slotId = Integer.parseInt(getNextArgRequired());
1574 } catch (NumberFormatException e) {
1575 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1576 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1577 }
1578 }
1579 int[] subIds = SubscriptionManager.getSubId(slotId);
1580 return subIds[0];
1581 }
1582
1583 private int handleGbaSetServiceCommand() {
1584 int subId = getSubId("gba set-service");
1585 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1586 return -1;
1587 }
1588
1589 String packageName = getNextArg();
1590 try {
1591 if (packageName == null) {
1592 packageName = "";
1593 }
1594 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1595 if (VDBG) {
1596 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1597 + packageName + ", result=" + result);
1598 }
1599 getOutPrintWriter().println(result);
1600 } catch (RemoteException e) {
1601 Log.w(LOG_TAG, "gba set-service " + subId + " "
1602 + packageName + ", error" + e.getMessage());
1603 getErrPrintWriter().println("Exception: " + e.getMessage());
1604 return -1;
1605 }
1606 return 0;
1607 }
1608
1609 private int handleGbaGetServiceCommand() {
1610 String result;
1611
1612 int subId = getSubId("gba get-service");
1613 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1614 return -1;
1615 }
1616
1617 try {
1618 result = mInterface.getBoundGbaService(subId);
1619 } catch (RemoteException e) {
1620 return -1;
1621 }
1622 if (VDBG) {
1623 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1624 }
1625 getOutPrintWriter().println(result);
1626 return 0;
1627 }
1628
1629 private int handleGbaSetReleaseCommand() {
1630 //the release time value could be -1
1631 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1632 : SubscriptionManager.getDefaultSubscriptionId();
1633 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1634 return -1;
1635 }
1636
1637 String intervalStr = getNextArg();
1638 if (intervalStr == null) {
1639 return -1;
1640 }
1641
1642 try {
1643 int interval = Integer.parseInt(intervalStr);
1644 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1645 if (VDBG) {
1646 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1647 + intervalStr + ", result=" + result);
1648 }
1649 getOutPrintWriter().println(result);
1650 } catch (NumberFormatException | RemoteException e) {
1651 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1652 + intervalStr + ", error" + e.getMessage());
1653 getErrPrintWriter().println("Exception: " + e.getMessage());
1654 return -1;
1655 }
1656 return 0;
1657 }
1658
1659 private int handleGbaGetReleaseCommand() {
1660 int subId = getSubId("gba get-release");
1661 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1662 return -1;
1663 }
1664
1665 int result = 0;
1666 try {
1667 result = mInterface.getGbaReleaseTime(subId);
1668 } catch (RemoteException e) {
1669 return -1;
1670 }
1671 if (VDBG) {
1672 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1673 }
1674 getOutPrintWriter().println(result);
1675 return 0;
1676 }
Hui Wang761a6682020-10-31 05:12:53 +00001677
1678 private int handleSingleRegistrationConfigCommand() {
1679 String arg = getNextArg();
1680 if (arg == null) {
1681 onHelpSrc();
1682 return 0;
1683 }
1684
1685 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001686 case SRC_SET_TEST_ENABLED: {
1687 return handleSrcSetTestEnabledCommand();
1688 }
1689 case SRC_GET_TEST_ENABLED: {
1690 return handleSrcGetTestEnabledCommand();
1691 }
Hui Wang761a6682020-10-31 05:12:53 +00001692 case SRC_SET_DEVICE_ENABLED: {
1693 return handleSrcSetDeviceEnabledCommand();
1694 }
1695 case SRC_GET_DEVICE_ENABLED: {
1696 return handleSrcGetDeviceEnabledCommand();
1697 }
1698 case SRC_SET_CARRIER_ENABLED: {
1699 return handleSrcSetCarrierEnabledCommand();
1700 }
1701 case SRC_GET_CARRIER_ENABLED: {
1702 return handleSrcGetCarrierEnabledCommand();
1703 }
1704 }
1705
1706 return -1;
1707 }
1708
James.cf Linbcdf8b32021-01-14 16:44:13 +08001709 private int handleRcsUceCommand() {
1710 String arg = getNextArg();
1711 if (arg == null) {
1712 Log.w(LOG_TAG, "cannot get uce parameter");
1713 return -1;
1714 }
1715
1716 switch (arg) {
1717 case UCE_REMOVE_EAB_CONTACT:
1718 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001719 case UCE_GET_EAB_CONTACT:
1720 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001721 case UCE_GET_DEVICE_ENABLED:
1722 return handleUceGetDeviceEnabledCommand();
1723 case UCE_SET_DEVICE_ENABLED:
1724 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001725 }
1726 return -1;
1727 }
1728
1729 private int handleRemovingEabContactCommand() {
1730 int subId = getSubId("uce remove-eab-contact");
1731 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1732 return -1;
1733 }
1734
1735 String phoneNumber = getNextArgRequired();
1736 if (TextUtils.isEmpty(phoneNumber)) {
1737 return -1;
1738 }
1739 int result = 0;
1740 try {
1741 result = mInterface.removeContactFromEab(subId, phoneNumber);
1742 } catch (RemoteException e) {
1743 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1744 getErrPrintWriter().println("Exception: " + e.getMessage());
1745 return -1;
1746 }
1747
1748 if (VDBG) {
1749 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1750 }
calvinpan293ea1b2021-02-04 17:52:13 +08001751 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001752 }
1753
calvinpane4a8a1d2021-01-25 13:51:18 +08001754 private int handleGettingEabContactCommand() {
1755 String phoneNumber = getNextArgRequired();
1756 if (TextUtils.isEmpty(phoneNumber)) {
1757 return -1;
1758 }
1759 String result = "";
1760 try {
1761 result = mInterface.getContactFromEab(phoneNumber);
1762
1763 } catch (RemoteException e) {
1764 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1765 getErrPrintWriter().println("Exception: " + e.getMessage());
1766 return -1;
1767 }
1768
1769 if (VDBG) {
1770 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1771 }
calvinpan293ea1b2021-02-04 17:52:13 +08001772 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001773 return 0;
1774 }
1775
1776 private int handleUceGetDeviceEnabledCommand() {
1777 boolean result = false;
1778 try {
1779 result = mInterface.getDeviceUceEnabled();
1780 } catch (RemoteException e) {
1781 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1782 return -1;
1783 }
1784 if (VDBG) {
1785 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1786 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001787 getOutPrintWriter().println(result);
1788 return 0;
1789 }
1790
James.cf Lin4b784aa2021-01-31 03:25:15 +08001791 private int handleUceSetDeviceEnabledCommand() {
1792 String enabledStr = getNextArg();
1793 if (TextUtils.isEmpty(enabledStr)) {
1794 return -1;
1795 }
1796
1797 try {
1798 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1799 mInterface.setDeviceUceEnabled(isEnabled);
1800 if (VDBG) {
1801 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1802 }
1803 } catch (NumberFormatException | RemoteException e) {
1804 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1805 getErrPrintWriter().println("Exception: " + e.getMessage());
1806 return -1;
1807 }
1808 return 0;
1809 }
1810
Hui Wangbaaee6a2021-02-19 20:45:36 -08001811 private int handleSrcSetTestEnabledCommand() {
1812 String enabledStr = getNextArg();
1813 if (enabledStr == null) {
1814 return -1;
1815 }
1816
1817 try {
1818 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1819 if (VDBG) {
1820 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1821 }
1822 getOutPrintWriter().println("Done");
1823 } catch (NumberFormatException | RemoteException e) {
1824 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1825 getErrPrintWriter().println("Exception: " + e.getMessage());
1826 return -1;
1827 }
1828 return 0;
1829 }
1830
1831 private int handleSrcGetTestEnabledCommand() {
1832 boolean result = false;
1833 try {
1834 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1835 } catch (RemoteException e) {
1836 return -1;
1837 }
1838 if (VDBG) {
1839 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1840 }
1841 getOutPrintWriter().println(result);
1842 return 0;
1843 }
1844
Hui Wang761a6682020-10-31 05:12:53 +00001845 private int handleSrcSetDeviceEnabledCommand() {
1846 String enabledStr = getNextArg();
1847 if (enabledStr == null) {
1848 return -1;
1849 }
1850
1851 try {
1852 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1853 if (VDBG) {
1854 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1855 }
1856 getOutPrintWriter().println("Done");
1857 } catch (NumberFormatException | RemoteException e) {
1858 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1859 getErrPrintWriter().println("Exception: " + e.getMessage());
1860 return -1;
1861 }
1862 return 0;
1863 }
1864
1865 private int handleSrcGetDeviceEnabledCommand() {
1866 boolean result = false;
1867 try {
1868 result = mInterface.getDeviceSingleRegistrationEnabled();
1869 } catch (RemoteException e) {
1870 return -1;
1871 }
1872 if (VDBG) {
1873 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1874 }
1875 getOutPrintWriter().println(result);
1876 return 0;
1877 }
1878
1879 private int handleSrcSetCarrierEnabledCommand() {
1880 //the release time value could be -1
1881 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1882 : SubscriptionManager.getDefaultSubscriptionId();
1883 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1884 return -1;
1885 }
1886
1887 String enabledStr = getNextArg();
1888 if (enabledStr == null) {
1889 return -1;
1890 }
1891
1892 try {
1893 boolean result =
1894 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1895 if (VDBG) {
1896 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1897 + enabledStr + ", result=" + result);
1898 }
1899 getOutPrintWriter().println(result);
1900 } catch (NumberFormatException | RemoteException e) {
1901 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1902 + enabledStr + ", error" + e.getMessage());
1903 getErrPrintWriter().println("Exception: " + e.getMessage());
1904 return -1;
1905 }
1906 return 0;
1907 }
1908
1909 private int handleSrcGetCarrierEnabledCommand() {
1910 int subId = getSubId("src get-carrier-enabled");
1911 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1912 return -1;
1913 }
1914
1915 boolean result = false;
1916 try {
1917 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1918 } catch (RemoteException e) {
1919 return -1;
1920 }
1921 if (VDBG) {
1922 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1923 }
1924 getOutPrintWriter().println(result);
1925 return 0;
1926 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001927
1928 private void onHelpCallComposer() {
1929 PrintWriter pw = getOutPrintWriter();
1930 pw.println("Call composer commands");
1931 pw.println(" callcomposer test-mode enable|disable|query");
1932 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1933 pw.println(" upload/download from carrier servers is disabled, and operations are");
1934 pw.println(" performed using emulated local files instead.");
1935 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1936 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1937 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08001938 pw.println(" callcomposer user-setting [subId] enable|disable|query");
1939 pw.println(" Enables or disables the user setting for call composer, as set by");
1940 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08001941 }
1942
1943 private int handleCallComposerCommand() {
1944 String arg = getNextArg();
1945 if (arg == null) {
1946 onHelpCallComposer();
1947 return 0;
1948 }
1949
1950 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1951 "MODIFY_PHONE_STATE required for call composer shell cmds");
1952 switch (arg) {
1953 case CALL_COMPOSER_TEST_MODE: {
1954 String enabledStr = getNextArg();
1955 if (ENABLE.equals(enabledStr)) {
1956 CallComposerPictureManager.sTestMode = true;
1957 } else if (DISABLE.equals(enabledStr)) {
1958 CallComposerPictureManager.sTestMode = false;
1959 } else if (QUERY.equals(enabledStr)) {
1960 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1961 } else {
1962 onHelpCallComposer();
1963 return 1;
1964 }
1965 break;
1966 }
1967 case CALL_COMPOSER_SIMULATE_CALL: {
1968 int subscriptionId = Integer.valueOf(getNextArg());
1969 String uuidString = getNextArg();
1970 UUID uuid = UUID.fromString(uuidString);
1971 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1972 Binder.withCleanCallingIdentity(() -> {
1973 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1974 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1975 });
1976 try {
1977 Uri uri = storageUriFuture.get();
1978 getOutPrintWriter().println(String.valueOf(uri));
1979 } catch (Exception e) {
1980 throw new RuntimeException(e);
1981 }
1982 break;
1983 }
Hall Liu7917ecf2021-02-23 12:22:31 -08001984 case CALL_COMPOSER_USER_SETTING: {
1985 try {
1986 int subscriptionId = Integer.valueOf(getNextArg());
1987 String enabledStr = getNextArg();
1988 if (ENABLE.equals(enabledStr)) {
1989 mInterface.setCallComposerStatus(subscriptionId,
1990 TelephonyManager.CALL_COMPOSER_STATUS_ON);
1991 } else if (DISABLE.equals(enabledStr)) {
1992 mInterface.setCallComposerStatus(subscriptionId,
1993 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
1994 } else if (QUERY.equals(enabledStr)) {
1995 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
1996 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
1997 } else {
1998 onHelpCallComposer();
1999 return 1;
2000 }
2001 } catch (RemoteException e) {
2002 e.printStackTrace(getOutPrintWriter());
2003 return 1;
2004 }
2005 break;
2006 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002007 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002008 return 0;
2009 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002010
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002011 private int handleHasCarrierPrivilegesCommand() {
2012 String packageName = getNextArgRequired();
2013
2014 boolean hasCarrierPrivileges;
2015 try {
2016 hasCarrierPrivileges =
2017 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2018 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2019 } catch (RemoteException e) {
2020 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2021 getErrPrintWriter().println("Exception: " + e.getMessage());
2022 return -1;
2023 }
2024
2025 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002026 return 0;
2027 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002028}