blob: 5edd51cbf8432c97c0d0eaecdef467c66ab4d726 [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;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070037import android.util.Log;
38
39import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080040import com.android.internal.telephony.Phone;
41import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080042import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080043import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080044import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080045import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080046import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070047
48import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080049import java.util.ArrayList;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010050import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080051import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010052import java.util.Map;
53import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080054import java.util.UUID;
55import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070056
57/**
58 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
59 * permission checks have been done before onCommand was called. Make sure any commands processed
60 * here also contain the appropriate permissions checks.
61 */
62
Hall Liua1548bd2019-12-24 14:14:12 -080063public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064
65 private static final String LOG_TAG = "TelephonyShellCommand";
66 // Don't commit with this true.
67 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070068 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070069
Hall Liuaa4211e2021-01-20 15:43:39 -080070 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070071 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080072 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080073 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070074 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000075 private static final String RESTART_MODEM = "restart-modem";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010076 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080077 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080078 private static final String ENABLE = "enable";
79 private static final String DISABLE = "disable";
80 private static final String QUERY = "query";
81
82 private static final String CALL_COMPOSER_TEST_MODE = "test_mode";
83 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liud892bec2018-11-30 14:51:45 -080084
Brad Ebinger999d3302020-11-25 14:31:39 -080085 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
86 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
87 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070088 // Used to disable or enable processing of conference event package data from the network.
89 // This is handy for testing scenarios where CEP data does not exist on a network which does
90 // support CEP data.
91 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070092
Hall Liud892bec2018-11-30 14:51:45 -080093 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080094 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080095
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010096 private static final String CC_GET_VALUE = "get-value";
97 private static final String CC_SET_VALUE = "set-value";
98 private static final String CC_CLEAR_VALUES = "clear-values";
99
Hui Wang641e81c2020-10-12 12:14:23 -0700100 private static final String GBA_SUBCOMMAND = "gba";
101 private static final String GBA_SET_SERVICE = "set-service";
102 private static final String GBA_GET_SERVICE = "get-service";
103 private static final String GBA_SET_RELEASE_TIME = "set-release";
104 private static final String GBA_GET_RELEASE_TIME = "get-release";
105
Hui Wang761a6682020-10-31 05:12:53 +0000106 private static final String SINGLE_REGISTATION_CONFIG = "src";
107 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
108 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
109 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
110 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
111
Tyler Gunn92479152021-01-20 16:30:10 -0800112 private static final String D2D_SUBCOMMAND = "d2d";
113 private static final String D2D_SEND = "send";
114
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700115 // Take advantage of existing methods that already contain permissions checks when possible.
116 private final ITelephony mInterface;
117
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100118 private SubscriptionManager mSubscriptionManager;
119 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700120 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100121
122 private enum CcType {
123 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
124 STRING_ARRAY, UNKNOWN
125 }
126
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100127 private class CcOptionParseResult {
128 public int mSubId;
129 public boolean mPersistent;
130 }
131
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100132 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
133 // keys by looking at the end of the string which usually tells the type.
134 // For instance: "xxxx_string", "xxxx_string_array", etc.
135 // The carrier config keys in this map does not follow this convention. It is therefore not
136 // possible to infer the type for these keys by looking at the string.
137 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
138 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
139 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
140 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
141 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
142 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
143 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
149 CcType.STRING);
150 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
151 CcType.STRING_ARRAY);
152 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
153 CcType.STRING_ARRAY);
154 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
155 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
156 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
157 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
158 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
159 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
160 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
161 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
162 }
163 };
164
165 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700166 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100167 mCarrierConfigManager =
168 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
169 mSubscriptionManager = (SubscriptionManager)
170 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700171 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700172 }
173
174 @Override
175 public int onCommand(String cmd) {
176 if (cmd == null) {
177 return handleDefaultCommands(null);
178 }
179
180 switch (cmd) {
181 case IMS_SUBCOMMAND: {
182 return handleImsCommand();
183 }
Hall Liud892bec2018-11-30 14:51:45 -0800184 case NUMBER_VERIFICATION_SUBCOMMAND:
185 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800186 case EMERGENCY_NUMBER_TEST_MODE:
187 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100188 case CARRIER_CONFIG_SUBCOMMAND: {
189 return handleCcCommand();
190 }
Shuo Qianf5125122019-12-16 17:03:07 -0800191 case DATA_TEST_MODE:
192 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700193 case END_BLOCK_SUPPRESSION:
194 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700195 case GBA_SUBCOMMAND:
196 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800197 case D2D_SUBCOMMAND:
198 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000199 case SINGLE_REGISTATION_CONFIG:
200 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000201 case RESTART_MODEM:
202 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800203 case CALL_COMPOSER_SUBCOMMAND:
204 return handleCallComposerCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700205 default: {
206 return handleDefaultCommands(cmd);
207 }
208 }
209 }
210
211 @Override
212 public void onHelp() {
213 PrintWriter pw = getOutPrintWriter();
214 pw.println("Telephony Commands:");
215 pw.println(" help");
216 pw.println(" Print this help text.");
217 pw.println(" ims");
218 pw.println(" IMS Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800219 pw.println(" emergency-number-test-mode");
220 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700221 pw.println(" end-block-suppression");
222 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800223 pw.println(" data");
224 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100225 pw.println(" cc");
226 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700227 pw.println(" gba");
228 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000229 pw.println(" src");
230 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000231 pw.println(" restart-modem");
232 pw.println(" Restart modem command.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700233 onHelpIms();
sqian9d4df8b2019-01-15 18:32:07 -0800234 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700235 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800236 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100237 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700238 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000239 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800240 onHelpD2D();
241 }
242
243 private void onHelpD2D() {
244 PrintWriter pw = getOutPrintWriter();
245 pw.println("D2D Comms Commands:");
246 pw.println(" d2d send TYPE VALUE");
247 pw.println(" Sends a D2D message of specified type and value.");
248 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
249 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
250 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
251 MESSAGE_CALL_AUDIO_CODEC));
252 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
253 + Communicator.messageToString(
254 MESSAGE_DEVICE_BATTERY_STATE));
255 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
256 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700257 }
258
259 private void onHelpIms() {
260 PrintWriter pw = getOutPrintWriter();
261 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800262 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700263 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
264 pw.println(" ImsService. Options are:");
265 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
266 pw.println(" is specified, it will choose the default voice SIM slot.");
267 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
268 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800269 pw.println(" -f: Set the feature that this override if for, if no option is");
270 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700271 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
272 pw.println(" Gets the package name of the currently defined ImsService.");
273 pw.println(" Options are:");
274 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
275 pw.println(" is specified, it will choose the default voice SIM slot.");
276 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000277 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800278 pw.println(" -f: The feature type that the query will be requested for. If none is");
279 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800280 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
281 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
282 pw.println(" configuration overrides. Options are:");
283 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
284 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700285 pw.println(" ims enable [-s SLOT_ID]");
286 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
287 pw.println(" if none is specified.");
288 pw.println(" ims disable [-s SLOT_ID]");
289 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
290 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700291 pw.println(" ims conference-event-package [enable/disable]");
292 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700293 }
294
Hall Liud892bec2018-11-30 14:51:45 -0800295 private void onHelpNumberVerification() {
296 PrintWriter pw = getOutPrintWriter();
297 pw.println("Number verification commands");
298 pw.println(" numverify override-package PACKAGE_NAME;");
299 pw.println(" Set the authorized package for number verification.");
300 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800301 pw.println(" numverify fake-call NUMBER;");
302 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
303 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800304 }
305
Shuo Qianf5125122019-12-16 17:03:07 -0800306 private void onHelpDataTestMode() {
307 PrintWriter pw = getOutPrintWriter();
308 pw.println("Mobile Data Test Mode Commands:");
309 pw.println(" data enable: enable mobile data connectivity");
310 pw.println(" data disable: disable mobile data connectivity");
311 }
312
sqian9d4df8b2019-01-15 18:32:07 -0800313 private void onHelpEmergencyNumber() {
314 PrintWriter pw = getOutPrintWriter();
315 pw.println("Emergency Number Test Mode Commands:");
316 pw.println(" emergency-number-test-mode ");
317 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
318 + " the test mode");
319 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700320 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800321 pw.println(" -c: clear the emergency number list in the test mode.");
322 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700323 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800324 pw.println(" -p: get the full emergency number list in the test mode.");
325 }
326
Shuo Qian489d9282020-07-09 11:30:03 -0700327 private void onHelpEndBlockSupperssion() {
328 PrintWriter pw = getOutPrintWriter();
329 pw.println("End Block Suppression command:");
330 pw.println(" end-block-suppression: disable suppressing blocking by contact");
331 pw.println(" with emergency services.");
332 }
333
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100334 private void onHelpCc() {
335 PrintWriter pw = getOutPrintWriter();
336 pw.println("Carrier Config Commands:");
337 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
338 pw.println(" Print carrier config values.");
339 pw.println(" Options are:");
340 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
341 pw.println(" is specified, it will choose the default voice SIM slot.");
342 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
343 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100344 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100345 pw.println(" Set carrier config KEY to NEW_VALUE.");
346 pw.println(" Options are:");
347 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
348 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100349 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100350 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
351 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
352 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
353 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
354 pw.println(" cc clear-values [-s SLOT_ID]");
355 pw.println(" Clear all carrier override values that has previously been set");
356 pw.println(" with set-value");
357 pw.println(" Options are:");
358 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
359 pw.println(" is specified, it will choose the default voice SIM slot.");
360 }
361
Hui Wang641e81c2020-10-12 12:14:23 -0700362 private void onHelpGba() {
363 PrintWriter pw = getOutPrintWriter();
364 pw.println("Gba Commands:");
365 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
366 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
367 pw.println(" Options are:");
368 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
369 pw.println(" is specified, it will choose the default voice SIM slot.");
370 pw.println(" gba get-service [-s SLOT_ID]");
371 pw.println(" Gets the package name of the currently defined GbaService.");
372 pw.println(" Options are:");
373 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
374 pw.println(" is specified, it will choose the default voice SIM slot.");
375 pw.println(" gba set-release [-s SLOT_ID] n");
376 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
377 pw.println(" Do not release/unbind if n is -1.");
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(" gba get-release [-s SLOT_ID]");
382 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
383 pw.println(" Options are:");
384 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
385 pw.println(" is specified, it will choose the default voice SIM slot.");
386 }
387
Hui Wang761a6682020-10-31 05:12:53 +0000388 private void onHelpSrc() {
389 PrintWriter pw = getOutPrintWriter();
390 pw.println("RCS VoLTE Single Registration Config Commands:");
391 pw.println(" src set-device-enabled true|false|null");
392 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
393 pw.println(" The value could be true, false, or null(undefined).");
394 pw.println(" src get-device-enabled");
395 pw.println(" Gets the device config for RCS VoLTE single registration.");
396 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
397 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
398 pw.println(" The value could be true, false, or null(undefined).");
399 pw.println(" Options are:");
400 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
401 pw.println(" is specified, it will choose the default voice SIM slot.");
402 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
403 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
404 pw.println(" Options are:");
405 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
406 pw.println(" is specified, it will choose the default voice SIM slot.");
407 }
408
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700409 private int handleImsCommand() {
410 String arg = getNextArg();
411 if (arg == null) {
412 onHelpIms();
413 return 0;
414 }
415
416 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800417 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700418 return handleImsSetServiceCommand();
419 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800420 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700421 return handleImsGetServiceCommand();
422 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800423 case IMS_CLEAR_SERVICE_OVERRIDE: {
424 return handleImsClearCarrierServiceCommand();
425 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800426 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700427 return handleEnableIms();
428 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800429 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700430 return handleDisableIms();
431 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700432 case IMS_CEP: {
433 return handleCepChange();
434 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700435 }
436
437 return -1;
438 }
439
Shuo Qianf5125122019-12-16 17:03:07 -0800440 private int handleDataTestModeCommand() {
441 PrintWriter errPw = getErrPrintWriter();
442 String arg = getNextArgRequired();
443 if (arg == null) {
444 onHelpDataTestMode();
445 return 0;
446 }
447 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800448 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800449 try {
450 mInterface.enableDataConnectivity();
451 } catch (RemoteException ex) {
452 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
453 errPw.println("Exception: " + ex.getMessage());
454 return -1;
455 }
456 break;
457 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800458 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800459 try {
460 mInterface.disableDataConnectivity();
461 } catch (RemoteException ex) {
462 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
463 errPw.println("Exception: " + ex.getMessage());
464 return -1;
465 }
466 break;
467 }
468 default:
469 onHelpDataTestMode();
470 break;
471 }
472 return 0;
473 }
474
sqian9d4df8b2019-01-15 18:32:07 -0800475 private int handleEmergencyNumberTestModeCommand() {
476 PrintWriter errPw = getErrPrintWriter();
477 String opt = getNextOption();
478 if (opt == null) {
479 onHelpEmergencyNumber();
480 return 0;
481 }
482
483 switch (opt) {
484 case "-a": {
485 String emergencyNumberCmd = getNextArgRequired();
486 if (emergencyNumberCmd == null
487 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700488 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800489 + " to be specified after -a in the command ");
490 return -1;
491 }
492 try {
493 mInterface.updateEmergencyNumberListTestMode(
494 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
495 new EmergencyNumber(emergencyNumberCmd, "", "",
496 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
497 new ArrayList<String>(),
498 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
499 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
500 } catch (RemoteException ex) {
501 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
502 + ", error " + ex.getMessage());
503 errPw.println("Exception: " + ex.getMessage());
504 return -1;
505 }
506 break;
507 }
508 case "-c": {
509 try {
510 mInterface.updateEmergencyNumberListTestMode(
511 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
512 } catch (RemoteException ex) {
513 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
514 errPw.println("Exception: " + ex.getMessage());
515 return -1;
516 }
517 break;
518 }
519 case "-r": {
520 String emergencyNumberCmd = getNextArgRequired();
521 if (emergencyNumberCmd == null
522 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700523 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800524 + " to be specified after -r in the command ");
525 return -1;
526 }
527 try {
528 mInterface.updateEmergencyNumberListTestMode(
529 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
530 new EmergencyNumber(emergencyNumberCmd, "", "",
531 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
532 new ArrayList<String>(),
533 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
534 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
535 } catch (RemoteException ex) {
536 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
537 + ", error " + ex.getMessage());
538 errPw.println("Exception: " + ex.getMessage());
539 return -1;
540 }
541 break;
542 }
543 case "-p": {
544 try {
545 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
546 } catch (RemoteException ex) {
547 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
548 errPw.println("Exception: " + ex.getMessage());
549 return -1;
550 }
551 break;
552 }
553 default:
554 onHelpEmergencyNumber();
555 break;
556 }
557 return 0;
558 }
559
Hall Liud892bec2018-11-30 14:51:45 -0800560 private int handleNumberVerificationCommand() {
561 String arg = getNextArg();
562 if (arg == null) {
563 onHelpNumberVerification();
564 return 0;
565 }
566
Hall Liuca5af3a2018-12-04 16:58:23 -0800567 if (!checkShellUid()) {
568 return -1;
569 }
570
Hall Liud892bec2018-11-30 14:51:45 -0800571 switch (arg) {
572 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800573 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
574 return 0;
575 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800576 case NUMBER_VERIFICATION_FAKE_CALL: {
577 boolean val = NumberVerificationManager.getInstance()
578 .checkIncomingCall(getNextArg());
579 getOutPrintWriter().println(val ? "1" : "0");
580 return 0;
581 }
Hall Liud892bec2018-11-30 14:51:45 -0800582 }
583
584 return -1;
585 }
586
Tyler Gunn92479152021-01-20 16:30:10 -0800587 private int handleD2dCommand() {
588 String arg = getNextArg();
589 if (arg == null) {
590 onHelpD2D();
591 return 0;
592 }
593
594 switch (arg) {
595 case D2D_SEND: {
596 return handleD2dSendCommand();
597 }
598 }
599
600 return -1;
601 }
602
603 private int handleD2dSendCommand() {
604 PrintWriter errPw = getErrPrintWriter();
605 String opt;
606 int messageType = -1;
607 int messageValue = -1;
608
609
610 String arg = getNextArg();
611 if (arg == null) {
612 onHelpD2D();
613 return 0;
614 }
615 try {
616 messageType = Integer.parseInt(arg);
617 } catch (NumberFormatException e) {
618 errPw.println("message type must be a valid integer");
619 return -1;
620 }
621
622 arg = getNextArg();
623 if (arg == null) {
624 onHelpD2D();
625 return 0;
626 }
627 try {
628 messageValue = Integer.parseInt(arg);
629 } catch (NumberFormatException e) {
630 errPw.println("message value must be a valid integer");
631 return -1;
632 }
633
634 try {
635 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
636 } catch (RemoteException e) {
637 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
638 errPw.println("Exception: " + e.getMessage());
639 return -1;
640 }
641
642 return 0;
643 }
644
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700645 // ims set-ims-service
646 private int handleImsSetServiceCommand() {
647 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700648 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700649 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800650 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700651
652 String opt;
653 while ((opt = getNextOption()) != null) {
654 switch (opt) {
655 case "-s": {
656 try {
657 slotId = Integer.parseInt(getNextArgRequired());
658 } catch (NumberFormatException e) {
659 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
660 return -1;
661 }
662 break;
663 }
664 case "-c": {
665 isCarrierService = true;
666 break;
667 }
668 case "-d": {
669 isCarrierService = false;
670 break;
671 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800672 case "-f": {
673 String featureString = getNextArgRequired();
674 String[] features = featureString.split(",");
675 for (int i = 0; i < features.length; i++) {
676 try {
677 Integer result = Integer.parseInt(features[i]);
678 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
679 || result >= ImsFeature.FEATURE_MAX) {
680 errPw.println("ims set-ims-service -f " + result
681 + " is an invalid feature.");
682 return -1;
683 }
684 featuresList.add(result);
685 } catch (NumberFormatException e) {
686 errPw.println("ims set-ims-service -f tried to parse " + features[i]
687 + " as an integer.");
688 return -1;
689 }
690 }
691 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700692 }
693 }
694 // Mandatory param, either -c or -d
695 if (isCarrierService == null) {
696 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
697 return -1;
698 }
699
700 String packageName = getNextArg();
701
702 try {
703 if (packageName == null) {
704 packageName = "";
705 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800706 int[] featureArray = new int[featuresList.size()];
707 for (int i = 0; i < featuresList.size(); i++) {
708 featureArray[i] = featuresList.get(i);
709 }
710 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
711 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700712 if (VDBG) {
713 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800714 + (isCarrierService ? "-c " : "-d ")
715 + "-f " + featuresList + " "
716 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700717 }
718 getOutPrintWriter().println(result);
719 } catch (RemoteException e) {
720 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800721 + (isCarrierService ? "-c " : "-d ")
722 + "-f " + featuresList + " "
723 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700724 errPw.println("Exception: " + e.getMessage());
725 return -1;
726 }
727 return 0;
728 }
729
Brad Ebinger999d3302020-11-25 14:31:39 -0800730 // ims clear-ims-service-override
731 private int handleImsClearCarrierServiceCommand() {
732 PrintWriter errPw = getErrPrintWriter();
733 int slotId = getDefaultSlot();
734
735 String opt;
736 while ((opt = getNextOption()) != null) {
737 switch (opt) {
738 case "-s": {
739 try {
740 slotId = Integer.parseInt(getNextArgRequired());
741 } catch (NumberFormatException e) {
742 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
743 return -1;
744 }
745 break;
746 }
747 }
748 }
749
750 try {
751 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
752 if (VDBG) {
753 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
754 + ", result=" + result);
755 }
756 getOutPrintWriter().println(result);
757 } catch (RemoteException e) {
758 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
759 + ", error" + e.getMessage());
760 errPw.println("Exception: " + e.getMessage());
761 return -1;
762 }
763 return 0;
764 }
765
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700766 // ims get-ims-service
767 private int handleImsGetServiceCommand() {
768 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700769 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700770 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800771 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700772
773 String opt;
774 while ((opt = getNextOption()) != null) {
775 switch (opt) {
776 case "-s": {
777 try {
778 slotId = Integer.parseInt(getNextArgRequired());
779 } catch (NumberFormatException e) {
780 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
781 return -1;
782 }
783 break;
784 }
785 case "-c": {
786 isCarrierService = true;
787 break;
788 }
789 case "-d": {
790 isCarrierService = false;
791 break;
792 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800793 case "-f": {
794 try {
795 featureType = Integer.parseInt(getNextArg());
796 } catch (NumberFormatException e) {
797 errPw.println("ims get-ims-service -f requires valid integer as feature.");
798 return -1;
799 }
800 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
801 || featureType >= ImsFeature.FEATURE_MAX) {
802 errPw.println("ims get-ims-service -f invalid feature.");
803 return -1;
804 }
805 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700806 }
807 }
808 // Mandatory param, either -c or -d
809 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800810 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700811 return -1;
812 }
813
814 String result;
815 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800816 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700817 } catch (RemoteException e) {
818 return -1;
819 }
820 if (VDBG) {
821 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800822 + (isCarrierService ? "-c " : "-d ")
823 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
824 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700825 }
826 getOutPrintWriter().println(result);
827 return 0;
828 }
829
830 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700831 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700832 String opt;
833 while ((opt = getNextOption()) != null) {
834 switch (opt) {
835 case "-s": {
836 try {
837 slotId = Integer.parseInt(getNextArgRequired());
838 } catch (NumberFormatException e) {
839 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
840 return -1;
841 }
842 break;
843 }
844 }
845 }
846 try {
847 mInterface.enableIms(slotId);
848 } catch (RemoteException e) {
849 return -1;
850 }
851 if (VDBG) {
852 Log.v(LOG_TAG, "ims enable -s " + slotId);
853 }
854 return 0;
855 }
856
857 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700858 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700859 String opt;
860 while ((opt = getNextOption()) != null) {
861 switch (opt) {
862 case "-s": {
863 try {
864 slotId = Integer.parseInt(getNextArgRequired());
865 } catch (NumberFormatException e) {
866 getErrPrintWriter().println(
867 "ims disable requires an integer as a SLOT_ID.");
868 return -1;
869 }
870 break;
871 }
872 }
873 }
874 try {
875 mInterface.disableIms(slotId);
876 } catch (RemoteException e) {
877 return -1;
878 }
879 if (VDBG) {
880 Log.v(LOG_TAG, "ims disable -s " + slotId);
881 }
882 return 0;
883 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700884
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700885 private int handleCepChange() {
886 Log.i(LOG_TAG, "handleCepChange");
887 String opt = getNextArg();
888 if (opt == null) {
889 return -1;
890 }
891 boolean isCepEnabled = opt.equals("enable");
892
893 try {
894 mInterface.setCepEnabled(isCepEnabled);
895 } catch (RemoteException e) {
896 return -1;
897 }
898 return 0;
899 }
900
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700901 private int getDefaultSlot() {
902 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
903 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
904 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
905 // If there is no default, default to slot 0.
906 slotId = DEFAULT_PHONE_ID;
907 }
908 return slotId;
909 }
sqian2fff4a32018-11-05 14:18:37 -0800910
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100911 // Parse options related to Carrier Config Commands.
912 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100913 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100914 CcOptionParseResult result = new CcOptionParseResult();
915 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
916 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100917
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100918 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100919 while ((opt = getNextOption()) != null) {
920 switch (opt) {
921 case "-s": {
922 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100923 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
924 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
925 errPw.println(tag + "No valid subscription found.");
926 return null;
927 }
928
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100929 } catch (IllegalArgumentException e) {
930 // Missing slot id
931 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100932 return null;
933 }
934 break;
935 }
936 case "-p": {
937 if (allowOptionPersistent) {
938 result.mPersistent = true;
939 } else {
940 errPw.println(tag + "Unexpected option " + opt);
941 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100942 }
943 break;
944 }
945 default: {
946 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100947 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100948 }
949 }
950 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100951 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100952 }
953
954 private int slotStringToSubId(String tag, String slotString) {
955 int slotId = -1;
956 try {
957 slotId = Integer.parseInt(slotString);
958 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800959 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
960 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
961 }
962
963 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100964 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
965 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
966 }
967
Qiong Liuf25799b2020-09-10 10:13:46 +0800968 Phone phone = PhoneFactory.getPhone(slotId);
969 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100970 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
971 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
972 }
Qiong Liuf25799b2020-09-10 10:13:46 +0800973 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100974 }
975
Hall Liud892bec2018-11-30 14:51:45 -0800976 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -0800977 // adb can run as root or as shell, depending on whether the device is rooted.
978 return Binder.getCallingUid() == Process.SHELL_UID
979 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -0800980 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100981
982 private int handleCcCommand() {
983 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
984 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -0800985 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100986 getErrPrintWriter().println("cc: Permission denied.");
987 return -1;
988 }
989
990 String arg = getNextArg();
991 if (arg == null) {
992 onHelpCc();
993 return 0;
994 }
995
996 switch (arg) {
997 case CC_GET_VALUE: {
998 return handleCcGetValue();
999 }
1000 case CC_SET_VALUE: {
1001 return handleCcSetValue();
1002 }
1003 case CC_CLEAR_VALUES: {
1004 return handleCcClearValues();
1005 }
1006 default: {
1007 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1008 }
1009 }
1010 return -1;
1011 }
1012
1013 // cc get-value
1014 private int handleCcGetValue() {
1015 PrintWriter errPw = getErrPrintWriter();
1016 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1017 String key = null;
1018
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001019 // Parse all options
1020 CcOptionParseResult options = parseCcOptions(tag, false);
1021 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001022 return -1;
1023 }
1024
1025 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001026 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001027 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001028 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001029 return -1;
1030 }
1031
1032 // Get the key.
1033 key = getNextArg();
1034 if (key != null) {
1035 // A key was provided. Verify if it is a valid key
1036 if (!bundle.containsKey(key)) {
1037 errPw.println(tag + key + " is not a valid key.");
1038 return -1;
1039 }
1040
1041 // Print the carrier config value for key.
1042 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1043 } else {
1044 // No key provided. Show all values.
1045 // Iterate over a sorted list of all carrier config keys and print them.
1046 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1047 for (String k : sortedSet) {
1048 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1049 }
1050 }
1051 return 0;
1052 }
1053
1054 // cc set-value
1055 private int handleCcSetValue() {
1056 PrintWriter errPw = getErrPrintWriter();
1057 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1058
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001059 // Parse all options
1060 CcOptionParseResult options = parseCcOptions(tag, true);
1061 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001062 return -1;
1063 }
1064
1065 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001066 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001067 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001068 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001069 return -1;
1070 }
1071
1072 // Get the key.
1073 String key = getNextArg();
1074 if (key == null || key.equals("")) {
1075 errPw.println(tag + "KEY is missing");
1076 return -1;
1077 }
1078
1079 // Verify if the key is valid
1080 if (!originalValues.containsKey(key)) {
1081 errPw.println(tag + key + " is not a valid key.");
1082 return -1;
1083 }
1084
1085 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1086 ArrayList<String> valueList = new ArrayList<String>();
1087 while (peekNextArg() != null) {
1088 valueList.add(getNextArg());
1089 }
1090
1091 // Find the type of the carrier config value
1092 CcType type = getType(tag, key, originalValues);
1093 if (type == CcType.UNKNOWN) {
1094 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1095 return -1;
1096 }
1097
1098 // Create an override bundle containing the key and value that should be overriden.
1099 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1100 if (overrideBundle == null) {
1101 return -1;
1102 }
1103
1104 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001105 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001106
1107 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001108 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001109 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001110 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001111 return -1;
1112 }
1113
1114 // Print the original and new value.
1115 String originalValueString = ccValueToString(key, type, originalValues);
1116 String newValueString = ccValueToString(key, type, newValues);
1117 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1118 getOutPrintWriter().println("New value: \n" + newValueString);
1119
1120 return 0;
1121 }
1122
1123 // cc clear-values
1124 private int handleCcClearValues() {
1125 PrintWriter errPw = getErrPrintWriter();
1126 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1127
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001128 // Parse all options
1129 CcOptionParseResult options = parseCcOptions(tag, false);
1130 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001131 return -1;
1132 }
1133
1134 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001135 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001136 getOutPrintWriter()
1137 .println("All previously set carrier config override values has been cleared");
1138 return 0;
1139 }
1140
1141 private CcType getType(String tag, String key, PersistableBundle bundle) {
1142 // Find the type by checking the type of the current value stored in the bundle.
1143 Object value = bundle.get(key);
1144
1145 if (CC_TYPE_MAP.containsKey(key)) {
1146 return CC_TYPE_MAP.get(key);
1147 } else if (value != null) {
1148 if (value instanceof Boolean) {
1149 return CcType.BOOLEAN;
1150 } else if (value instanceof Double) {
1151 return CcType.DOUBLE;
1152 } else if (value instanceof double[]) {
1153 return CcType.DOUBLE_ARRAY;
1154 } else if (value instanceof Integer) {
1155 return CcType.INT;
1156 } else if (value instanceof int[]) {
1157 return CcType.INT_ARRAY;
1158 } else if (value instanceof Long) {
1159 return CcType.LONG;
1160 } else if (value instanceof long[]) {
1161 return CcType.LONG_ARRAY;
1162 } else if (value instanceof String) {
1163 return CcType.STRING;
1164 } else if (value instanceof String[]) {
1165 return CcType.STRING_ARRAY;
1166 }
1167 } else {
1168 // Current value was null and can therefore not be used in order to find the type.
1169 // Check the name of the key to infer the type. This check is not needed for primitive
1170 // data types (boolean, double, int and long), since they can not be null.
1171 if (key.endsWith("double_array")) {
1172 return CcType.DOUBLE_ARRAY;
1173 }
1174 if (key.endsWith("int_array")) {
1175 return CcType.INT_ARRAY;
1176 }
1177 if (key.endsWith("long_array")) {
1178 return CcType.LONG_ARRAY;
1179 }
1180 if (key.endsWith("string")) {
1181 return CcType.STRING;
1182 }
1183 if (key.endsWith("string_array") || key.endsWith("strings")) {
1184 return CcType.STRING_ARRAY;
1185 }
1186 }
1187
1188 // Not possible to infer the type by looking at the current value or the key.
1189 PrintWriter errPw = getErrPrintWriter();
1190 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1191 return CcType.UNKNOWN;
1192 }
1193
1194 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1195 String result;
1196 StringBuilder valueString = new StringBuilder();
1197 String typeString = type.toString();
1198 Object value = bundle.get(key);
1199
1200 if (value == null) {
1201 valueString.append("null");
1202 } else {
1203 switch (type) {
1204 case DOUBLE_ARRAY: {
1205 // Format the string representation of the int array as value1 value2......
1206 double[] valueArray = (double[]) value;
1207 for (int i = 0; i < valueArray.length; i++) {
1208 if (i != 0) {
1209 valueString.append(" ");
1210 }
1211 valueString.append(valueArray[i]);
1212 }
1213 break;
1214 }
1215 case INT_ARRAY: {
1216 // Format the string representation of the int array as value1 value2......
1217 int[] valueArray = (int[]) value;
1218 for (int i = 0; i < valueArray.length; i++) {
1219 if (i != 0) {
1220 valueString.append(" ");
1221 }
1222 valueString.append(valueArray[i]);
1223 }
1224 break;
1225 }
1226 case LONG_ARRAY: {
1227 // Format the string representation of the int array as value1 value2......
1228 long[] valueArray = (long[]) value;
1229 for (int i = 0; i < valueArray.length; i++) {
1230 if (i != 0) {
1231 valueString.append(" ");
1232 }
1233 valueString.append(valueArray[i]);
1234 }
1235 break;
1236 }
1237 case STRING: {
1238 valueString.append("\"" + value.toString() + "\"");
1239 break;
1240 }
1241 case STRING_ARRAY: {
1242 // Format the string representation of the string array as "value1" "value2"....
1243 String[] valueArray = (String[]) value;
1244 for (int i = 0; i < valueArray.length; i++) {
1245 if (i != 0) {
1246 valueString.append(" ");
1247 }
1248 if (valueArray[i] != null) {
1249 valueString.append("\"" + valueArray[i] + "\"");
1250 } else {
1251 valueString.append("null");
1252 }
1253 }
1254 break;
1255 }
1256 default: {
1257 valueString.append(value.toString());
1258 }
1259 }
1260 }
1261 return String.format("%-70s %-15s %s", key, typeString, valueString);
1262 }
1263
1264 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1265 ArrayList<String> valueList) {
1266 PrintWriter errPw = getErrPrintWriter();
1267 PersistableBundle bundle = new PersistableBundle();
1268
1269 // First verify that a valid number of values has been provided for the type.
1270 switch (type) {
1271 case BOOLEAN:
1272 case DOUBLE:
1273 case INT:
1274 case LONG: {
1275 if (valueList.size() != 1) {
1276 errPw.println(tag + "Expected 1 value for type " + type
1277 + ". Found: " + valueList.size());
1278 return null;
1279 }
1280 break;
1281 }
1282 case STRING: {
1283 if (valueList.size() > 1) {
1284 errPw.println(tag + "Expected 0 or 1 values for type " + type
1285 + ". Found: " + valueList.size());
1286 return null;
1287 }
1288 break;
1289 }
1290 }
1291
1292 // Parse the value according to type and add it to the Bundle.
1293 switch (type) {
1294 case BOOLEAN: {
1295 if ("true".equalsIgnoreCase(valueList.get(0))) {
1296 bundle.putBoolean(key, true);
1297 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1298 bundle.putBoolean(key, false);
1299 } else {
1300 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1301 return null;
1302 }
1303 break;
1304 }
1305 case DOUBLE: {
1306 try {
1307 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1308 } catch (NumberFormatException nfe) {
1309 // Not a valid double
1310 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1311 return null;
1312 }
1313 break;
1314 }
1315 case DOUBLE_ARRAY: {
1316 double[] valueDoubleArray = null;
1317 if (valueList.size() > 0) {
1318 valueDoubleArray = new double[valueList.size()];
1319 for (int i = 0; i < valueList.size(); i++) {
1320 try {
1321 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1322 } catch (NumberFormatException nfe) {
1323 // Not a valid double
1324 errPw.println(
1325 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1326 return null;
1327 }
1328 }
1329 }
1330 bundle.putDoubleArray(key, valueDoubleArray);
1331 break;
1332 }
1333 case INT: {
1334 try {
1335 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1336 } catch (NumberFormatException nfe) {
1337 // Not a valid integer
1338 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1339 return null;
1340 }
1341 break;
1342 }
1343 case INT_ARRAY: {
1344 int[] valueIntArray = null;
1345 if (valueList.size() > 0) {
1346 valueIntArray = new int[valueList.size()];
1347 for (int i = 0; i < valueList.size(); i++) {
1348 try {
1349 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1350 } catch (NumberFormatException nfe) {
1351 // Not a valid integer
1352 errPw.println(tag
1353 + "Unable to parse " + valueList.get(i) + " as an integer.");
1354 return null;
1355 }
1356 }
1357 }
1358 bundle.putIntArray(key, valueIntArray);
1359 break;
1360 }
1361 case LONG: {
1362 try {
1363 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1364 } catch (NumberFormatException nfe) {
1365 // Not a valid long
1366 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1367 return null;
1368 }
1369 break;
1370 }
1371 case LONG_ARRAY: {
1372 long[] valueLongArray = null;
1373 if (valueList.size() > 0) {
1374 valueLongArray = new long[valueList.size()];
1375 for (int i = 0; i < valueList.size(); i++) {
1376 try {
1377 valueLongArray[i] = Long.parseLong(valueList.get(i));
1378 } catch (NumberFormatException nfe) {
1379 // Not a valid long
1380 errPw.println(
1381 tag + "Unable to parse " + valueList.get(i) + " as a long");
1382 return null;
1383 }
1384 }
1385 }
1386 bundle.putLongArray(key, valueLongArray);
1387 break;
1388 }
1389 case STRING: {
1390 String value = null;
1391 if (valueList.size() > 0) {
1392 value = valueList.get(0);
1393 }
1394 bundle.putString(key, value);
1395 break;
1396 }
1397 case STRING_ARRAY: {
1398 String[] valueStringArray = null;
1399 if (valueList.size() > 0) {
1400 valueStringArray = new String[valueList.size()];
1401 valueList.toArray(valueStringArray);
1402 }
1403 bundle.putStringArray(key, valueStringArray);
1404 break;
1405 }
1406 }
1407 return bundle;
1408 }
Shuo Qian489d9282020-07-09 11:30:03 -07001409
1410 private int handleEndBlockSuppressionCommand() {
1411 if (!checkShellUid()) {
1412 return -1;
1413 }
1414
1415 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1416 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1417 }
1418 return 0;
1419 }
Hui Wang641e81c2020-10-12 12:14:23 -07001420
Michele Berionne54af4632020-12-28 20:23:16 +00001421 private int handleRestartModemCommand() {
1422 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1423 // non user build.
1424 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1425 getErrPrintWriter().println("RestartModem: Permission denied.");
1426 return -1;
1427 }
1428
1429 boolean result = TelephonyManager.getDefault().rebootRadio();
1430 getOutPrintWriter().println(result);
1431
1432 return result ? 0 : -1;
1433 }
1434
Hui Wang641e81c2020-10-12 12:14:23 -07001435 private int handleGbaCommand() {
1436 String arg = getNextArg();
1437 if (arg == null) {
1438 onHelpGba();
1439 return 0;
1440 }
1441
1442 switch (arg) {
1443 case GBA_SET_SERVICE: {
1444 return handleGbaSetServiceCommand();
1445 }
1446 case GBA_GET_SERVICE: {
1447 return handleGbaGetServiceCommand();
1448 }
1449 case GBA_SET_RELEASE_TIME: {
1450 return handleGbaSetReleaseCommand();
1451 }
1452 case GBA_GET_RELEASE_TIME: {
1453 return handleGbaGetReleaseCommand();
1454 }
1455 }
1456
1457 return -1;
1458 }
1459
1460 private int getSubId(String cmd) {
1461 int slotId = getDefaultSlot();
1462 String opt = getNextOption();
1463 if (opt != null && opt.equals("-s")) {
1464 try {
1465 slotId = Integer.parseInt(getNextArgRequired());
1466 } catch (NumberFormatException e) {
1467 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1468 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1469 }
1470 }
1471 int[] subIds = SubscriptionManager.getSubId(slotId);
1472 return subIds[0];
1473 }
1474
1475 private int handleGbaSetServiceCommand() {
1476 int subId = getSubId("gba set-service");
1477 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1478 return -1;
1479 }
1480
1481 String packageName = getNextArg();
1482 try {
1483 if (packageName == null) {
1484 packageName = "";
1485 }
1486 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1487 if (VDBG) {
1488 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1489 + packageName + ", result=" + result);
1490 }
1491 getOutPrintWriter().println(result);
1492 } catch (RemoteException e) {
1493 Log.w(LOG_TAG, "gba set-service " + subId + " "
1494 + packageName + ", error" + e.getMessage());
1495 getErrPrintWriter().println("Exception: " + e.getMessage());
1496 return -1;
1497 }
1498 return 0;
1499 }
1500
1501 private int handleGbaGetServiceCommand() {
1502 String result;
1503
1504 int subId = getSubId("gba get-service");
1505 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1506 return -1;
1507 }
1508
1509 try {
1510 result = mInterface.getBoundGbaService(subId);
1511 } catch (RemoteException e) {
1512 return -1;
1513 }
1514 if (VDBG) {
1515 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1516 }
1517 getOutPrintWriter().println(result);
1518 return 0;
1519 }
1520
1521 private int handleGbaSetReleaseCommand() {
1522 //the release time value could be -1
1523 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1524 : SubscriptionManager.getDefaultSubscriptionId();
1525 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1526 return -1;
1527 }
1528
1529 String intervalStr = getNextArg();
1530 if (intervalStr == null) {
1531 return -1;
1532 }
1533
1534 try {
1535 int interval = Integer.parseInt(intervalStr);
1536 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1537 if (VDBG) {
1538 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1539 + intervalStr + ", result=" + result);
1540 }
1541 getOutPrintWriter().println(result);
1542 } catch (NumberFormatException | RemoteException e) {
1543 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1544 + intervalStr + ", error" + e.getMessage());
1545 getErrPrintWriter().println("Exception: " + e.getMessage());
1546 return -1;
1547 }
1548 return 0;
1549 }
1550
1551 private int handleGbaGetReleaseCommand() {
1552 int subId = getSubId("gba get-release");
1553 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1554 return -1;
1555 }
1556
1557 int result = 0;
1558 try {
1559 result = mInterface.getGbaReleaseTime(subId);
1560 } catch (RemoteException e) {
1561 return -1;
1562 }
1563 if (VDBG) {
1564 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1565 }
1566 getOutPrintWriter().println(result);
1567 return 0;
1568 }
Hui Wang761a6682020-10-31 05:12:53 +00001569
1570 private int handleSingleRegistrationConfigCommand() {
1571 String arg = getNextArg();
1572 if (arg == null) {
1573 onHelpSrc();
1574 return 0;
1575 }
1576
1577 switch (arg) {
1578 case SRC_SET_DEVICE_ENABLED: {
1579 return handleSrcSetDeviceEnabledCommand();
1580 }
1581 case SRC_GET_DEVICE_ENABLED: {
1582 return handleSrcGetDeviceEnabledCommand();
1583 }
1584 case SRC_SET_CARRIER_ENABLED: {
1585 return handleSrcSetCarrierEnabledCommand();
1586 }
1587 case SRC_GET_CARRIER_ENABLED: {
1588 return handleSrcGetCarrierEnabledCommand();
1589 }
1590 }
1591
1592 return -1;
1593 }
1594
1595 private int handleSrcSetDeviceEnabledCommand() {
1596 String enabledStr = getNextArg();
1597 if (enabledStr == null) {
1598 return -1;
1599 }
1600
1601 try {
1602 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1603 if (VDBG) {
1604 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1605 }
1606 getOutPrintWriter().println("Done");
1607 } catch (NumberFormatException | RemoteException e) {
1608 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1609 getErrPrintWriter().println("Exception: " + e.getMessage());
1610 return -1;
1611 }
1612 return 0;
1613 }
1614
1615 private int handleSrcGetDeviceEnabledCommand() {
1616 boolean result = false;
1617 try {
1618 result = mInterface.getDeviceSingleRegistrationEnabled();
1619 } catch (RemoteException e) {
1620 return -1;
1621 }
1622 if (VDBG) {
1623 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1624 }
1625 getOutPrintWriter().println(result);
1626 return 0;
1627 }
1628
1629 private int handleSrcSetCarrierEnabledCommand() {
1630 //the release time value could be -1
1631 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1632 : SubscriptionManager.getDefaultSubscriptionId();
1633 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1634 return -1;
1635 }
1636
1637 String enabledStr = getNextArg();
1638 if (enabledStr == null) {
1639 return -1;
1640 }
1641
1642 try {
1643 boolean result =
1644 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1645 if (VDBG) {
1646 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1647 + enabledStr + ", result=" + result);
1648 }
1649 getOutPrintWriter().println(result);
1650 } catch (NumberFormatException | RemoteException e) {
1651 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1652 + enabledStr + ", error" + e.getMessage());
1653 getErrPrintWriter().println("Exception: " + e.getMessage());
1654 return -1;
1655 }
1656 return 0;
1657 }
1658
1659 private int handleSrcGetCarrierEnabledCommand() {
1660 int subId = getSubId("src get-carrier-enabled");
1661 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1662 return -1;
1663 }
1664
1665 boolean result = false;
1666 try {
1667 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1668 } catch (RemoteException e) {
1669 return -1;
1670 }
1671 if (VDBG) {
1672 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1673 }
1674 getOutPrintWriter().println(result);
1675 return 0;
1676 }
Hall Liuaa4211e2021-01-20 15:43:39 -08001677
1678 private void onHelpCallComposer() {
1679 PrintWriter pw = getOutPrintWriter();
1680 pw.println("Call composer commands");
1681 pw.println(" callcomposer test-mode enable|disable|query");
1682 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
1683 pw.println(" upload/download from carrier servers is disabled, and operations are");
1684 pw.println(" performed using emulated local files instead.");
1685 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
1686 pw.println(" Simulates an outgoing call being placed with the picture ID as");
1687 pw.println(" the provided UUID. This triggers storage to the call log.");
1688 }
1689
1690 private int handleCallComposerCommand() {
1691 String arg = getNextArg();
1692 if (arg == null) {
1693 onHelpCallComposer();
1694 return 0;
1695 }
1696
1697 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
1698 "MODIFY_PHONE_STATE required for call composer shell cmds");
1699 switch (arg) {
1700 case CALL_COMPOSER_TEST_MODE: {
1701 String enabledStr = getNextArg();
1702 if (ENABLE.equals(enabledStr)) {
1703 CallComposerPictureManager.sTestMode = true;
1704 } else if (DISABLE.equals(enabledStr)) {
1705 CallComposerPictureManager.sTestMode = false;
1706 } else if (QUERY.equals(enabledStr)) {
1707 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
1708 } else {
1709 onHelpCallComposer();
1710 return 1;
1711 }
1712 break;
1713 }
1714 case CALL_COMPOSER_SIMULATE_CALL: {
1715 int subscriptionId = Integer.valueOf(getNextArg());
1716 String uuidString = getNextArg();
1717 UUID uuid = UUID.fromString(uuidString);
1718 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
1719 Binder.withCleanCallingIdentity(() -> {
1720 CallComposerPictureManager.getInstance(mContext, subscriptionId)
1721 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
1722 });
1723 try {
1724 Uri uri = storageUriFuture.get();
1725 getOutPrintWriter().println(String.valueOf(uri));
1726 } catch (Exception e) {
1727 throw new RuntimeException(e);
1728 }
1729 break;
1730 }
1731 }
1732
1733 return 0;
1734 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001735}