blob: 79dfbcf26115209ac432e77db43d4e66c22fe76a [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Shuo Qian489d9282020-07-09 11:30:03 -070031import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010032import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070033import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000034import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080035import android.telephony.emergency.EmergencyNumber;
Brad Ebinger24c29992019-12-05 13:03:21 -080036import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080037import android.text.TextUtils;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.util.Log;
39
40import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080041import com.android.internal.telephony.Phone;
42import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080043import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080044import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080045import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080046import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080047import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
49import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080050import java.util.ArrayList;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010051import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080052import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010053import java.util.Map;
54import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080055import java.util.UUID;
56import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070057
58/**
59 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
60 * permission checks have been done before onCommand was called. Make sure any commands processed
61 * here also contain the appropriate permissions checks.
62 */
63
Hall Liua1548bd2019-12-24 14:14:12 -080064public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070065
66 private static final String LOG_TAG = "TelephonyShellCommand";
67 // Don't commit with this true.
68 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070069 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070
Hall Liuaa4211e2021-01-20 15:43:39 -080071 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070072 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080073 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080074 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070075 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000076 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000077 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010078 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080079 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080080 private static final String ENABLE = "enable";
81 private static final String DISABLE = "disable";
82 private static final String QUERY = "query";
83
Hall Liu7135e502021-02-04 16:58:17 -080084 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080085 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liud892bec2018-11-30 14:51:45 -080086
Brad Ebinger999d3302020-11-25 14:31:39 -080087 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
88 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
89 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070090 // Used to disable or enable processing of conference event package data from the network.
91 // This is handy for testing scenarios where CEP data does not exist on a network which does
92 // support CEP data.
93 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070094
Hall Liud892bec2018-11-30 14:51:45 -080095 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080096 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080097
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010098 private static final String CC_GET_VALUE = "get-value";
99 private static final String CC_SET_VALUE = "set-value";
100 private static final String CC_CLEAR_VALUES = "clear-values";
101
Hui Wang641e81c2020-10-12 12:14:23 -0700102 private static final String GBA_SUBCOMMAND = "gba";
103 private static final String GBA_SET_SERVICE = "set-service";
104 private static final String GBA_GET_SERVICE = "get-service";
105 private static final String GBA_SET_RELEASE_TIME = "set-release";
106 private static final String GBA_GET_RELEASE_TIME = "get-release";
107
Hui Wang761a6682020-10-31 05:12:53 +0000108 private static final String SINGLE_REGISTATION_CONFIG = "src";
109 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
110 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
111 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
112 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
113
Tyler Gunn92479152021-01-20 16:30:10 -0800114 private static final String D2D_SUBCOMMAND = "d2d";
115 private static final String D2D_SEND = "send";
116
James.cf Linbcdf8b32021-01-14 16:44:13 +0800117 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800118 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800119 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800120 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
121 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800122
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700123 // Take advantage of existing methods that already contain permissions checks when possible.
124 private final ITelephony mInterface;
125
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100126 private SubscriptionManager mSubscriptionManager;
127 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700128 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100129
130 private enum CcType {
131 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
132 STRING_ARRAY, UNKNOWN
133 }
134
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100135 private class CcOptionParseResult {
136 public int mSubId;
137 public boolean mPersistent;
138 }
139
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100140 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
141 // keys by looking at the end of the string which usually tells the type.
142 // For instance: "xxxx_string", "xxxx_string_array", etc.
143 // The carrier config keys in this map does not follow this convention. It is therefore not
144 // possible to infer the type for these keys by looking at the string.
145 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
146 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
157 CcType.STRING);
158 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
159 CcType.STRING_ARRAY);
160 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
161 CcType.STRING_ARRAY);
162 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
163 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
164 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
165 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
167 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
168 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
169 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
170 }
171 };
172
173 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700174 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100175 mCarrierConfigManager =
176 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
177 mSubscriptionManager = (SubscriptionManager)
178 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700179 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700180 }
181
182 @Override
183 public int onCommand(String cmd) {
184 if (cmd == null) {
185 return handleDefaultCommands(null);
186 }
187
188 switch (cmd) {
189 case IMS_SUBCOMMAND: {
190 return handleImsCommand();
191 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800192 case RCS_UCE_COMMAND:
193 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800194 case NUMBER_VERIFICATION_SUBCOMMAND:
195 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800196 case EMERGENCY_NUMBER_TEST_MODE:
197 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100198 case CARRIER_CONFIG_SUBCOMMAND: {
199 return handleCcCommand();
200 }
Shuo Qianf5125122019-12-16 17:03:07 -0800201 case DATA_TEST_MODE:
202 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700203 case END_BLOCK_SUPPRESSION:
204 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700205 case GBA_SUBCOMMAND:
206 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800207 case D2D_SUBCOMMAND:
208 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000209 case SINGLE_REGISTATION_CONFIG:
210 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000211 case RESTART_MODEM:
212 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800213 case CALL_COMPOSER_SUBCOMMAND:
214 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000215 case UNATTENDED_REBOOT:
216 return handleUnattendedReboot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700217 default: {
218 return handleDefaultCommands(cmd);
219 }
220 }
221 }
222
223 @Override
224 public void onHelp() {
225 PrintWriter pw = getOutPrintWriter();
226 pw.println("Telephony Commands:");
227 pw.println(" help");
228 pw.println(" Print this help text.");
229 pw.println(" ims");
230 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800231 pw.println(" uce");
232 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800233 pw.println(" emergency-number-test-mode");
234 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700235 pw.println(" end-block-suppression");
236 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800237 pw.println(" data");
238 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100239 pw.println(" cc");
240 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700241 pw.println(" gba");
242 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000243 pw.println(" src");
244 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000245 pw.println(" restart-modem");
246 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000247 pw.println(" unattended-reboot");
248 pw.println(" Prepare for unattended reboot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700249 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800250 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800251 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700252 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800253 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100254 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700255 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000256 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800257 onHelpD2D();
258 }
259
260 private void onHelpD2D() {
261 PrintWriter pw = getOutPrintWriter();
262 pw.println("D2D Comms Commands:");
263 pw.println(" d2d send TYPE VALUE");
264 pw.println(" Sends a D2D message of specified type and value.");
265 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
266 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
267 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
268 MESSAGE_CALL_AUDIO_CODEC));
269 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
270 + Communicator.messageToString(
271 MESSAGE_DEVICE_BATTERY_STATE));
272 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
273 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700274 }
275
276 private void onHelpIms() {
277 PrintWriter pw = getOutPrintWriter();
278 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800279 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700280 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
281 pw.println(" ImsService. Options are:");
282 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
283 pw.println(" is specified, it will choose the default voice SIM slot.");
284 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
285 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800286 pw.println(" -f: Set the feature that this override if for, if no option is");
287 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700288 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
289 pw.println(" Gets the package name of the currently defined ImsService.");
290 pw.println(" Options are:");
291 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
292 pw.println(" is specified, it will choose the default voice SIM slot.");
293 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000294 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800295 pw.println(" -f: The feature type that the query will be requested for. If none is");
296 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800297 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
298 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
299 pw.println(" configuration overrides. Options are:");
300 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
301 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700302 pw.println(" ims enable [-s SLOT_ID]");
303 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
304 pw.println(" if none is specified.");
305 pw.println(" ims disable [-s SLOT_ID]");
306 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
307 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700308 pw.println(" ims conference-event-package [enable/disable]");
309 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700310 }
311
James.cf Linbcdf8b32021-01-14 16:44:13 +0800312 private void onHelpUce() {
313 PrintWriter pw = getOutPrintWriter();
314 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800315 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
316 pw.println(" Get the EAB contacts from the EAB database.");
317 pw.println(" Options are:");
318 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
319 pw.println(" Expected output format :");
320 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800321 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
322 pw.println(" Remove the EAB contacts from the EAB database.");
323 pw.println(" Options are:");
324 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
325 pw.println(" is specified, it will choose the default voice SIM slot.");
326 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800327 pw.println(" uce get-device-enabled");
328 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
329 pw.println(" uce set-device-enabled true|false");
330 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
331 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800332 }
333
Hall Liud892bec2018-11-30 14:51:45 -0800334 private void onHelpNumberVerification() {
335 PrintWriter pw = getOutPrintWriter();
336 pw.println("Number verification commands");
337 pw.println(" numverify override-package PACKAGE_NAME;");
338 pw.println(" Set the authorized package for number verification.");
339 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800340 pw.println(" numverify fake-call NUMBER;");
341 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
342 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800343 }
344
Shuo Qianf5125122019-12-16 17:03:07 -0800345 private void onHelpDataTestMode() {
346 PrintWriter pw = getOutPrintWriter();
347 pw.println("Mobile Data Test Mode Commands:");
348 pw.println(" data enable: enable mobile data connectivity");
349 pw.println(" data disable: disable mobile data connectivity");
350 }
351
sqian9d4df8b2019-01-15 18:32:07 -0800352 private void onHelpEmergencyNumber() {
353 PrintWriter pw = getOutPrintWriter();
354 pw.println("Emergency Number Test Mode Commands:");
355 pw.println(" emergency-number-test-mode ");
356 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
357 + " the test mode");
358 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700359 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800360 pw.println(" -c: clear the emergency number list in the test mode.");
361 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700362 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800363 pw.println(" -p: get the full emergency number list in the test mode.");
364 }
365
Shuo Qian489d9282020-07-09 11:30:03 -0700366 private void onHelpEndBlockSupperssion() {
367 PrintWriter pw = getOutPrintWriter();
368 pw.println("End Block Suppression command:");
369 pw.println(" end-block-suppression: disable suppressing blocking by contact");
370 pw.println(" with emergency services.");
371 }
372
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100373 private void onHelpCc() {
374 PrintWriter pw = getOutPrintWriter();
375 pw.println("Carrier Config Commands:");
376 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
377 pw.println(" Print carrier config values.");
378 pw.println(" Options are:");
379 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
380 pw.println(" is specified, it will choose the default voice SIM slot.");
381 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
382 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100383 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100384 pw.println(" Set carrier config KEY to NEW_VALUE.");
385 pw.println(" Options are:");
386 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
387 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100388 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100389 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
390 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
391 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
392 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
393 pw.println(" cc clear-values [-s SLOT_ID]");
394 pw.println(" Clear all carrier override values that has previously been set");
395 pw.println(" with set-value");
396 pw.println(" Options are:");
397 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
398 pw.println(" is specified, it will choose the default voice SIM slot.");
399 }
400
Hui Wang641e81c2020-10-12 12:14:23 -0700401 private void onHelpGba() {
402 PrintWriter pw = getOutPrintWriter();
403 pw.println("Gba Commands:");
404 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
405 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
406 pw.println(" Options are:");
407 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
408 pw.println(" is specified, it will choose the default voice SIM slot.");
409 pw.println(" gba get-service [-s SLOT_ID]");
410 pw.println(" Gets the package name of the currently defined GbaService.");
411 pw.println(" Options are:");
412 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
413 pw.println(" is specified, it will choose the default voice SIM slot.");
414 pw.println(" gba set-release [-s SLOT_ID] n");
415 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
416 pw.println(" Do not release/unbind if n is -1.");
417 pw.println(" Options are:");
418 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
419 pw.println(" is specified, it will choose the default voice SIM slot.");
420 pw.println(" gba get-release [-s SLOT_ID]");
421 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
422 pw.println(" Options are:");
423 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
424 pw.println(" is specified, it will choose the default voice SIM slot.");
425 }
426
Hui Wang761a6682020-10-31 05:12:53 +0000427 private void onHelpSrc() {
428 PrintWriter pw = getOutPrintWriter();
429 pw.println("RCS VoLTE Single Registration Config Commands:");
430 pw.println(" src set-device-enabled true|false|null");
431 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
432 pw.println(" The value could be true, false, or null(undefined).");
433 pw.println(" src get-device-enabled");
434 pw.println(" Gets the device config for RCS VoLTE single registration.");
435 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
436 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
437 pw.println(" The value could be true, false, or null(undefined).");
438 pw.println(" Options are:");
439 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
440 pw.println(" is specified, it will choose the default voice SIM slot.");
441 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
442 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
443 pw.println(" Options are:");
444 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
445 pw.println(" is specified, it will choose the default voice SIM slot.");
446 }
447
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700448 private int handleImsCommand() {
449 String arg = getNextArg();
450 if (arg == null) {
451 onHelpIms();
452 return 0;
453 }
454
455 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800456 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700457 return handleImsSetServiceCommand();
458 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800459 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700460 return handleImsGetServiceCommand();
461 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800462 case IMS_CLEAR_SERVICE_OVERRIDE: {
463 return handleImsClearCarrierServiceCommand();
464 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800465 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700466 return handleEnableIms();
467 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800468 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700469 return handleDisableIms();
470 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700471 case IMS_CEP: {
472 return handleCepChange();
473 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700474 }
475
476 return -1;
477 }
478
Shuo Qianf5125122019-12-16 17:03:07 -0800479 private int handleDataTestModeCommand() {
480 PrintWriter errPw = getErrPrintWriter();
481 String arg = getNextArgRequired();
482 if (arg == null) {
483 onHelpDataTestMode();
484 return 0;
485 }
486 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800487 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800488 try {
489 mInterface.enableDataConnectivity();
490 } catch (RemoteException ex) {
491 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
492 errPw.println("Exception: " + ex.getMessage());
493 return -1;
494 }
495 break;
496 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800497 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800498 try {
499 mInterface.disableDataConnectivity();
500 } catch (RemoteException ex) {
501 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
502 errPw.println("Exception: " + ex.getMessage());
503 return -1;
504 }
505 break;
506 }
507 default:
508 onHelpDataTestMode();
509 break;
510 }
511 return 0;
512 }
513
sqian9d4df8b2019-01-15 18:32:07 -0800514 private int handleEmergencyNumberTestModeCommand() {
515 PrintWriter errPw = getErrPrintWriter();
516 String opt = getNextOption();
517 if (opt == null) {
518 onHelpEmergencyNumber();
519 return 0;
520 }
521
522 switch (opt) {
523 case "-a": {
524 String emergencyNumberCmd = getNextArgRequired();
525 if (emergencyNumberCmd == null
526 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700527 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800528 + " to be specified after -a in the command ");
529 return -1;
530 }
531 try {
532 mInterface.updateEmergencyNumberListTestMode(
533 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
534 new EmergencyNumber(emergencyNumberCmd, "", "",
535 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
536 new ArrayList<String>(),
537 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
538 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
539 } catch (RemoteException ex) {
540 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
541 + ", error " + ex.getMessage());
542 errPw.println("Exception: " + ex.getMessage());
543 return -1;
544 }
545 break;
546 }
547 case "-c": {
548 try {
549 mInterface.updateEmergencyNumberListTestMode(
550 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
551 } catch (RemoteException ex) {
552 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
553 errPw.println("Exception: " + ex.getMessage());
554 return -1;
555 }
556 break;
557 }
558 case "-r": {
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 -r in the command ");
564 return -1;
565 }
566 try {
567 mInterface.updateEmergencyNumberListTestMode(
568 EmergencyNumberTracker.REMOVE_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 -r " + emergencyNumberCmd
576 + ", error " + ex.getMessage());
577 errPw.println("Exception: " + ex.getMessage());
578 return -1;
579 }
580 break;
581 }
582 case "-p": {
583 try {
584 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
585 } catch (RemoteException ex) {
586 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
587 errPw.println("Exception: " + ex.getMessage());
588 return -1;
589 }
590 break;
591 }
592 default:
593 onHelpEmergencyNumber();
594 break;
595 }
596 return 0;
597 }
598
Hall Liud892bec2018-11-30 14:51:45 -0800599 private int handleNumberVerificationCommand() {
600 String arg = getNextArg();
601 if (arg == null) {
602 onHelpNumberVerification();
603 return 0;
604 }
605
Hall Liuca5af3a2018-12-04 16:58:23 -0800606 if (!checkShellUid()) {
607 return -1;
608 }
609
Hall Liud892bec2018-11-30 14:51:45 -0800610 switch (arg) {
611 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800612 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
613 return 0;
614 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800615 case NUMBER_VERIFICATION_FAKE_CALL: {
616 boolean val = NumberVerificationManager.getInstance()
617 .checkIncomingCall(getNextArg());
618 getOutPrintWriter().println(val ? "1" : "0");
619 return 0;
620 }
Hall Liud892bec2018-11-30 14:51:45 -0800621 }
622
623 return -1;
624 }
625
Tyler Gunn92479152021-01-20 16:30:10 -0800626 private int handleD2dCommand() {
627 String arg = getNextArg();
628 if (arg == null) {
629 onHelpD2D();
630 return 0;
631 }
632
633 switch (arg) {
634 case D2D_SEND: {
635 return handleD2dSendCommand();
636 }
637 }
638
639 return -1;
640 }
641
642 private int handleD2dSendCommand() {
643 PrintWriter errPw = getErrPrintWriter();
644 String opt;
645 int messageType = -1;
646 int messageValue = -1;
647
648
649 String arg = getNextArg();
650 if (arg == null) {
651 onHelpD2D();
652 return 0;
653 }
654 try {
655 messageType = Integer.parseInt(arg);
656 } catch (NumberFormatException e) {
657 errPw.println("message type must be a valid integer");
658 return -1;
659 }
660
661 arg = getNextArg();
662 if (arg == null) {
663 onHelpD2D();
664 return 0;
665 }
666 try {
667 messageValue = Integer.parseInt(arg);
668 } catch (NumberFormatException e) {
669 errPw.println("message value must be a valid integer");
670 return -1;
671 }
672
673 try {
674 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
675 } catch (RemoteException e) {
676 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
677 errPw.println("Exception: " + e.getMessage());
678 return -1;
679 }
680
681 return 0;
682 }
683
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700684 // ims set-ims-service
685 private int handleImsSetServiceCommand() {
686 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700687 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700688 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800689 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700690
691 String opt;
692 while ((opt = getNextOption()) != null) {
693 switch (opt) {
694 case "-s": {
695 try {
696 slotId = Integer.parseInt(getNextArgRequired());
697 } catch (NumberFormatException e) {
698 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
699 return -1;
700 }
701 break;
702 }
703 case "-c": {
704 isCarrierService = true;
705 break;
706 }
707 case "-d": {
708 isCarrierService = false;
709 break;
710 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800711 case "-f": {
712 String featureString = getNextArgRequired();
713 String[] features = featureString.split(",");
714 for (int i = 0; i < features.length; i++) {
715 try {
716 Integer result = Integer.parseInt(features[i]);
717 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
718 || result >= ImsFeature.FEATURE_MAX) {
719 errPw.println("ims set-ims-service -f " + result
720 + " is an invalid feature.");
721 return -1;
722 }
723 featuresList.add(result);
724 } catch (NumberFormatException e) {
725 errPw.println("ims set-ims-service -f tried to parse " + features[i]
726 + " as an integer.");
727 return -1;
728 }
729 }
730 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700731 }
732 }
733 // Mandatory param, either -c or -d
734 if (isCarrierService == null) {
735 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
736 return -1;
737 }
738
739 String packageName = getNextArg();
740
741 try {
742 if (packageName == null) {
743 packageName = "";
744 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800745 int[] featureArray = new int[featuresList.size()];
746 for (int i = 0; i < featuresList.size(); i++) {
747 featureArray[i] = featuresList.get(i);
748 }
749 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
750 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700751 if (VDBG) {
752 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800753 + (isCarrierService ? "-c " : "-d ")
754 + "-f " + featuresList + " "
755 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700756 }
757 getOutPrintWriter().println(result);
758 } catch (RemoteException e) {
759 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800760 + (isCarrierService ? "-c " : "-d ")
761 + "-f " + featuresList + " "
762 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700763 errPw.println("Exception: " + e.getMessage());
764 return -1;
765 }
766 return 0;
767 }
768
Brad Ebinger999d3302020-11-25 14:31:39 -0800769 // ims clear-ims-service-override
770 private int handleImsClearCarrierServiceCommand() {
771 PrintWriter errPw = getErrPrintWriter();
772 int slotId = getDefaultSlot();
773
774 String opt;
775 while ((opt = getNextOption()) != null) {
776 switch (opt) {
777 case "-s": {
778 try {
779 slotId = Integer.parseInt(getNextArgRequired());
780 } catch (NumberFormatException e) {
781 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
782 return -1;
783 }
784 break;
785 }
786 }
787 }
788
789 try {
790 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
791 if (VDBG) {
792 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
793 + ", result=" + result);
794 }
795 getOutPrintWriter().println(result);
796 } catch (RemoteException e) {
797 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
798 + ", error" + e.getMessage());
799 errPw.println("Exception: " + e.getMessage());
800 return -1;
801 }
802 return 0;
803 }
804
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700805 // ims get-ims-service
806 private int handleImsGetServiceCommand() {
807 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700808 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700809 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800810 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700811
812 String opt;
813 while ((opt = getNextOption()) != null) {
814 switch (opt) {
815 case "-s": {
816 try {
817 slotId = Integer.parseInt(getNextArgRequired());
818 } catch (NumberFormatException e) {
819 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
820 return -1;
821 }
822 break;
823 }
824 case "-c": {
825 isCarrierService = true;
826 break;
827 }
828 case "-d": {
829 isCarrierService = false;
830 break;
831 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800832 case "-f": {
833 try {
834 featureType = Integer.parseInt(getNextArg());
835 } catch (NumberFormatException e) {
836 errPw.println("ims get-ims-service -f requires valid integer as feature.");
837 return -1;
838 }
839 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
840 || featureType >= ImsFeature.FEATURE_MAX) {
841 errPw.println("ims get-ims-service -f invalid feature.");
842 return -1;
843 }
844 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700845 }
846 }
847 // Mandatory param, either -c or -d
848 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800849 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700850 return -1;
851 }
852
853 String result;
854 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800855 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700856 } catch (RemoteException e) {
857 return -1;
858 }
859 if (VDBG) {
860 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800861 + (isCarrierService ? "-c " : "-d ")
862 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
863 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700864 }
865 getOutPrintWriter().println(result);
866 return 0;
867 }
868
869 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700870 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700871 String opt;
872 while ((opt = getNextOption()) != null) {
873 switch (opt) {
874 case "-s": {
875 try {
876 slotId = Integer.parseInt(getNextArgRequired());
877 } catch (NumberFormatException e) {
878 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
879 return -1;
880 }
881 break;
882 }
883 }
884 }
885 try {
886 mInterface.enableIms(slotId);
887 } catch (RemoteException e) {
888 return -1;
889 }
890 if (VDBG) {
891 Log.v(LOG_TAG, "ims enable -s " + slotId);
892 }
893 return 0;
894 }
895
896 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700897 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700898 String opt;
899 while ((opt = getNextOption()) != null) {
900 switch (opt) {
901 case "-s": {
902 try {
903 slotId = Integer.parseInt(getNextArgRequired());
904 } catch (NumberFormatException e) {
905 getErrPrintWriter().println(
906 "ims disable requires an integer as a SLOT_ID.");
907 return -1;
908 }
909 break;
910 }
911 }
912 }
913 try {
914 mInterface.disableIms(slotId);
915 } catch (RemoteException e) {
916 return -1;
917 }
918 if (VDBG) {
919 Log.v(LOG_TAG, "ims disable -s " + slotId);
920 }
921 return 0;
922 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700923
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700924 private int handleCepChange() {
925 Log.i(LOG_TAG, "handleCepChange");
926 String opt = getNextArg();
927 if (opt == null) {
928 return -1;
929 }
930 boolean isCepEnabled = opt.equals("enable");
931
932 try {
933 mInterface.setCepEnabled(isCepEnabled);
934 } catch (RemoteException e) {
935 return -1;
936 }
937 return 0;
938 }
939
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700940 private int getDefaultSlot() {
941 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
942 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
943 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
944 // If there is no default, default to slot 0.
945 slotId = DEFAULT_PHONE_ID;
946 }
947 return slotId;
948 }
sqian2fff4a32018-11-05 14:18:37 -0800949
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100950 // Parse options related to Carrier Config Commands.
951 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100952 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100953 CcOptionParseResult result = new CcOptionParseResult();
954 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
955 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100956
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100957 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100958 while ((opt = getNextOption()) != null) {
959 switch (opt) {
960 case "-s": {
961 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100962 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
963 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
964 errPw.println(tag + "No valid subscription found.");
965 return null;
966 }
967
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100968 } catch (IllegalArgumentException e) {
969 // Missing slot id
970 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100971 return null;
972 }
973 break;
974 }
975 case "-p": {
976 if (allowOptionPersistent) {
977 result.mPersistent = true;
978 } else {
979 errPw.println(tag + "Unexpected option " + opt);
980 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100981 }
982 break;
983 }
984 default: {
985 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100986 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100987 }
988 }
989 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100990 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100991 }
992
993 private int slotStringToSubId(String tag, String slotString) {
994 int slotId = -1;
995 try {
996 slotId = Integer.parseInt(slotString);
997 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800998 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
999 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1000 }
1001
1002 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001003 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1004 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1005 }
1006
Qiong Liuf25799b2020-09-10 10:13:46 +08001007 Phone phone = PhoneFactory.getPhone(slotId);
1008 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001009 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1010 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1011 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001012 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001013 }
1014
Hall Liud892bec2018-11-30 14:51:45 -08001015 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001016 // adb can run as root or as shell, depending on whether the device is rooted.
1017 return Binder.getCallingUid() == Process.SHELL_UID
1018 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001019 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001020
1021 private int handleCcCommand() {
1022 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1023 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001024 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001025 getErrPrintWriter().println("cc: Permission denied.");
1026 return -1;
1027 }
1028
1029 String arg = getNextArg();
1030 if (arg == null) {
1031 onHelpCc();
1032 return 0;
1033 }
1034
1035 switch (arg) {
1036 case CC_GET_VALUE: {
1037 return handleCcGetValue();
1038 }
1039 case CC_SET_VALUE: {
1040 return handleCcSetValue();
1041 }
1042 case CC_CLEAR_VALUES: {
1043 return handleCcClearValues();
1044 }
1045 default: {
1046 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1047 }
1048 }
1049 return -1;
1050 }
1051
1052 // cc get-value
1053 private int handleCcGetValue() {
1054 PrintWriter errPw = getErrPrintWriter();
1055 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1056 String key = null;
1057
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001058 // Parse all options
1059 CcOptionParseResult options = parseCcOptions(tag, false);
1060 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001061 return -1;
1062 }
1063
1064 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001065 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001066 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001067 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001068 return -1;
1069 }
1070
1071 // Get the key.
1072 key = getNextArg();
1073 if (key != null) {
1074 // A key was provided. Verify if it is a valid key
1075 if (!bundle.containsKey(key)) {
1076 errPw.println(tag + key + " is not a valid key.");
1077 return -1;
1078 }
1079
1080 // Print the carrier config value for key.
1081 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1082 } else {
1083 // No key provided. Show all values.
1084 // Iterate over a sorted list of all carrier config keys and print them.
1085 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1086 for (String k : sortedSet) {
1087 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1088 }
1089 }
1090 return 0;
1091 }
1092
1093 // cc set-value
1094 private int handleCcSetValue() {
1095 PrintWriter errPw = getErrPrintWriter();
1096 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1097
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001098 // Parse all options
1099 CcOptionParseResult options = parseCcOptions(tag, true);
1100 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001101 return -1;
1102 }
1103
1104 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001105 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001106 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001107 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001108 return -1;
1109 }
1110
1111 // Get the key.
1112 String key = getNextArg();
1113 if (key == null || key.equals("")) {
1114 errPw.println(tag + "KEY is missing");
1115 return -1;
1116 }
1117
1118 // Verify if the key is valid
1119 if (!originalValues.containsKey(key)) {
1120 errPw.println(tag + key + " is not a valid key.");
1121 return -1;
1122 }
1123
1124 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1125 ArrayList<String> valueList = new ArrayList<String>();
1126 while (peekNextArg() != null) {
1127 valueList.add(getNextArg());
1128 }
1129
1130 // Find the type of the carrier config value
1131 CcType type = getType(tag, key, originalValues);
1132 if (type == CcType.UNKNOWN) {
1133 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1134 return -1;
1135 }
1136
1137 // Create an override bundle containing the key and value that should be overriden.
1138 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1139 if (overrideBundle == null) {
1140 return -1;
1141 }
1142
1143 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001144 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001145
1146 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001147 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001148 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001149 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001150 return -1;
1151 }
1152
1153 // Print the original and new value.
1154 String originalValueString = ccValueToString(key, type, originalValues);
1155 String newValueString = ccValueToString(key, type, newValues);
1156 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1157 getOutPrintWriter().println("New value: \n" + newValueString);
1158
1159 return 0;
1160 }
1161
1162 // cc clear-values
1163 private int handleCcClearValues() {
1164 PrintWriter errPw = getErrPrintWriter();
1165 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1166
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001167 // Parse all options
1168 CcOptionParseResult options = parseCcOptions(tag, false);
1169 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001170 return -1;
1171 }
1172
1173 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001174 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001175 getOutPrintWriter()
1176 .println("All previously set carrier config override values has been cleared");
1177 return 0;
1178 }
1179
1180 private CcType getType(String tag, String key, PersistableBundle bundle) {
1181 // Find the type by checking the type of the current value stored in the bundle.
1182 Object value = bundle.get(key);
1183
1184 if (CC_TYPE_MAP.containsKey(key)) {
1185 return CC_TYPE_MAP.get(key);
1186 } else if (value != null) {
1187 if (value instanceof Boolean) {
1188 return CcType.BOOLEAN;
1189 } else if (value instanceof Double) {
1190 return CcType.DOUBLE;
1191 } else if (value instanceof double[]) {
1192 return CcType.DOUBLE_ARRAY;
1193 } else if (value instanceof Integer) {
1194 return CcType.INT;
1195 } else if (value instanceof int[]) {
1196 return CcType.INT_ARRAY;
1197 } else if (value instanceof Long) {
1198 return CcType.LONG;
1199 } else if (value instanceof long[]) {
1200 return CcType.LONG_ARRAY;
1201 } else if (value instanceof String) {
1202 return CcType.STRING;
1203 } else if (value instanceof String[]) {
1204 return CcType.STRING_ARRAY;
1205 }
1206 } else {
1207 // Current value was null and can therefore not be used in order to find the type.
1208 // Check the name of the key to infer the type. This check is not needed for primitive
1209 // data types (boolean, double, int and long), since they can not be null.
1210 if (key.endsWith("double_array")) {
1211 return CcType.DOUBLE_ARRAY;
1212 }
1213 if (key.endsWith("int_array")) {
1214 return CcType.INT_ARRAY;
1215 }
1216 if (key.endsWith("long_array")) {
1217 return CcType.LONG_ARRAY;
1218 }
1219 if (key.endsWith("string")) {
1220 return CcType.STRING;
1221 }
1222 if (key.endsWith("string_array") || key.endsWith("strings")) {
1223 return CcType.STRING_ARRAY;
1224 }
1225 }
1226
1227 // Not possible to infer the type by looking at the current value or the key.
1228 PrintWriter errPw = getErrPrintWriter();
1229 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1230 return CcType.UNKNOWN;
1231 }
1232
1233 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1234 String result;
1235 StringBuilder valueString = new StringBuilder();
1236 String typeString = type.toString();
1237 Object value = bundle.get(key);
1238
1239 if (value == null) {
1240 valueString.append("null");
1241 } else {
1242 switch (type) {
1243 case DOUBLE_ARRAY: {
1244 // Format the string representation of the int array as value1 value2......
1245 double[] valueArray = (double[]) value;
1246 for (int i = 0; i < valueArray.length; i++) {
1247 if (i != 0) {
1248 valueString.append(" ");
1249 }
1250 valueString.append(valueArray[i]);
1251 }
1252 break;
1253 }
1254 case INT_ARRAY: {
1255 // Format the string representation of the int array as value1 value2......
1256 int[] valueArray = (int[]) value;
1257 for (int i = 0; i < valueArray.length; i++) {
1258 if (i != 0) {
1259 valueString.append(" ");
1260 }
1261 valueString.append(valueArray[i]);
1262 }
1263 break;
1264 }
1265 case LONG_ARRAY: {
1266 // Format the string representation of the int array as value1 value2......
1267 long[] valueArray = (long[]) value;
1268 for (int i = 0; i < valueArray.length; i++) {
1269 if (i != 0) {
1270 valueString.append(" ");
1271 }
1272 valueString.append(valueArray[i]);
1273 }
1274 break;
1275 }
1276 case STRING: {
1277 valueString.append("\"" + value.toString() + "\"");
1278 break;
1279 }
1280 case STRING_ARRAY: {
1281 // Format the string representation of the string array as "value1" "value2"....
1282 String[] valueArray = (String[]) value;
1283 for (int i = 0; i < valueArray.length; i++) {
1284 if (i != 0) {
1285 valueString.append(" ");
1286 }
1287 if (valueArray[i] != null) {
1288 valueString.append("\"" + valueArray[i] + "\"");
1289 } else {
1290 valueString.append("null");
1291 }
1292 }
1293 break;
1294 }
1295 default: {
1296 valueString.append(value.toString());
1297 }
1298 }
1299 }
1300 return String.format("%-70s %-15s %s", key, typeString, valueString);
1301 }
1302
1303 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1304 ArrayList<String> valueList) {
1305 PrintWriter errPw = getErrPrintWriter();
1306 PersistableBundle bundle = new PersistableBundle();
1307
1308 // First verify that a valid number of values has been provided for the type.
1309 switch (type) {
1310 case BOOLEAN:
1311 case DOUBLE:
1312 case INT:
1313 case LONG: {
1314 if (valueList.size() != 1) {
1315 errPw.println(tag + "Expected 1 value for type " + type
1316 + ". Found: " + valueList.size());
1317 return null;
1318 }
1319 break;
1320 }
1321 case STRING: {
1322 if (valueList.size() > 1) {
1323 errPw.println(tag + "Expected 0 or 1 values for type " + type
1324 + ". Found: " + valueList.size());
1325 return null;
1326 }
1327 break;
1328 }
1329 }
1330
1331 // Parse the value according to type and add it to the Bundle.
1332 switch (type) {
1333 case BOOLEAN: {
1334 if ("true".equalsIgnoreCase(valueList.get(0))) {
1335 bundle.putBoolean(key, true);
1336 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1337 bundle.putBoolean(key, false);
1338 } else {
1339 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1340 return null;
1341 }
1342 break;
1343 }
1344 case DOUBLE: {
1345 try {
1346 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1347 } catch (NumberFormatException nfe) {
1348 // Not a valid double
1349 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1350 return null;
1351 }
1352 break;
1353 }
1354 case DOUBLE_ARRAY: {
1355 double[] valueDoubleArray = null;
1356 if (valueList.size() > 0) {
1357 valueDoubleArray = new double[valueList.size()];
1358 for (int i = 0; i < valueList.size(); i++) {
1359 try {
1360 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1361 } catch (NumberFormatException nfe) {
1362 // Not a valid double
1363 errPw.println(
1364 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1365 return null;
1366 }
1367 }
1368 }
1369 bundle.putDoubleArray(key, valueDoubleArray);
1370 break;
1371 }
1372 case INT: {
1373 try {
1374 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1375 } catch (NumberFormatException nfe) {
1376 // Not a valid integer
1377 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1378 return null;
1379 }
1380 break;
1381 }
1382 case INT_ARRAY: {
1383 int[] valueIntArray = null;
1384 if (valueList.size() > 0) {
1385 valueIntArray = new int[valueList.size()];
1386 for (int i = 0; i < valueList.size(); i++) {
1387 try {
1388 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1389 } catch (NumberFormatException nfe) {
1390 // Not a valid integer
1391 errPw.println(tag
1392 + "Unable to parse " + valueList.get(i) + " as an integer.");
1393 return null;
1394 }
1395 }
1396 }
1397 bundle.putIntArray(key, valueIntArray);
1398 break;
1399 }
1400 case LONG: {
1401 try {
1402 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1403 } catch (NumberFormatException nfe) {
1404 // Not a valid long
1405 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1406 return null;
1407 }
1408 break;
1409 }
1410 case LONG_ARRAY: {
1411 long[] valueLongArray = null;
1412 if (valueList.size() > 0) {
1413 valueLongArray = new long[valueList.size()];
1414 for (int i = 0; i < valueList.size(); i++) {
1415 try {
1416 valueLongArray[i] = Long.parseLong(valueList.get(i));
1417 } catch (NumberFormatException nfe) {
1418 // Not a valid long
1419 errPw.println(
1420 tag + "Unable to parse " + valueList.get(i) + " as a long");
1421 return null;
1422 }
1423 }
1424 }
1425 bundle.putLongArray(key, valueLongArray);
1426 break;
1427 }
1428 case STRING: {
1429 String value = null;
1430 if (valueList.size() > 0) {
1431 value = valueList.get(0);
1432 }
1433 bundle.putString(key, value);
1434 break;
1435 }
1436 case STRING_ARRAY: {
1437 String[] valueStringArray = null;
1438 if (valueList.size() > 0) {
1439 valueStringArray = new String[valueList.size()];
1440 valueList.toArray(valueStringArray);
1441 }
1442 bundle.putStringArray(key, valueStringArray);
1443 break;
1444 }
1445 }
1446 return bundle;
1447 }
Shuo Qian489d9282020-07-09 11:30:03 -07001448
1449 private int handleEndBlockSuppressionCommand() {
1450 if (!checkShellUid()) {
1451 return -1;
1452 }
1453
1454 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1455 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1456 }
1457 return 0;
1458 }
Hui Wang641e81c2020-10-12 12:14:23 -07001459
Michele Berionne54af4632020-12-28 20:23:16 +00001460 private int handleRestartModemCommand() {
1461 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1462 // non user build.
1463 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1464 getErrPrintWriter().println("RestartModem: Permission denied.");
1465 return -1;
1466 }
1467
1468 boolean result = TelephonyManager.getDefault().rebootRadio();
1469 getOutPrintWriter().println(result);
1470
1471 return result ? 0 : -1;
1472 }
1473
Michele Berionne5e411512020-11-13 02:36:59 +00001474 private int handleUnattendedReboot() {
1475 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1476 // non user build.
1477 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1478 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1479 return -1;
1480 }
1481
1482 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1483 getOutPrintWriter().println("result: " + result);
1484
1485 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1486 }
1487
Hui Wang641e81c2020-10-12 12:14:23 -07001488 private int handleGbaCommand() {
1489 String arg = getNextArg();
1490 if (arg == null) {
1491 onHelpGba();
1492 return 0;
1493 }
1494
1495 switch (arg) {
1496 case GBA_SET_SERVICE: {
1497 return handleGbaSetServiceCommand();
1498 }
1499 case GBA_GET_SERVICE: {
1500 return handleGbaGetServiceCommand();
1501 }
1502 case GBA_SET_RELEASE_TIME: {
1503 return handleGbaSetReleaseCommand();
1504 }
1505 case GBA_GET_RELEASE_TIME: {
1506 return handleGbaGetReleaseCommand();
1507 }
1508 }
1509
1510 return -1;
1511 }
1512
1513 private int getSubId(String cmd) {
1514 int slotId = getDefaultSlot();
1515 String opt = getNextOption();
1516 if (opt != null && opt.equals("-s")) {
1517 try {
1518 slotId = Integer.parseInt(getNextArgRequired());
1519 } catch (NumberFormatException e) {
1520 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1521 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1522 }
1523 }
1524 int[] subIds = SubscriptionManager.getSubId(slotId);
1525 return subIds[0];
1526 }
1527
1528 private int handleGbaSetServiceCommand() {
1529 int subId = getSubId("gba set-service");
1530 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1531 return -1;
1532 }
1533
1534 String packageName = getNextArg();
1535 try {
1536 if (packageName == null) {
1537 packageName = "";
1538 }
1539 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1540 if (VDBG) {
1541 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1542 + packageName + ", result=" + result);
1543 }
1544 getOutPrintWriter().println(result);
1545 } catch (RemoteException e) {
1546 Log.w(LOG_TAG, "gba set-service " + subId + " "
1547 + packageName + ", error" + e.getMessage());
1548 getErrPrintWriter().println("Exception: " + e.getMessage());
1549 return -1;
1550 }
1551 return 0;
1552 }
1553
1554 private int handleGbaGetServiceCommand() {
1555 String result;
1556
1557 int subId = getSubId("gba get-service");
1558 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1559 return -1;
1560 }
1561
1562 try {
1563 result = mInterface.getBoundGbaService(subId);
1564 } catch (RemoteException e) {
1565 return -1;
1566 }
1567 if (VDBG) {
1568 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1569 }
1570 getOutPrintWriter().println(result);
1571 return 0;
1572 }
1573
1574 private int handleGbaSetReleaseCommand() {
1575 //the release time value could be -1
1576 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1577 : SubscriptionManager.getDefaultSubscriptionId();
1578 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1579 return -1;
1580 }
1581
1582 String intervalStr = getNextArg();
1583 if (intervalStr == null) {
1584 return -1;
1585 }
1586
1587 try {
1588 int interval = Integer.parseInt(intervalStr);
1589 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1590 if (VDBG) {
1591 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1592 + intervalStr + ", result=" + result);
1593 }
1594 getOutPrintWriter().println(result);
1595 } catch (NumberFormatException | RemoteException e) {
1596 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1597 + intervalStr + ", error" + e.getMessage());
1598 getErrPrintWriter().println("Exception: " + e.getMessage());
1599 return -1;
1600 }
1601 return 0;
1602 }
1603
1604 private int handleGbaGetReleaseCommand() {
1605 int subId = getSubId("gba get-release");
1606 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1607 return -1;
1608 }
1609
1610 int result = 0;
1611 try {
1612 result = mInterface.getGbaReleaseTime(subId);
1613 } catch (RemoteException e) {
1614 return -1;
1615 }
1616 if (VDBG) {
1617 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1618 }
1619 getOutPrintWriter().println(result);
1620 return 0;
1621 }
Hui Wang761a6682020-10-31 05:12:53 +00001622
1623 private int handleSingleRegistrationConfigCommand() {
1624 String arg = getNextArg();
1625 if (arg == null) {
1626 onHelpSrc();
1627 return 0;
1628 }
1629
1630 switch (arg) {
1631 case SRC_SET_DEVICE_ENABLED: {
1632 return handleSrcSetDeviceEnabledCommand();
1633 }
1634 case SRC_GET_DEVICE_ENABLED: {
1635 return handleSrcGetDeviceEnabledCommand();
1636 }
1637 case SRC_SET_CARRIER_ENABLED: {
1638 return handleSrcSetCarrierEnabledCommand();
1639 }
1640 case SRC_GET_CARRIER_ENABLED: {
1641 return handleSrcGetCarrierEnabledCommand();
1642 }
1643 }
1644
1645 return -1;
1646 }
1647
James.cf Linbcdf8b32021-01-14 16:44:13 +08001648 private int handleRcsUceCommand() {
1649 String arg = getNextArg();
1650 if (arg == null) {
1651 Log.w(LOG_TAG, "cannot get uce parameter");
1652 return -1;
1653 }
1654
1655 switch (arg) {
1656 case UCE_REMOVE_EAB_CONTACT:
1657 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001658 case UCE_GET_EAB_CONTACT:
1659 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001660 case UCE_GET_DEVICE_ENABLED:
1661 return handleUceGetDeviceEnabledCommand();
1662 case UCE_SET_DEVICE_ENABLED:
1663 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001664 }
1665 return -1;
1666 }
1667
1668 private int handleRemovingEabContactCommand() {
1669 int subId = getSubId("uce remove-eab-contact");
1670 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1671 return -1;
1672 }
1673
1674 String phoneNumber = getNextArgRequired();
1675 if (TextUtils.isEmpty(phoneNumber)) {
1676 return -1;
1677 }
1678 int result = 0;
1679 try {
1680 result = mInterface.removeContactFromEab(subId, phoneNumber);
1681 } catch (RemoteException e) {
1682 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1683 getErrPrintWriter().println("Exception: " + e.getMessage());
1684 return -1;
1685 }
1686
1687 if (VDBG) {
1688 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1689 }
calvinpan293ea1b2021-02-04 17:52:13 +08001690 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001691 }
1692
calvinpane4a8a1d2021-01-25 13:51:18 +08001693 private int handleGettingEabContactCommand() {
1694 String phoneNumber = getNextArgRequired();
1695 if (TextUtils.isEmpty(phoneNumber)) {
1696 return -1;
1697 }
1698 String result = "";
1699 try {
1700 result = mInterface.getContactFromEab(phoneNumber);
1701
1702 } catch (RemoteException e) {
1703 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1704 getErrPrintWriter().println("Exception: " + e.getMessage());
1705 return -1;
1706 }
1707
1708 if (VDBG) {
1709 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1710 }
calvinpan293ea1b2021-02-04 17:52:13 +08001711 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001712 return 0;
1713 }
1714
1715 private int handleUceGetDeviceEnabledCommand() {
1716 boolean result = false;
1717 try {
1718 result = mInterface.getDeviceUceEnabled();
1719 } catch (RemoteException e) {
1720 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1721 return -1;
1722 }
1723 if (VDBG) {
1724 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1725 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001726 getOutPrintWriter().println(result);
1727 return 0;
1728 }
1729
James.cf Lin4b784aa2021-01-31 03:25:15 +08001730 private int handleUceSetDeviceEnabledCommand() {
1731 String enabledStr = getNextArg();
1732 if (TextUtils.isEmpty(enabledStr)) {
1733 return -1;
1734 }
1735
1736 try {
1737 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1738 mInterface.setDeviceUceEnabled(isEnabled);
1739 if (VDBG) {
1740 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1741 }
1742 } catch (NumberFormatException | RemoteException e) {
1743 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1744 getErrPrintWriter().println("Exception: " + e.getMessage());
1745 return -1;
1746 }
1747 return 0;
1748 }
1749
Hui Wang761a6682020-10-31 05:12:53 +00001750 private int handleSrcSetDeviceEnabledCommand() {
1751 String enabledStr = getNextArg();
1752 if (enabledStr == null) {
1753 return -1;
1754 }
1755
1756 try {
1757 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1758 if (VDBG) {
1759 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1760 }
1761 getOutPrintWriter().println("Done");
1762 } catch (NumberFormatException | RemoteException e) {
1763 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1764 getErrPrintWriter().println("Exception: " + e.getMessage());
1765 return -1;
1766 }
1767 return 0;
1768 }
1769
1770 private int handleSrcGetDeviceEnabledCommand() {
1771 boolean result = false;
1772 try {
1773 result = mInterface.getDeviceSingleRegistrationEnabled();
1774 } catch (RemoteException e) {
1775 return -1;
1776 }
1777 if (VDBG) {
1778 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1779 }
1780 getOutPrintWriter().println(result);
1781 return 0;
1782 }
1783
1784 private int handleSrcSetCarrierEnabledCommand() {
1785 //the release time value could be -1
1786 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1787 : SubscriptionManager.getDefaultSubscriptionId();
1788 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1789 return -1;
1790 }
1791
1792 String enabledStr = getNextArg();
1793 if (enabledStr == null) {
1794 return -1;
1795 }
1796
1797 try {
1798 boolean result =
1799 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1800 if (VDBG) {
1801 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1802 + enabledStr + ", result=" + result);
1803 }
1804 getOutPrintWriter().println(result);
1805 } catch (NumberFormatException | RemoteException e) {
1806 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1807 + enabledStr + ", error" + e.getMessage());
1808 getErrPrintWriter().println("Exception: " + e.getMessage());
1809 return -1;
1810 }
1811 return 0;
1812 }
1813
1814 private int handleSrcGetCarrierEnabledCommand() {
1815 int subId = getSubId("src get-carrier-enabled");
1816 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1817 return -1;
1818 }
1819
1820 boolean result = false;
1821 try {
1822 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1823 } catch (RemoteException e) {
1824 return -1;
1825 }
1826 if (VDBG) {
1827 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1828 }
1829 getOutPrintWriter().println(result);
1830 return 0;
1831 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001832
1833 private void onHelpCallComposer() {
1834 PrintWriter pw = getOutPrintWriter();
1835 pw.println("Call composer commands");
1836 pw.println(" callcomposer test-mode enable|disable|query");
1837 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1838 pw.println(" upload/download from carrier servers is disabled, and operations are");
1839 pw.println(" performed using emulated local files instead.");
1840 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1841 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1842 pw.println(" the provided UUID. This triggers storage to the call log.");
1843 }
1844
1845 private int handleCallComposerCommand() {
1846 String arg = getNextArg();
1847 if (arg == null) {
1848 onHelpCallComposer();
1849 return 0;
1850 }
1851
1852 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1853 "MODIFY_PHONE_STATE required for call composer shell cmds");
1854 switch (arg) {
1855 case CALL_COMPOSER_TEST_MODE: {
1856 String enabledStr = getNextArg();
1857 if (ENABLE.equals(enabledStr)) {
1858 CallComposerPictureManager.sTestMode = true;
1859 } else if (DISABLE.equals(enabledStr)) {
1860 CallComposerPictureManager.sTestMode = false;
1861 } else if (QUERY.equals(enabledStr)) {
1862 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1863 } else {
1864 onHelpCallComposer();
1865 return 1;
1866 }
1867 break;
1868 }
1869 case CALL_COMPOSER_SIMULATE_CALL: {
1870 int subscriptionId = Integer.valueOf(getNextArg());
1871 String uuidString = getNextArg();
1872 UUID uuid = UUID.fromString(uuidString);
1873 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1874 Binder.withCleanCallingIdentity(() -> {
1875 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1876 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1877 });
1878 try {
1879 Uri uri = storageUriFuture.get();
1880 getOutPrintWriter().println(String.valueOf(uri));
1881 } catch (Exception e) {
1882 throw new RuntimeException(e);
1883 }
1884 break;
1885 }
1886 }
1887
1888 return 0;
1889 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001890}