blob: 9676e59bb8566ac73095d25033f83502582129fb [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";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010077 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080078 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080079 private static final String ENABLE = "enable";
80 private static final String DISABLE = "disable";
81 private static final String QUERY = "query";
82
83 private static final String CALL_COMPOSER_TEST_MODE = "test_mode";
84 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liud892bec2018-11-30 14:51:45 -080085
Brad Ebinger999d3302020-11-25 14:31:39 -080086 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
87 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
88 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070089 // Used to disable or enable processing of conference event package data from the network.
90 // This is handy for testing scenarios where CEP data does not exist on a network which does
91 // support CEP data.
92 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070093
Hall Liud892bec2018-11-30 14:51:45 -080094 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080095 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080096
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010097 private static final String CC_GET_VALUE = "get-value";
98 private static final String CC_SET_VALUE = "set-value";
99 private static final String CC_CLEAR_VALUES = "clear-values";
100
Hui Wang641e81c2020-10-12 12:14:23 -0700101 private static final String GBA_SUBCOMMAND = "gba";
102 private static final String GBA_SET_SERVICE = "set-service";
103 private static final String GBA_GET_SERVICE = "get-service";
104 private static final String GBA_SET_RELEASE_TIME = "set-release";
105 private static final String GBA_GET_RELEASE_TIME = "get-release";
106
Hui Wang761a6682020-10-31 05:12:53 +0000107 private static final String SINGLE_REGISTATION_CONFIG = "src";
108 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
109 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
110 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
111 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
112
Tyler Gunn92479152021-01-20 16:30:10 -0800113 private static final String D2D_SUBCOMMAND = "d2d";
114 private static final String D2D_SEND = "send";
115
James.cf Linbcdf8b32021-01-14 16:44:13 +0800116 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800117 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800118 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800119 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
120 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800121
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700122 // Take advantage of existing methods that already contain permissions checks when possible.
123 private final ITelephony mInterface;
124
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100125 private SubscriptionManager mSubscriptionManager;
126 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700127 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100128
129 private enum CcType {
130 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
131 STRING_ARRAY, UNKNOWN
132 }
133
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100134 private class CcOptionParseResult {
135 public int mSubId;
136 public boolean mPersistent;
137 }
138
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100139 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
140 // keys by looking at the end of the string which usually tells the type.
141 // For instance: "xxxx_string", "xxxx_string_array", etc.
142 // The carrier config keys in this map does not follow this convention. It is therefore not
143 // possible to infer the type for these keys by looking at the string.
144 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
145 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
156 CcType.STRING);
157 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
158 CcType.STRING_ARRAY);
159 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
160 CcType.STRING_ARRAY);
161 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
162 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
163 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
164 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
165 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
167 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
168 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
169 }
170 };
171
172 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700173 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100174 mCarrierConfigManager =
175 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
176 mSubscriptionManager = (SubscriptionManager)
177 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700178 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700179 }
180
181 @Override
182 public int onCommand(String cmd) {
183 if (cmd == null) {
184 return handleDefaultCommands(null);
185 }
186
187 switch (cmd) {
188 case IMS_SUBCOMMAND: {
189 return handleImsCommand();
190 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800191 case RCS_UCE_COMMAND:
192 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800193 case NUMBER_VERIFICATION_SUBCOMMAND:
194 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800195 case EMERGENCY_NUMBER_TEST_MODE:
196 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100197 case CARRIER_CONFIG_SUBCOMMAND: {
198 return handleCcCommand();
199 }
Shuo Qianf5125122019-12-16 17:03:07 -0800200 case DATA_TEST_MODE:
201 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700202 case END_BLOCK_SUPPRESSION:
203 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700204 case GBA_SUBCOMMAND:
205 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800206 case D2D_SUBCOMMAND:
207 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000208 case SINGLE_REGISTATION_CONFIG:
209 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000210 case RESTART_MODEM:
211 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800212 case CALL_COMPOSER_SUBCOMMAND:
213 return handleCallComposerCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700214 default: {
215 return handleDefaultCommands(cmd);
216 }
217 }
218 }
219
220 @Override
221 public void onHelp() {
222 PrintWriter pw = getOutPrintWriter();
223 pw.println("Telephony Commands:");
224 pw.println(" help");
225 pw.println(" Print this help text.");
226 pw.println(" ims");
227 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800228 pw.println(" uce");
229 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800230 pw.println(" emergency-number-test-mode");
231 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700232 pw.println(" end-block-suppression");
233 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800234 pw.println(" data");
235 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100236 pw.println(" cc");
237 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700238 pw.println(" gba");
239 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000240 pw.println(" src");
241 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000242 pw.println(" restart-modem");
243 pw.println(" Restart modem command.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700244 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800245 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800246 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700247 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800248 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100249 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700250 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000251 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800252 onHelpD2D();
253 }
254
255 private void onHelpD2D() {
256 PrintWriter pw = getOutPrintWriter();
257 pw.println("D2D Comms Commands:");
258 pw.println(" d2d send TYPE VALUE");
259 pw.println(" Sends a D2D message of specified type and value.");
260 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
261 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
262 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
263 MESSAGE_CALL_AUDIO_CODEC));
264 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
265 + Communicator.messageToString(
266 MESSAGE_DEVICE_BATTERY_STATE));
267 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
268 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700269 }
270
271 private void onHelpIms() {
272 PrintWriter pw = getOutPrintWriter();
273 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800274 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700275 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
276 pw.println(" ImsService. Options are:");
277 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
278 pw.println(" is specified, it will choose the default voice SIM slot.");
279 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
280 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800281 pw.println(" -f: Set the feature that this override if for, if no option is");
282 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700283 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
284 pw.println(" Gets the package name of the currently defined ImsService.");
285 pw.println(" Options are:");
286 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
287 pw.println(" is specified, it will choose the default voice SIM slot.");
288 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000289 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800290 pw.println(" -f: The feature type that the query will be requested for. If none is");
291 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800292 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
293 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
294 pw.println(" configuration overrides. Options are:");
295 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
296 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700297 pw.println(" ims enable [-s SLOT_ID]");
298 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
299 pw.println(" if none is specified.");
300 pw.println(" ims disable [-s SLOT_ID]");
301 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
302 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700303 pw.println(" ims conference-event-package [enable/disable]");
304 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700305 }
306
James.cf Linbcdf8b32021-01-14 16:44:13 +0800307 private void onHelpUce() {
308 PrintWriter pw = getOutPrintWriter();
309 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800310 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
311 pw.println(" Get the EAB contacts from the EAB database.");
312 pw.println(" Options are:");
313 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
314 pw.println(" Expected output format :");
315 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800316 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
317 pw.println(" Remove the EAB contacts from the EAB database.");
318 pw.println(" Options are:");
319 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
320 pw.println(" is specified, it will choose the default voice SIM slot.");
321 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800322 pw.println(" uce get-device-enabled");
323 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
324 pw.println(" uce set-device-enabled true|false");
325 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
326 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800327 }
328
Hall Liud892bec2018-11-30 14:51:45 -0800329 private void onHelpNumberVerification() {
330 PrintWriter pw = getOutPrintWriter();
331 pw.println("Number verification commands");
332 pw.println(" numverify override-package PACKAGE_NAME;");
333 pw.println(" Set the authorized package for number verification.");
334 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800335 pw.println(" numverify fake-call NUMBER;");
336 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
337 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800338 }
339
Shuo Qianf5125122019-12-16 17:03:07 -0800340 private void onHelpDataTestMode() {
341 PrintWriter pw = getOutPrintWriter();
342 pw.println("Mobile Data Test Mode Commands:");
343 pw.println(" data enable: enable mobile data connectivity");
344 pw.println(" data disable: disable mobile data connectivity");
345 }
346
sqian9d4df8b2019-01-15 18:32:07 -0800347 private void onHelpEmergencyNumber() {
348 PrintWriter pw = getOutPrintWriter();
349 pw.println("Emergency Number Test Mode Commands:");
350 pw.println(" emergency-number-test-mode ");
351 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
352 + " the test mode");
353 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700354 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800355 pw.println(" -c: clear the emergency number list in the test mode.");
356 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700357 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800358 pw.println(" -p: get the full emergency number list in the test mode.");
359 }
360
Shuo Qian489d9282020-07-09 11:30:03 -0700361 private void onHelpEndBlockSupperssion() {
362 PrintWriter pw = getOutPrintWriter();
363 pw.println("End Block Suppression command:");
364 pw.println(" end-block-suppression: disable suppressing blocking by contact");
365 pw.println(" with emergency services.");
366 }
367
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100368 private void onHelpCc() {
369 PrintWriter pw = getOutPrintWriter();
370 pw.println("Carrier Config Commands:");
371 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
372 pw.println(" Print carrier config values.");
373 pw.println(" Options are:");
374 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
375 pw.println(" is specified, it will choose the default voice SIM slot.");
376 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
377 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100378 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100379 pw.println(" Set carrier config KEY to NEW_VALUE.");
380 pw.println(" Options are:");
381 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
382 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100383 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100384 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
385 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
386 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
387 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
388 pw.println(" cc clear-values [-s SLOT_ID]");
389 pw.println(" Clear all carrier override values that has previously been set");
390 pw.println(" with set-value");
391 pw.println(" Options are:");
392 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
393 pw.println(" is specified, it will choose the default voice SIM slot.");
394 }
395
Hui Wang641e81c2020-10-12 12:14:23 -0700396 private void onHelpGba() {
397 PrintWriter pw = getOutPrintWriter();
398 pw.println("Gba Commands:");
399 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
400 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
401 pw.println(" Options are:");
402 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
403 pw.println(" is specified, it will choose the default voice SIM slot.");
404 pw.println(" gba get-service [-s SLOT_ID]");
405 pw.println(" Gets the package name of the currently defined GbaService.");
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 set-release [-s SLOT_ID] n");
410 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
411 pw.println(" Do not release/unbind if n is -1.");
412 pw.println(" Options are:");
413 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
414 pw.println(" is specified, it will choose the default voice SIM slot.");
415 pw.println(" gba get-release [-s SLOT_ID]");
416 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
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 }
421
Hui Wang761a6682020-10-31 05:12:53 +0000422 private void onHelpSrc() {
423 PrintWriter pw = getOutPrintWriter();
424 pw.println("RCS VoLTE Single Registration Config Commands:");
425 pw.println(" src set-device-enabled true|false|null");
426 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
427 pw.println(" The value could be true, false, or null(undefined).");
428 pw.println(" src get-device-enabled");
429 pw.println(" Gets the device config for RCS VoLTE single registration.");
430 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
431 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
432 pw.println(" The value could be true, false, or null(undefined).");
433 pw.println(" Options are:");
434 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
435 pw.println(" is specified, it will choose the default voice SIM slot.");
436 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
437 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
438 pw.println(" Options are:");
439 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
440 pw.println(" is specified, it will choose the default voice SIM slot.");
441 }
442
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700443 private int handleImsCommand() {
444 String arg = getNextArg();
445 if (arg == null) {
446 onHelpIms();
447 return 0;
448 }
449
450 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800451 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700452 return handleImsSetServiceCommand();
453 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800454 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700455 return handleImsGetServiceCommand();
456 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800457 case IMS_CLEAR_SERVICE_OVERRIDE: {
458 return handleImsClearCarrierServiceCommand();
459 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800460 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700461 return handleEnableIms();
462 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800463 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700464 return handleDisableIms();
465 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700466 case IMS_CEP: {
467 return handleCepChange();
468 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700469 }
470
471 return -1;
472 }
473
Shuo Qianf5125122019-12-16 17:03:07 -0800474 private int handleDataTestModeCommand() {
475 PrintWriter errPw = getErrPrintWriter();
476 String arg = getNextArgRequired();
477 if (arg == null) {
478 onHelpDataTestMode();
479 return 0;
480 }
481 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800482 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800483 try {
484 mInterface.enableDataConnectivity();
485 } catch (RemoteException ex) {
486 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
487 errPw.println("Exception: " + ex.getMessage());
488 return -1;
489 }
490 break;
491 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800492 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800493 try {
494 mInterface.disableDataConnectivity();
495 } catch (RemoteException ex) {
496 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
497 errPw.println("Exception: " + ex.getMessage());
498 return -1;
499 }
500 break;
501 }
502 default:
503 onHelpDataTestMode();
504 break;
505 }
506 return 0;
507 }
508
sqian9d4df8b2019-01-15 18:32:07 -0800509 private int handleEmergencyNumberTestModeCommand() {
510 PrintWriter errPw = getErrPrintWriter();
511 String opt = getNextOption();
512 if (opt == null) {
513 onHelpEmergencyNumber();
514 return 0;
515 }
516
517 switch (opt) {
518 case "-a": {
519 String emergencyNumberCmd = getNextArgRequired();
520 if (emergencyNumberCmd == null
521 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700522 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800523 + " to be specified after -a in the command ");
524 return -1;
525 }
526 try {
527 mInterface.updateEmergencyNumberListTestMode(
528 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
529 new EmergencyNumber(emergencyNumberCmd, "", "",
530 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
531 new ArrayList<String>(),
532 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
533 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
534 } catch (RemoteException ex) {
535 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
536 + ", error " + ex.getMessage());
537 errPw.println("Exception: " + ex.getMessage());
538 return -1;
539 }
540 break;
541 }
542 case "-c": {
543 try {
544 mInterface.updateEmergencyNumberListTestMode(
545 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
546 } catch (RemoteException ex) {
547 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
548 errPw.println("Exception: " + ex.getMessage());
549 return -1;
550 }
551 break;
552 }
553 case "-r": {
554 String emergencyNumberCmd = getNextArgRequired();
555 if (emergencyNumberCmd == null
556 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700557 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800558 + " to be specified after -r in the command ");
559 return -1;
560 }
561 try {
562 mInterface.updateEmergencyNumberListTestMode(
563 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
564 new EmergencyNumber(emergencyNumberCmd, "", "",
565 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
566 new ArrayList<String>(),
567 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
568 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
569 } catch (RemoteException ex) {
570 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
571 + ", error " + ex.getMessage());
572 errPw.println("Exception: " + ex.getMessage());
573 return -1;
574 }
575 break;
576 }
577 case "-p": {
578 try {
579 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
580 } catch (RemoteException ex) {
581 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
582 errPw.println("Exception: " + ex.getMessage());
583 return -1;
584 }
585 break;
586 }
587 default:
588 onHelpEmergencyNumber();
589 break;
590 }
591 return 0;
592 }
593
Hall Liud892bec2018-11-30 14:51:45 -0800594 private int handleNumberVerificationCommand() {
595 String arg = getNextArg();
596 if (arg == null) {
597 onHelpNumberVerification();
598 return 0;
599 }
600
Hall Liuca5af3a2018-12-04 16:58:23 -0800601 if (!checkShellUid()) {
602 return -1;
603 }
604
Hall Liud892bec2018-11-30 14:51:45 -0800605 switch (arg) {
606 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800607 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
608 return 0;
609 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800610 case NUMBER_VERIFICATION_FAKE_CALL: {
611 boolean val = NumberVerificationManager.getInstance()
612 .checkIncomingCall(getNextArg());
613 getOutPrintWriter().println(val ? "1" : "0");
614 return 0;
615 }
Hall Liud892bec2018-11-30 14:51:45 -0800616 }
617
618 return -1;
619 }
620
Tyler Gunn92479152021-01-20 16:30:10 -0800621 private int handleD2dCommand() {
622 String arg = getNextArg();
623 if (arg == null) {
624 onHelpD2D();
625 return 0;
626 }
627
628 switch (arg) {
629 case D2D_SEND: {
630 return handleD2dSendCommand();
631 }
632 }
633
634 return -1;
635 }
636
637 private int handleD2dSendCommand() {
638 PrintWriter errPw = getErrPrintWriter();
639 String opt;
640 int messageType = -1;
641 int messageValue = -1;
642
643
644 String arg = getNextArg();
645 if (arg == null) {
646 onHelpD2D();
647 return 0;
648 }
649 try {
650 messageType = Integer.parseInt(arg);
651 } catch (NumberFormatException e) {
652 errPw.println("message type must be a valid integer");
653 return -1;
654 }
655
656 arg = getNextArg();
657 if (arg == null) {
658 onHelpD2D();
659 return 0;
660 }
661 try {
662 messageValue = Integer.parseInt(arg);
663 } catch (NumberFormatException e) {
664 errPw.println("message value must be a valid integer");
665 return -1;
666 }
667
668 try {
669 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
670 } catch (RemoteException e) {
671 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
672 errPw.println("Exception: " + e.getMessage());
673 return -1;
674 }
675
676 return 0;
677 }
678
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700679 // ims set-ims-service
680 private int handleImsSetServiceCommand() {
681 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700682 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700683 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800684 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700685
686 String opt;
687 while ((opt = getNextOption()) != null) {
688 switch (opt) {
689 case "-s": {
690 try {
691 slotId = Integer.parseInt(getNextArgRequired());
692 } catch (NumberFormatException e) {
693 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
694 return -1;
695 }
696 break;
697 }
698 case "-c": {
699 isCarrierService = true;
700 break;
701 }
702 case "-d": {
703 isCarrierService = false;
704 break;
705 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800706 case "-f": {
707 String featureString = getNextArgRequired();
708 String[] features = featureString.split(",");
709 for (int i = 0; i < features.length; i++) {
710 try {
711 Integer result = Integer.parseInt(features[i]);
712 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
713 || result >= ImsFeature.FEATURE_MAX) {
714 errPw.println("ims set-ims-service -f " + result
715 + " is an invalid feature.");
716 return -1;
717 }
718 featuresList.add(result);
719 } catch (NumberFormatException e) {
720 errPw.println("ims set-ims-service -f tried to parse " + features[i]
721 + " as an integer.");
722 return -1;
723 }
724 }
725 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700726 }
727 }
728 // Mandatory param, either -c or -d
729 if (isCarrierService == null) {
730 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
731 return -1;
732 }
733
734 String packageName = getNextArg();
735
736 try {
737 if (packageName == null) {
738 packageName = "";
739 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800740 int[] featureArray = new int[featuresList.size()];
741 for (int i = 0; i < featuresList.size(); i++) {
742 featureArray[i] = featuresList.get(i);
743 }
744 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
745 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700746 if (VDBG) {
747 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800748 + (isCarrierService ? "-c " : "-d ")
749 + "-f " + featuresList + " "
750 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700751 }
752 getOutPrintWriter().println(result);
753 } catch (RemoteException e) {
754 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800755 + (isCarrierService ? "-c " : "-d ")
756 + "-f " + featuresList + " "
757 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700758 errPw.println("Exception: " + e.getMessage());
759 return -1;
760 }
761 return 0;
762 }
763
Brad Ebinger999d3302020-11-25 14:31:39 -0800764 // ims clear-ims-service-override
765 private int handleImsClearCarrierServiceCommand() {
766 PrintWriter errPw = getErrPrintWriter();
767 int slotId = getDefaultSlot();
768
769 String opt;
770 while ((opt = getNextOption()) != null) {
771 switch (opt) {
772 case "-s": {
773 try {
774 slotId = Integer.parseInt(getNextArgRequired());
775 } catch (NumberFormatException e) {
776 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
777 return -1;
778 }
779 break;
780 }
781 }
782 }
783
784 try {
785 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
786 if (VDBG) {
787 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
788 + ", result=" + result);
789 }
790 getOutPrintWriter().println(result);
791 } catch (RemoteException e) {
792 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
793 + ", error" + e.getMessage());
794 errPw.println("Exception: " + e.getMessage());
795 return -1;
796 }
797 return 0;
798 }
799
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700800 // ims get-ims-service
801 private int handleImsGetServiceCommand() {
802 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700803 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700804 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800805 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700806
807 String opt;
808 while ((opt = getNextOption()) != null) {
809 switch (opt) {
810 case "-s": {
811 try {
812 slotId = Integer.parseInt(getNextArgRequired());
813 } catch (NumberFormatException e) {
814 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
815 return -1;
816 }
817 break;
818 }
819 case "-c": {
820 isCarrierService = true;
821 break;
822 }
823 case "-d": {
824 isCarrierService = false;
825 break;
826 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800827 case "-f": {
828 try {
829 featureType = Integer.parseInt(getNextArg());
830 } catch (NumberFormatException e) {
831 errPw.println("ims get-ims-service -f requires valid integer as feature.");
832 return -1;
833 }
834 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
835 || featureType >= ImsFeature.FEATURE_MAX) {
836 errPw.println("ims get-ims-service -f invalid feature.");
837 return -1;
838 }
839 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700840 }
841 }
842 // Mandatory param, either -c or -d
843 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800844 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700845 return -1;
846 }
847
848 String result;
849 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800850 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700851 } catch (RemoteException e) {
852 return -1;
853 }
854 if (VDBG) {
855 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800856 + (isCarrierService ? "-c " : "-d ")
857 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
858 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700859 }
860 getOutPrintWriter().println(result);
861 return 0;
862 }
863
864 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700865 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700866 String opt;
867 while ((opt = getNextOption()) != null) {
868 switch (opt) {
869 case "-s": {
870 try {
871 slotId = Integer.parseInt(getNextArgRequired());
872 } catch (NumberFormatException e) {
873 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
874 return -1;
875 }
876 break;
877 }
878 }
879 }
880 try {
881 mInterface.enableIms(slotId);
882 } catch (RemoteException e) {
883 return -1;
884 }
885 if (VDBG) {
886 Log.v(LOG_TAG, "ims enable -s " + slotId);
887 }
888 return 0;
889 }
890
891 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700892 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700893 String opt;
894 while ((opt = getNextOption()) != null) {
895 switch (opt) {
896 case "-s": {
897 try {
898 slotId = Integer.parseInt(getNextArgRequired());
899 } catch (NumberFormatException e) {
900 getErrPrintWriter().println(
901 "ims disable requires an integer as a SLOT_ID.");
902 return -1;
903 }
904 break;
905 }
906 }
907 }
908 try {
909 mInterface.disableIms(slotId);
910 } catch (RemoteException e) {
911 return -1;
912 }
913 if (VDBG) {
914 Log.v(LOG_TAG, "ims disable -s " + slotId);
915 }
916 return 0;
917 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700918
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700919 private int handleCepChange() {
920 Log.i(LOG_TAG, "handleCepChange");
921 String opt = getNextArg();
922 if (opt == null) {
923 return -1;
924 }
925 boolean isCepEnabled = opt.equals("enable");
926
927 try {
928 mInterface.setCepEnabled(isCepEnabled);
929 } catch (RemoteException e) {
930 return -1;
931 }
932 return 0;
933 }
934
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700935 private int getDefaultSlot() {
936 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
937 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
938 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
939 // If there is no default, default to slot 0.
940 slotId = DEFAULT_PHONE_ID;
941 }
942 return slotId;
943 }
sqian2fff4a32018-11-05 14:18:37 -0800944
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100945 // Parse options related to Carrier Config Commands.
946 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100947 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100948 CcOptionParseResult result = new CcOptionParseResult();
949 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
950 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100951
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100952 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100953 while ((opt = getNextOption()) != null) {
954 switch (opt) {
955 case "-s": {
956 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100957 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
958 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
959 errPw.println(tag + "No valid subscription found.");
960 return null;
961 }
962
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100963 } catch (IllegalArgumentException e) {
964 // Missing slot id
965 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100966 return null;
967 }
968 break;
969 }
970 case "-p": {
971 if (allowOptionPersistent) {
972 result.mPersistent = true;
973 } else {
974 errPw.println(tag + "Unexpected option " + opt);
975 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100976 }
977 break;
978 }
979 default: {
980 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100981 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100982 }
983 }
984 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100985 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100986 }
987
988 private int slotStringToSubId(String tag, String slotString) {
989 int slotId = -1;
990 try {
991 slotId = Integer.parseInt(slotString);
992 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800993 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
994 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
995 }
996
997 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100998 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
999 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1000 }
1001
Qiong Liuf25799b2020-09-10 10:13:46 +08001002 Phone phone = PhoneFactory.getPhone(slotId);
1003 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001004 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1005 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1006 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001007 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001008 }
1009
Hall Liud892bec2018-11-30 14:51:45 -08001010 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001011 // adb can run as root or as shell, depending on whether the device is rooted.
1012 return Binder.getCallingUid() == Process.SHELL_UID
1013 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001014 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001015
1016 private int handleCcCommand() {
1017 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1018 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001019 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001020 getErrPrintWriter().println("cc: Permission denied.");
1021 return -1;
1022 }
1023
1024 String arg = getNextArg();
1025 if (arg == null) {
1026 onHelpCc();
1027 return 0;
1028 }
1029
1030 switch (arg) {
1031 case CC_GET_VALUE: {
1032 return handleCcGetValue();
1033 }
1034 case CC_SET_VALUE: {
1035 return handleCcSetValue();
1036 }
1037 case CC_CLEAR_VALUES: {
1038 return handleCcClearValues();
1039 }
1040 default: {
1041 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1042 }
1043 }
1044 return -1;
1045 }
1046
1047 // cc get-value
1048 private int handleCcGetValue() {
1049 PrintWriter errPw = getErrPrintWriter();
1050 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1051 String key = null;
1052
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001053 // Parse all options
1054 CcOptionParseResult options = parseCcOptions(tag, false);
1055 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001056 return -1;
1057 }
1058
1059 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001060 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001061 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001062 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001063 return -1;
1064 }
1065
1066 // Get the key.
1067 key = getNextArg();
1068 if (key != null) {
1069 // A key was provided. Verify if it is a valid key
1070 if (!bundle.containsKey(key)) {
1071 errPw.println(tag + key + " is not a valid key.");
1072 return -1;
1073 }
1074
1075 // Print the carrier config value for key.
1076 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1077 } else {
1078 // No key provided. Show all values.
1079 // Iterate over a sorted list of all carrier config keys and print them.
1080 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1081 for (String k : sortedSet) {
1082 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1083 }
1084 }
1085 return 0;
1086 }
1087
1088 // cc set-value
1089 private int handleCcSetValue() {
1090 PrintWriter errPw = getErrPrintWriter();
1091 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1092
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001093 // Parse all options
1094 CcOptionParseResult options = parseCcOptions(tag, true);
1095 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001096 return -1;
1097 }
1098
1099 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001100 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001101 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001102 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001103 return -1;
1104 }
1105
1106 // Get the key.
1107 String key = getNextArg();
1108 if (key == null || key.equals("")) {
1109 errPw.println(tag + "KEY is missing");
1110 return -1;
1111 }
1112
1113 // Verify if the key is valid
1114 if (!originalValues.containsKey(key)) {
1115 errPw.println(tag + key + " is not a valid key.");
1116 return -1;
1117 }
1118
1119 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1120 ArrayList<String> valueList = new ArrayList<String>();
1121 while (peekNextArg() != null) {
1122 valueList.add(getNextArg());
1123 }
1124
1125 // Find the type of the carrier config value
1126 CcType type = getType(tag, key, originalValues);
1127 if (type == CcType.UNKNOWN) {
1128 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1129 return -1;
1130 }
1131
1132 // Create an override bundle containing the key and value that should be overriden.
1133 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1134 if (overrideBundle == null) {
1135 return -1;
1136 }
1137
1138 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001139 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001140
1141 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001142 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001143 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001144 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001145 return -1;
1146 }
1147
1148 // Print the original and new value.
1149 String originalValueString = ccValueToString(key, type, originalValues);
1150 String newValueString = ccValueToString(key, type, newValues);
1151 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1152 getOutPrintWriter().println("New value: \n" + newValueString);
1153
1154 return 0;
1155 }
1156
1157 // cc clear-values
1158 private int handleCcClearValues() {
1159 PrintWriter errPw = getErrPrintWriter();
1160 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1161
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001162 // Parse all options
1163 CcOptionParseResult options = parseCcOptions(tag, false);
1164 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001165 return -1;
1166 }
1167
1168 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001169 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001170 getOutPrintWriter()
1171 .println("All previously set carrier config override values has been cleared");
1172 return 0;
1173 }
1174
1175 private CcType getType(String tag, String key, PersistableBundle bundle) {
1176 // Find the type by checking the type of the current value stored in the bundle.
1177 Object value = bundle.get(key);
1178
1179 if (CC_TYPE_MAP.containsKey(key)) {
1180 return CC_TYPE_MAP.get(key);
1181 } else if (value != null) {
1182 if (value instanceof Boolean) {
1183 return CcType.BOOLEAN;
1184 } else if (value instanceof Double) {
1185 return CcType.DOUBLE;
1186 } else if (value instanceof double[]) {
1187 return CcType.DOUBLE_ARRAY;
1188 } else if (value instanceof Integer) {
1189 return CcType.INT;
1190 } else if (value instanceof int[]) {
1191 return CcType.INT_ARRAY;
1192 } else if (value instanceof Long) {
1193 return CcType.LONG;
1194 } else if (value instanceof long[]) {
1195 return CcType.LONG_ARRAY;
1196 } else if (value instanceof String) {
1197 return CcType.STRING;
1198 } else if (value instanceof String[]) {
1199 return CcType.STRING_ARRAY;
1200 }
1201 } else {
1202 // Current value was null and can therefore not be used in order to find the type.
1203 // Check the name of the key to infer the type. This check is not needed for primitive
1204 // data types (boolean, double, int and long), since they can not be null.
1205 if (key.endsWith("double_array")) {
1206 return CcType.DOUBLE_ARRAY;
1207 }
1208 if (key.endsWith("int_array")) {
1209 return CcType.INT_ARRAY;
1210 }
1211 if (key.endsWith("long_array")) {
1212 return CcType.LONG_ARRAY;
1213 }
1214 if (key.endsWith("string")) {
1215 return CcType.STRING;
1216 }
1217 if (key.endsWith("string_array") || key.endsWith("strings")) {
1218 return CcType.STRING_ARRAY;
1219 }
1220 }
1221
1222 // Not possible to infer the type by looking at the current value or the key.
1223 PrintWriter errPw = getErrPrintWriter();
1224 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1225 return CcType.UNKNOWN;
1226 }
1227
1228 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1229 String result;
1230 StringBuilder valueString = new StringBuilder();
1231 String typeString = type.toString();
1232 Object value = bundle.get(key);
1233
1234 if (value == null) {
1235 valueString.append("null");
1236 } else {
1237 switch (type) {
1238 case DOUBLE_ARRAY: {
1239 // Format the string representation of the int array as value1 value2......
1240 double[] valueArray = (double[]) value;
1241 for (int i = 0; i < valueArray.length; i++) {
1242 if (i != 0) {
1243 valueString.append(" ");
1244 }
1245 valueString.append(valueArray[i]);
1246 }
1247 break;
1248 }
1249 case INT_ARRAY: {
1250 // Format the string representation of the int array as value1 value2......
1251 int[] valueArray = (int[]) value;
1252 for (int i = 0; i < valueArray.length; i++) {
1253 if (i != 0) {
1254 valueString.append(" ");
1255 }
1256 valueString.append(valueArray[i]);
1257 }
1258 break;
1259 }
1260 case LONG_ARRAY: {
1261 // Format the string representation of the int array as value1 value2......
1262 long[] valueArray = (long[]) value;
1263 for (int i = 0; i < valueArray.length; i++) {
1264 if (i != 0) {
1265 valueString.append(" ");
1266 }
1267 valueString.append(valueArray[i]);
1268 }
1269 break;
1270 }
1271 case STRING: {
1272 valueString.append("\"" + value.toString() + "\"");
1273 break;
1274 }
1275 case STRING_ARRAY: {
1276 // Format the string representation of the string array as "value1" "value2"....
1277 String[] valueArray = (String[]) value;
1278 for (int i = 0; i < valueArray.length; i++) {
1279 if (i != 0) {
1280 valueString.append(" ");
1281 }
1282 if (valueArray[i] != null) {
1283 valueString.append("\"" + valueArray[i] + "\"");
1284 } else {
1285 valueString.append("null");
1286 }
1287 }
1288 break;
1289 }
1290 default: {
1291 valueString.append(value.toString());
1292 }
1293 }
1294 }
1295 return String.format("%-70s %-15s %s", key, typeString, valueString);
1296 }
1297
1298 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1299 ArrayList<String> valueList) {
1300 PrintWriter errPw = getErrPrintWriter();
1301 PersistableBundle bundle = new PersistableBundle();
1302
1303 // First verify that a valid number of values has been provided for the type.
1304 switch (type) {
1305 case BOOLEAN:
1306 case DOUBLE:
1307 case INT:
1308 case LONG: {
1309 if (valueList.size() != 1) {
1310 errPw.println(tag + "Expected 1 value for type " + type
1311 + ". Found: " + valueList.size());
1312 return null;
1313 }
1314 break;
1315 }
1316 case STRING: {
1317 if (valueList.size() > 1) {
1318 errPw.println(tag + "Expected 0 or 1 values for type " + type
1319 + ". Found: " + valueList.size());
1320 return null;
1321 }
1322 break;
1323 }
1324 }
1325
1326 // Parse the value according to type and add it to the Bundle.
1327 switch (type) {
1328 case BOOLEAN: {
1329 if ("true".equalsIgnoreCase(valueList.get(0))) {
1330 bundle.putBoolean(key, true);
1331 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1332 bundle.putBoolean(key, false);
1333 } else {
1334 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1335 return null;
1336 }
1337 break;
1338 }
1339 case DOUBLE: {
1340 try {
1341 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1342 } catch (NumberFormatException nfe) {
1343 // Not a valid double
1344 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1345 return null;
1346 }
1347 break;
1348 }
1349 case DOUBLE_ARRAY: {
1350 double[] valueDoubleArray = null;
1351 if (valueList.size() > 0) {
1352 valueDoubleArray = new double[valueList.size()];
1353 for (int i = 0; i < valueList.size(); i++) {
1354 try {
1355 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1356 } catch (NumberFormatException nfe) {
1357 // Not a valid double
1358 errPw.println(
1359 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1360 return null;
1361 }
1362 }
1363 }
1364 bundle.putDoubleArray(key, valueDoubleArray);
1365 break;
1366 }
1367 case INT: {
1368 try {
1369 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1370 } catch (NumberFormatException nfe) {
1371 // Not a valid integer
1372 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1373 return null;
1374 }
1375 break;
1376 }
1377 case INT_ARRAY: {
1378 int[] valueIntArray = null;
1379 if (valueList.size() > 0) {
1380 valueIntArray = new int[valueList.size()];
1381 for (int i = 0; i < valueList.size(); i++) {
1382 try {
1383 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1384 } catch (NumberFormatException nfe) {
1385 // Not a valid integer
1386 errPw.println(tag
1387 + "Unable to parse " + valueList.get(i) + " as an integer.");
1388 return null;
1389 }
1390 }
1391 }
1392 bundle.putIntArray(key, valueIntArray);
1393 break;
1394 }
1395 case LONG: {
1396 try {
1397 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1398 } catch (NumberFormatException nfe) {
1399 // Not a valid long
1400 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1401 return null;
1402 }
1403 break;
1404 }
1405 case LONG_ARRAY: {
1406 long[] valueLongArray = null;
1407 if (valueList.size() > 0) {
1408 valueLongArray = new long[valueList.size()];
1409 for (int i = 0; i < valueList.size(); i++) {
1410 try {
1411 valueLongArray[i] = Long.parseLong(valueList.get(i));
1412 } catch (NumberFormatException nfe) {
1413 // Not a valid long
1414 errPw.println(
1415 tag + "Unable to parse " + valueList.get(i) + " as a long");
1416 return null;
1417 }
1418 }
1419 }
1420 bundle.putLongArray(key, valueLongArray);
1421 break;
1422 }
1423 case STRING: {
1424 String value = null;
1425 if (valueList.size() > 0) {
1426 value = valueList.get(0);
1427 }
1428 bundle.putString(key, value);
1429 break;
1430 }
1431 case STRING_ARRAY: {
1432 String[] valueStringArray = null;
1433 if (valueList.size() > 0) {
1434 valueStringArray = new String[valueList.size()];
1435 valueList.toArray(valueStringArray);
1436 }
1437 bundle.putStringArray(key, valueStringArray);
1438 break;
1439 }
1440 }
1441 return bundle;
1442 }
Shuo Qian489d9282020-07-09 11:30:03 -07001443
1444 private int handleEndBlockSuppressionCommand() {
1445 if (!checkShellUid()) {
1446 return -1;
1447 }
1448
1449 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1450 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1451 }
1452 return 0;
1453 }
Hui Wang641e81c2020-10-12 12:14:23 -07001454
Michele Berionne54af4632020-12-28 20:23:16 +00001455 private int handleRestartModemCommand() {
1456 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1457 // non user build.
1458 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1459 getErrPrintWriter().println("RestartModem: Permission denied.");
1460 return -1;
1461 }
1462
1463 boolean result = TelephonyManager.getDefault().rebootRadio();
1464 getOutPrintWriter().println(result);
1465
1466 return result ? 0 : -1;
1467 }
1468
Hui Wang641e81c2020-10-12 12:14:23 -07001469 private int handleGbaCommand() {
1470 String arg = getNextArg();
1471 if (arg == null) {
1472 onHelpGba();
1473 return 0;
1474 }
1475
1476 switch (arg) {
1477 case GBA_SET_SERVICE: {
1478 return handleGbaSetServiceCommand();
1479 }
1480 case GBA_GET_SERVICE: {
1481 return handleGbaGetServiceCommand();
1482 }
1483 case GBA_SET_RELEASE_TIME: {
1484 return handleGbaSetReleaseCommand();
1485 }
1486 case GBA_GET_RELEASE_TIME: {
1487 return handleGbaGetReleaseCommand();
1488 }
1489 }
1490
1491 return -1;
1492 }
1493
1494 private int getSubId(String cmd) {
1495 int slotId = getDefaultSlot();
1496 String opt = getNextOption();
1497 if (opt != null && opt.equals("-s")) {
1498 try {
1499 slotId = Integer.parseInt(getNextArgRequired());
1500 } catch (NumberFormatException e) {
1501 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1502 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1503 }
1504 }
1505 int[] subIds = SubscriptionManager.getSubId(slotId);
1506 return subIds[0];
1507 }
1508
1509 private int handleGbaSetServiceCommand() {
1510 int subId = getSubId("gba set-service");
1511 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1512 return -1;
1513 }
1514
1515 String packageName = getNextArg();
1516 try {
1517 if (packageName == null) {
1518 packageName = "";
1519 }
1520 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1521 if (VDBG) {
1522 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1523 + packageName + ", result=" + result);
1524 }
1525 getOutPrintWriter().println(result);
1526 } catch (RemoteException e) {
1527 Log.w(LOG_TAG, "gba set-service " + subId + " "
1528 + packageName + ", error" + e.getMessage());
1529 getErrPrintWriter().println("Exception: " + e.getMessage());
1530 return -1;
1531 }
1532 return 0;
1533 }
1534
1535 private int handleGbaGetServiceCommand() {
1536 String result;
1537
1538 int subId = getSubId("gba get-service");
1539 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1540 return -1;
1541 }
1542
1543 try {
1544 result = mInterface.getBoundGbaService(subId);
1545 } catch (RemoteException e) {
1546 return -1;
1547 }
1548 if (VDBG) {
1549 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1550 }
1551 getOutPrintWriter().println(result);
1552 return 0;
1553 }
1554
1555 private int handleGbaSetReleaseCommand() {
1556 //the release time value could be -1
1557 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1558 : SubscriptionManager.getDefaultSubscriptionId();
1559 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1560 return -1;
1561 }
1562
1563 String intervalStr = getNextArg();
1564 if (intervalStr == null) {
1565 return -1;
1566 }
1567
1568 try {
1569 int interval = Integer.parseInt(intervalStr);
1570 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1571 if (VDBG) {
1572 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1573 + intervalStr + ", result=" + result);
1574 }
1575 getOutPrintWriter().println(result);
1576 } catch (NumberFormatException | RemoteException e) {
1577 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1578 + intervalStr + ", error" + e.getMessage());
1579 getErrPrintWriter().println("Exception: " + e.getMessage());
1580 return -1;
1581 }
1582 return 0;
1583 }
1584
1585 private int handleGbaGetReleaseCommand() {
1586 int subId = getSubId("gba get-release");
1587 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1588 return -1;
1589 }
1590
1591 int result = 0;
1592 try {
1593 result = mInterface.getGbaReleaseTime(subId);
1594 } catch (RemoteException e) {
1595 return -1;
1596 }
1597 if (VDBG) {
1598 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1599 }
1600 getOutPrintWriter().println(result);
1601 return 0;
1602 }
Hui Wang761a6682020-10-31 05:12:53 +00001603
1604 private int handleSingleRegistrationConfigCommand() {
1605 String arg = getNextArg();
1606 if (arg == null) {
1607 onHelpSrc();
1608 return 0;
1609 }
1610
1611 switch (arg) {
1612 case SRC_SET_DEVICE_ENABLED: {
1613 return handleSrcSetDeviceEnabledCommand();
1614 }
1615 case SRC_GET_DEVICE_ENABLED: {
1616 return handleSrcGetDeviceEnabledCommand();
1617 }
1618 case SRC_SET_CARRIER_ENABLED: {
1619 return handleSrcSetCarrierEnabledCommand();
1620 }
1621 case SRC_GET_CARRIER_ENABLED: {
1622 return handleSrcGetCarrierEnabledCommand();
1623 }
1624 }
1625
1626 return -1;
1627 }
1628
James.cf Linbcdf8b32021-01-14 16:44:13 +08001629 private int handleRcsUceCommand() {
1630 String arg = getNextArg();
1631 if (arg == null) {
1632 Log.w(LOG_TAG, "cannot get uce parameter");
1633 return -1;
1634 }
1635
1636 switch (arg) {
1637 case UCE_REMOVE_EAB_CONTACT:
1638 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001639 case UCE_GET_EAB_CONTACT:
1640 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001641 case UCE_GET_DEVICE_ENABLED:
1642 return handleUceGetDeviceEnabledCommand();
1643 case UCE_SET_DEVICE_ENABLED:
1644 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001645 }
1646 return -1;
1647 }
1648
1649 private int handleRemovingEabContactCommand() {
1650 int subId = getSubId("uce remove-eab-contact");
1651 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1652 return -1;
1653 }
1654
1655 String phoneNumber = getNextArgRequired();
1656 if (TextUtils.isEmpty(phoneNumber)) {
1657 return -1;
1658 }
1659 int result = 0;
1660 try {
1661 result = mInterface.removeContactFromEab(subId, phoneNumber);
1662 } catch (RemoteException e) {
1663 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1664 getErrPrintWriter().println("Exception: " + e.getMessage());
1665 return -1;
1666 }
1667
1668 if (VDBG) {
1669 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1670 }
1671 return result;
1672 }
1673
calvinpane4a8a1d2021-01-25 13:51:18 +08001674 private int handleGettingEabContactCommand() {
1675 String phoneNumber = getNextArgRequired();
1676 if (TextUtils.isEmpty(phoneNumber)) {
1677 return -1;
1678 }
1679 String result = "";
1680 try {
1681 result = mInterface.getContactFromEab(phoneNumber);
1682
1683 } catch (RemoteException e) {
1684 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1685 getErrPrintWriter().println("Exception: " + e.getMessage());
1686 return -1;
1687 }
1688
1689 if (VDBG) {
1690 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1691 }
James.cf Lin4b784aa2021-01-31 03:25:15 +08001692 return 0;
1693 }
1694
1695 private int handleUceGetDeviceEnabledCommand() {
1696 boolean result = false;
1697 try {
1698 result = mInterface.getDeviceUceEnabled();
1699 } catch (RemoteException e) {
1700 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1701 return -1;
1702 }
1703 if (VDBG) {
1704 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1705 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001706 getOutPrintWriter().println(result);
1707 return 0;
1708 }
1709
James.cf Lin4b784aa2021-01-31 03:25:15 +08001710 private int handleUceSetDeviceEnabledCommand() {
1711 String enabledStr = getNextArg();
1712 if (TextUtils.isEmpty(enabledStr)) {
1713 return -1;
1714 }
1715
1716 try {
1717 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1718 mInterface.setDeviceUceEnabled(isEnabled);
1719 if (VDBG) {
1720 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1721 }
1722 } catch (NumberFormatException | RemoteException e) {
1723 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1724 getErrPrintWriter().println("Exception: " + e.getMessage());
1725 return -1;
1726 }
1727 return 0;
1728 }
1729
Hui Wang761a6682020-10-31 05:12:53 +00001730 private int handleSrcSetDeviceEnabledCommand() {
1731 String enabledStr = getNextArg();
1732 if (enabledStr == null) {
1733 return -1;
1734 }
1735
1736 try {
1737 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1738 if (VDBG) {
1739 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1740 }
1741 getOutPrintWriter().println("Done");
1742 } catch (NumberFormatException | RemoteException e) {
1743 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1744 getErrPrintWriter().println("Exception: " + e.getMessage());
1745 return -1;
1746 }
1747 return 0;
1748 }
1749
1750 private int handleSrcGetDeviceEnabledCommand() {
1751 boolean result = false;
1752 try {
1753 result = mInterface.getDeviceSingleRegistrationEnabled();
1754 } catch (RemoteException e) {
1755 return -1;
1756 }
1757 if (VDBG) {
1758 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1759 }
1760 getOutPrintWriter().println(result);
1761 return 0;
1762 }
1763
1764 private int handleSrcSetCarrierEnabledCommand() {
1765 //the release time value could be -1
1766 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1767 : SubscriptionManager.getDefaultSubscriptionId();
1768 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1769 return -1;
1770 }
1771
1772 String enabledStr = getNextArg();
1773 if (enabledStr == null) {
1774 return -1;
1775 }
1776
1777 try {
1778 boolean result =
1779 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1780 if (VDBG) {
1781 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1782 + enabledStr + ", result=" + result);
1783 }
1784 getOutPrintWriter().println(result);
1785 } catch (NumberFormatException | RemoteException e) {
1786 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1787 + enabledStr + ", error" + e.getMessage());
1788 getErrPrintWriter().println("Exception: " + e.getMessage());
1789 return -1;
1790 }
1791 return 0;
1792 }
1793
1794 private int handleSrcGetCarrierEnabledCommand() {
1795 int subId = getSubId("src get-carrier-enabled");
1796 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1797 return -1;
1798 }
1799
1800 boolean result = false;
1801 try {
1802 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1803 } catch (RemoteException e) {
1804 return -1;
1805 }
1806 if (VDBG) {
1807 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1808 }
1809 getOutPrintWriter().println(result);
1810 return 0;
1811 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001812
1813 private void onHelpCallComposer() {
1814 PrintWriter pw = getOutPrintWriter();
1815 pw.println("Call composer commands");
1816 pw.println(" callcomposer test-mode enable|disable|query");
1817 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1818 pw.println(" upload/download from carrier servers is disabled, and operations are");
1819 pw.println(" performed using emulated local files instead.");
1820 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1821 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1822 pw.println(" the provided UUID. This triggers storage to the call log.");
1823 }
1824
1825 private int handleCallComposerCommand() {
1826 String arg = getNextArg();
1827 if (arg == null) {
1828 onHelpCallComposer();
1829 return 0;
1830 }
1831
1832 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1833 "MODIFY_PHONE_STATE required for call composer shell cmds");
1834 switch (arg) {
1835 case CALL_COMPOSER_TEST_MODE: {
1836 String enabledStr = getNextArg();
1837 if (ENABLE.equals(enabledStr)) {
1838 CallComposerPictureManager.sTestMode = true;
1839 } else if (DISABLE.equals(enabledStr)) {
1840 CallComposerPictureManager.sTestMode = false;
1841 } else if (QUERY.equals(enabledStr)) {
1842 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1843 } else {
1844 onHelpCallComposer();
1845 return 1;
1846 }
1847 break;
1848 }
1849 case CALL_COMPOSER_SIMULATE_CALL: {
1850 int subscriptionId = Integer.valueOf(getNextArg());
1851 String uuidString = getNextArg();
1852 UUID uuid = UUID.fromString(uuidString);
1853 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1854 Binder.withCleanCallingIdentity(() -> {
1855 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1856 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1857 });
1858 try {
1859 Uri uri = storageUriFuture.get();
1860 getOutPrintWriter().println(String.valueOf(uri));
1861 } catch (Exception e) {
1862 throw new RuntimeException(e);
1863 }
1864 break;
1865 }
1866 }
1867
1868 return 0;
1869 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001870}