blob: 5bd810c0b80ad81e6c21729c33e94e358bf04a16 [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
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010024import android.content.Context;
Hall Liud892bec2018-11-30 14:51:45 -080025import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010026import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070028import android.os.RemoteException;
Shuo Qian489d9282020-07-09 11:30:03 -070029import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070031import android.telephony.SubscriptionManager;
Michele Berionne38c1afa2020-12-28 20:23:16 +000032import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080033import android.telephony.emergency.EmergencyNumber;
Brad Ebinger24c29992019-12-05 13:03:21 -080034import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080035import android.text.TextUtils;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.util.Log;
37
38import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080039import com.android.internal.telephony.Phone;
40import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080041import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080042import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080043import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080044import com.android.modules.utils.BasicShellCommandHandler;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070045
46import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080047import java.util.ArrayList;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010048import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080049import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010050import java.util.Map;
51import java.util.TreeSet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052
53/**
54 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
55 * permission checks have been done before onCommand was called. Make sure any commands processed
56 * here also contain the appropriate permissions checks.
57 */
58
Hall Liua1548bd2019-12-24 14:14:12 -080059public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070060
61 private static final String LOG_TAG = "TelephonyShellCommand";
62 // Don't commit with this true.
63 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070064 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070065
66 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080067 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080068 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070069 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne38c1afa2020-12-28 20:23:16 +000070 private static final String RESTART_MODEM = "restart-modem";
Michele Berionned9fbae52020-11-13 02:36:59 +000071 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080073 private static final String DATA_TEST_MODE = "data";
74 private static final String DATA_ENABLE = "enable";
75 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080076
Brad Ebinger999d3302020-11-25 14:31:39 -080077 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
78 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
79 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070080 private static final String IMS_ENABLE = "enable";
81 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070082 // Used to disable or enable processing of conference event package data from the network.
83 // This is handy for testing scenarios where CEP data does not exist on a network which does
84 // support CEP data.
85 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070086
Hall Liud892bec2018-11-30 14:51:45 -080087 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080088 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080089
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010090 private static final String CC_GET_VALUE = "get-value";
91 private static final String CC_SET_VALUE = "set-value";
92 private static final String CC_CLEAR_VALUES = "clear-values";
93
Hui Wang0866fcc2020-10-12 12:14:23 -070094 private static final String GBA_SUBCOMMAND = "gba";
95 private static final String GBA_SET_SERVICE = "set-service";
96 private static final String GBA_GET_SERVICE = "get-service";
97 private static final String GBA_SET_RELEASE_TIME = "set-release";
98 private static final String GBA_GET_RELEASE_TIME = "get-release";
99
Hui Wang068ab862020-10-31 05:12:53 +0000100 private static final String SINGLE_REGISTATION_CONFIG = "src";
101 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
102 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
103 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
104 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wang19a21872021-02-19 20:45:36 -0800105 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
106 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wang068ab862020-10-31 05:12:53 +0000107
Tyler Gunn92479152021-01-20 16:30:10 -0800108 private static final String D2D_SUBCOMMAND = "d2d";
109 private static final String D2D_SEND = "send";
110
James.cf Linbcdf8b32021-01-14 16:44:13 +0800111 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800112 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800113 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800114 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
115 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800116
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800117 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
118 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
119
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700120 // Take advantage of existing methods that already contain permissions checks when possible.
121 private final ITelephony mInterface;
122
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100123 private SubscriptionManager mSubscriptionManager;
124 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700125 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100126
127 private enum CcType {
128 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
129 STRING_ARRAY, UNKNOWN
130 }
131
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100132 private class CcOptionParseResult {
133 public int mSubId;
134 public boolean mPersistent;
135 }
136
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100137 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
138 // keys by looking at the end of the string which usually tells the type.
139 // For instance: "xxxx_string", "xxxx_string_array", etc.
140 // The carrier config keys in this map does not follow this convention. It is therefore not
141 // possible to infer the type for these keys by looking at the string.
142 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
143 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
154 CcType.STRING);
155 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
156 CcType.STRING_ARRAY);
157 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
158 CcType.STRING_ARRAY);
159 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
160 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
161 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
162 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
163 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
164 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
165 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
167 }
168 };
169
170 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700171 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100172 mCarrierConfigManager =
173 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
174 mSubscriptionManager = (SubscriptionManager)
175 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700176 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700177 }
178
179 @Override
180 public int onCommand(String cmd) {
181 if (cmd == null) {
182 return handleDefaultCommands(null);
183 }
184
185 switch (cmd) {
186 case IMS_SUBCOMMAND: {
187 return handleImsCommand();
188 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800189 case RCS_UCE_COMMAND:
190 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800191 case NUMBER_VERIFICATION_SUBCOMMAND:
192 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800193 case EMERGENCY_NUMBER_TEST_MODE:
194 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100195 case CARRIER_CONFIG_SUBCOMMAND: {
196 return handleCcCommand();
197 }
Shuo Qianf5125122019-12-16 17:03:07 -0800198 case DATA_TEST_MODE:
199 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700200 case END_BLOCK_SUPPRESSION:
201 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700202 case GBA_SUBCOMMAND:
203 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800204 case D2D_SUBCOMMAND:
205 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000206 case SINGLE_REGISTATION_CONFIG:
207 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000208 case RESTART_MODEM:
209 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000210 case UNATTENDED_REBOOT:
211 return handleUnattendedReboot();
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800212 case HAS_CARRIER_PRIVILEGES_COMMAND:
213 return handleHasCarrierPrivilegesCommand();
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 Wang0866fcc2020-10-12 12:14:23 -0700238 pw.println(" gba");
239 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000240 pw.println(" src");
241 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000242 pw.println(" restart-modem");
243 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000244 pw.println(" unattended-reboot");
245 pw.println(" Prepare for unattended reboot.");
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800246 pw.println(" has-carrier-privileges [package]");
247 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700248 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800249 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800250 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700251 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800252 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100253 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700254 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000255 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800256 onHelpD2D();
257 }
258
259 private void onHelpD2D() {
260 PrintWriter pw = getOutPrintWriter();
261 pw.println("D2D Comms Commands:");
262 pw.println(" d2d send TYPE VALUE");
263 pw.println(" Sends a D2D message of specified type and value.");
264 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
265 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
266 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
267 MESSAGE_CALL_AUDIO_CODEC));
268 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
269 + Communicator.messageToString(
270 MESSAGE_DEVICE_BATTERY_STATE));
271 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
272 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700273 }
274
275 private void onHelpIms() {
276 PrintWriter pw = getOutPrintWriter();
277 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800278 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700279 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
280 pw.println(" ImsService. Options are:");
281 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
282 pw.println(" is specified, it will choose the default voice SIM slot.");
283 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
284 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800285 pw.println(" -f: Set the feature that this override if for, if no option is");
286 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700287 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
288 pw.println(" Gets the package name of the currently defined ImsService.");
289 pw.println(" Options are:");
290 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
291 pw.println(" is specified, it will choose the default voice SIM slot.");
292 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000293 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800294 pw.println(" -f: The feature type that the query will be requested for. If none is");
295 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800296 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
297 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
298 pw.println(" configuration overrides. Options are:");
299 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
300 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700301 pw.println(" ims enable [-s SLOT_ID]");
302 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
303 pw.println(" if none is specified.");
304 pw.println(" ims disable [-s SLOT_ID]");
305 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
306 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700307 pw.println(" ims conference-event-package [enable/disable]");
308 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700309 }
310
James.cf Linbcdf8b32021-01-14 16:44:13 +0800311 private void onHelpUce() {
312 PrintWriter pw = getOutPrintWriter();
313 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800314 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
315 pw.println(" Get the EAB contacts from the EAB database.");
316 pw.println(" Options are:");
317 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
318 pw.println(" Expected output format :");
319 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800320 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
321 pw.println(" Remove the EAB contacts from the EAB database.");
322 pw.println(" Options are:");
323 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
324 pw.println(" is specified, it will choose the default voice SIM slot.");
325 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800326 pw.println(" uce get-device-enabled");
327 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
328 pw.println(" uce set-device-enabled true|false");
329 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
330 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800331 }
332
Hall Liud892bec2018-11-30 14:51:45 -0800333 private void onHelpNumberVerification() {
334 PrintWriter pw = getOutPrintWriter();
335 pw.println("Number verification commands");
336 pw.println(" numverify override-package PACKAGE_NAME;");
337 pw.println(" Set the authorized package for number verification.");
338 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800339 pw.println(" numverify fake-call NUMBER;");
340 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
341 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800342 }
343
Shuo Qianf5125122019-12-16 17:03:07 -0800344 private void onHelpDataTestMode() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("Mobile Data Test Mode Commands:");
347 pw.println(" data enable: enable mobile data connectivity");
348 pw.println(" data disable: disable mobile data connectivity");
349 }
350
sqian9d4df8b2019-01-15 18:32:07 -0800351 private void onHelpEmergencyNumber() {
352 PrintWriter pw = getOutPrintWriter();
353 pw.println("Emergency Number Test Mode Commands:");
354 pw.println(" emergency-number-test-mode ");
355 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
356 + " the test mode");
357 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700358 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800359 pw.println(" -c: clear the emergency number list in the test mode.");
360 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700361 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800362 pw.println(" -p: get the full emergency number list in the test mode.");
363 }
364
Shuo Qian489d9282020-07-09 11:30:03 -0700365 private void onHelpEndBlockSupperssion() {
366 PrintWriter pw = getOutPrintWriter();
367 pw.println("End Block Suppression command:");
368 pw.println(" end-block-suppression: disable suppressing blocking by contact");
369 pw.println(" with emergency services.");
370 }
371
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100372 private void onHelpCc() {
373 PrintWriter pw = getOutPrintWriter();
374 pw.println("Carrier Config Commands:");
375 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
376 pw.println(" Print carrier config values.");
377 pw.println(" Options are:");
378 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
379 pw.println(" is specified, it will choose the default voice SIM slot.");
380 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
381 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100382 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100383 pw.println(" Set carrier config KEY to NEW_VALUE.");
384 pw.println(" Options are:");
385 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
386 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100387 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100388 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
389 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
390 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
391 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
392 pw.println(" cc clear-values [-s SLOT_ID]");
393 pw.println(" Clear all carrier override values that has previously been set");
394 pw.println(" with set-value");
395 pw.println(" Options are:");
396 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
397 pw.println(" is specified, it will choose the default voice SIM slot.");
398 }
399
Hui Wang0866fcc2020-10-12 12:14:23 -0700400 private void onHelpGba() {
401 PrintWriter pw = getOutPrintWriter();
402 pw.println("Gba Commands:");
403 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
404 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
405 pw.println(" Options are:");
406 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
407 pw.println(" is specified, it will choose the default voice SIM slot.");
408 pw.println(" gba get-service [-s SLOT_ID]");
409 pw.println(" Gets the package name of the currently defined GbaService.");
410 pw.println(" Options are:");
411 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
412 pw.println(" is specified, it will choose the default voice SIM slot.");
413 pw.println(" gba set-release [-s SLOT_ID] n");
414 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
415 pw.println(" Do not release/unbind if n is -1.");
416 pw.println(" Options are:");
417 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
418 pw.println(" is specified, it will choose the default voice SIM slot.");
419 pw.println(" gba get-release [-s SLOT_ID]");
420 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
421 pw.println(" Options are:");
422 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
423 pw.println(" is specified, it will choose the default voice SIM slot.");
424 }
425
Hui Wang068ab862020-10-31 05:12:53 +0000426 private void onHelpSrc() {
427 PrintWriter pw = getOutPrintWriter();
428 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wang19a21872021-02-19 20:45:36 -0800429 pw.println(" src set-test-enabled true|false");
430 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
431 pw.println(" The value could be true, false, or null(undefined).");
432 pw.println(" src get-test-enabled");
433 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang068ab862020-10-31 05:12:53 +0000434 pw.println(" src set-device-enabled true|false|null");
435 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
436 pw.println(" The value could be true, false, or null(undefined).");
437 pw.println(" src get-device-enabled");
438 pw.println(" Gets the device config for RCS VoLTE single registration.");
439 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
440 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
441 pw.println(" The value could be true, false, or null(undefined).");
442 pw.println(" Options are:");
443 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
444 pw.println(" is specified, it will choose the default voice SIM slot.");
445 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
446 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
447 pw.println(" Options are:");
448 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
449 pw.println(" is specified, it will choose the default voice SIM slot.");
450 }
451
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700452 private int handleImsCommand() {
453 String arg = getNextArg();
454 if (arg == null) {
455 onHelpIms();
456 return 0;
457 }
458
459 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800460 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700461 return handleImsSetServiceCommand();
462 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800463 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700464 return handleImsGetServiceCommand();
465 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800466 case IMS_CLEAR_SERVICE_OVERRIDE: {
467 return handleImsClearCarrierServiceCommand();
468 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700469 case IMS_ENABLE: {
470 return handleEnableIms();
471 }
472 case IMS_DISABLE: {
473 return handleDisableIms();
474 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700475 case IMS_CEP: {
476 return handleCepChange();
477 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700478 }
479
480 return -1;
481 }
482
Shuo Qianf5125122019-12-16 17:03:07 -0800483 private int handleDataTestModeCommand() {
484 PrintWriter errPw = getErrPrintWriter();
485 String arg = getNextArgRequired();
486 if (arg == null) {
487 onHelpDataTestMode();
488 return 0;
489 }
490 switch (arg) {
491 case DATA_ENABLE: {
492 try {
493 mInterface.enableDataConnectivity();
494 } catch (RemoteException ex) {
495 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
496 errPw.println("Exception: " + ex.getMessage());
497 return -1;
498 }
499 break;
500 }
501 case DATA_DISABLE: {
502 try {
503 mInterface.disableDataConnectivity();
504 } catch (RemoteException ex) {
505 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
506 errPw.println("Exception: " + ex.getMessage());
507 return -1;
508 }
509 break;
510 }
511 default:
512 onHelpDataTestMode();
513 break;
514 }
515 return 0;
516 }
517
sqian9d4df8b2019-01-15 18:32:07 -0800518 private int handleEmergencyNumberTestModeCommand() {
519 PrintWriter errPw = getErrPrintWriter();
520 String opt = getNextOption();
521 if (opt == null) {
522 onHelpEmergencyNumber();
523 return 0;
524 }
525
526 switch (opt) {
527 case "-a": {
528 String emergencyNumberCmd = getNextArgRequired();
529 if (emergencyNumberCmd == null
530 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700531 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800532 + " to be specified after -a in the command ");
533 return -1;
534 }
535 try {
536 mInterface.updateEmergencyNumberListTestMode(
537 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
538 new EmergencyNumber(emergencyNumberCmd, "", "",
539 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
540 new ArrayList<String>(),
541 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
542 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
543 } catch (RemoteException ex) {
544 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
545 + ", error " + ex.getMessage());
546 errPw.println("Exception: " + ex.getMessage());
547 return -1;
548 }
549 break;
550 }
551 case "-c": {
552 try {
553 mInterface.updateEmergencyNumberListTestMode(
554 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
555 } catch (RemoteException ex) {
556 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
557 errPw.println("Exception: " + ex.getMessage());
558 return -1;
559 }
560 break;
561 }
562 case "-r": {
563 String emergencyNumberCmd = getNextArgRequired();
564 if (emergencyNumberCmd == null
565 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700566 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800567 + " to be specified after -r in the command ");
568 return -1;
569 }
570 try {
571 mInterface.updateEmergencyNumberListTestMode(
572 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
573 new EmergencyNumber(emergencyNumberCmd, "", "",
574 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
575 new ArrayList<String>(),
576 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
577 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
578 } catch (RemoteException ex) {
579 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
580 + ", error " + ex.getMessage());
581 errPw.println("Exception: " + ex.getMessage());
582 return -1;
583 }
584 break;
585 }
586 case "-p": {
587 try {
588 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
589 } catch (RemoteException ex) {
590 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
591 errPw.println("Exception: " + ex.getMessage());
592 return -1;
593 }
594 break;
595 }
596 default:
597 onHelpEmergencyNumber();
598 break;
599 }
600 return 0;
601 }
602
Hall Liud892bec2018-11-30 14:51:45 -0800603 private int handleNumberVerificationCommand() {
604 String arg = getNextArg();
605 if (arg == null) {
606 onHelpNumberVerification();
607 return 0;
608 }
609
Hall Liuca5af3a2018-12-04 16:58:23 -0800610 if (!checkShellUid()) {
611 return -1;
612 }
613
Hall Liud892bec2018-11-30 14:51:45 -0800614 switch (arg) {
615 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800616 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
617 return 0;
618 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800619 case NUMBER_VERIFICATION_FAKE_CALL: {
620 boolean val = NumberVerificationManager.getInstance()
621 .checkIncomingCall(getNextArg());
622 getOutPrintWriter().println(val ? "1" : "0");
623 return 0;
624 }
Hall Liud892bec2018-11-30 14:51:45 -0800625 }
626
627 return -1;
628 }
629
Tyler Gunn92479152021-01-20 16:30:10 -0800630 private int handleD2dCommand() {
631 String arg = getNextArg();
632 if (arg == null) {
633 onHelpD2D();
634 return 0;
635 }
636
637 switch (arg) {
638 case D2D_SEND: {
639 return handleD2dSendCommand();
640 }
641 }
642
643 return -1;
644 }
645
646 private int handleD2dSendCommand() {
647 PrintWriter errPw = getErrPrintWriter();
648 String opt;
649 int messageType = -1;
650 int messageValue = -1;
651
652
653 String arg = getNextArg();
654 if (arg == null) {
655 onHelpD2D();
656 return 0;
657 }
658 try {
659 messageType = Integer.parseInt(arg);
660 } catch (NumberFormatException e) {
661 errPw.println("message type must be a valid integer");
662 return -1;
663 }
664
665 arg = getNextArg();
666 if (arg == null) {
667 onHelpD2D();
668 return 0;
669 }
670 try {
671 messageValue = Integer.parseInt(arg);
672 } catch (NumberFormatException e) {
673 errPw.println("message value must be a valid integer");
674 return -1;
675 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800676
Tyler Gunn92479152021-01-20 16:30:10 -0800677 try {
678 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
679 } catch (RemoteException e) {
680 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
681 errPw.println("Exception: " + e.getMessage());
682 return -1;
683 }
684
685 return 0;
686 }
687
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700688 // ims set-ims-service
689 private int handleImsSetServiceCommand() {
690 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700691 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700692 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800693 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700694
695 String opt;
696 while ((opt = getNextOption()) != null) {
697 switch (opt) {
698 case "-s": {
699 try {
700 slotId = Integer.parseInt(getNextArgRequired());
701 } catch (NumberFormatException e) {
702 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
703 return -1;
704 }
705 break;
706 }
707 case "-c": {
708 isCarrierService = true;
709 break;
710 }
711 case "-d": {
712 isCarrierService = false;
713 break;
714 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800715 case "-f": {
716 String featureString = getNextArgRequired();
717 String[] features = featureString.split(",");
718 for (int i = 0; i < features.length; i++) {
719 try {
720 Integer result = Integer.parseInt(features[i]);
721 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
722 || result >= ImsFeature.FEATURE_MAX) {
723 errPw.println("ims set-ims-service -f " + result
724 + " is an invalid feature.");
725 return -1;
726 }
727 featuresList.add(result);
728 } catch (NumberFormatException e) {
729 errPw.println("ims set-ims-service -f tried to parse " + features[i]
730 + " as an integer.");
731 return -1;
732 }
733 }
734 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700735 }
736 }
737 // Mandatory param, either -c or -d
738 if (isCarrierService == null) {
739 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
740 return -1;
741 }
742
743 String packageName = getNextArg();
744
745 try {
746 if (packageName == null) {
747 packageName = "";
748 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800749 int[] featureArray = new int[featuresList.size()];
750 for (int i = 0; i < featuresList.size(); i++) {
751 featureArray[i] = featuresList.get(i);
752 }
753 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
754 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700755 if (VDBG) {
756 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800757 + (isCarrierService ? "-c " : "-d ")
758 + "-f " + featuresList + " "
759 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700760 }
761 getOutPrintWriter().println(result);
762 } catch (RemoteException e) {
763 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800764 + (isCarrierService ? "-c " : "-d ")
765 + "-f " + featuresList + " "
766 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700767 errPw.println("Exception: " + e.getMessage());
768 return -1;
769 }
770 return 0;
771 }
772
Brad Ebinger999d3302020-11-25 14:31:39 -0800773 // ims clear-ims-service-override
774 private int handleImsClearCarrierServiceCommand() {
775 PrintWriter errPw = getErrPrintWriter();
776 int slotId = getDefaultSlot();
777
778 String opt;
779 while ((opt = getNextOption()) != null) {
780 switch (opt) {
781 case "-s": {
782 try {
783 slotId = Integer.parseInt(getNextArgRequired());
784 } catch (NumberFormatException e) {
785 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
786 return -1;
787 }
788 break;
789 }
790 }
791 }
792
793 try {
794 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
795 if (VDBG) {
796 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
797 + ", result=" + result);
798 }
799 getOutPrintWriter().println(result);
800 } catch (RemoteException e) {
801 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
802 + ", error" + e.getMessage());
803 errPw.println("Exception: " + e.getMessage());
804 return -1;
805 }
806 return 0;
807 }
808
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700809 // ims get-ims-service
810 private int handleImsGetServiceCommand() {
811 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700812 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700813 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800814 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700815
816 String opt;
817 while ((opt = getNextOption()) != null) {
818 switch (opt) {
819 case "-s": {
820 try {
821 slotId = Integer.parseInt(getNextArgRequired());
822 } catch (NumberFormatException e) {
823 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
824 return -1;
825 }
826 break;
827 }
828 case "-c": {
829 isCarrierService = true;
830 break;
831 }
832 case "-d": {
833 isCarrierService = false;
834 break;
835 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800836 case "-f": {
837 try {
838 featureType = Integer.parseInt(getNextArg());
839 } catch (NumberFormatException e) {
840 errPw.println("ims get-ims-service -f requires valid integer as feature.");
841 return -1;
842 }
843 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
844 || featureType >= ImsFeature.FEATURE_MAX) {
845 errPw.println("ims get-ims-service -f invalid feature.");
846 return -1;
847 }
848 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700849 }
850 }
851 // Mandatory param, either -c or -d
852 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800853 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700854 return -1;
855 }
856
857 String result;
858 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800859 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700860 } catch (RemoteException e) {
861 return -1;
862 }
863 if (VDBG) {
864 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800865 + (isCarrierService ? "-c " : "-d ")
866 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
867 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700868 }
869 getOutPrintWriter().println(result);
870 return 0;
871 }
872
873 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700874 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700875 String opt;
876 while ((opt = getNextOption()) != null) {
877 switch (opt) {
878 case "-s": {
879 try {
880 slotId = Integer.parseInt(getNextArgRequired());
881 } catch (NumberFormatException e) {
882 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
883 return -1;
884 }
885 break;
886 }
887 }
888 }
889 try {
890 mInterface.enableIms(slotId);
891 } catch (RemoteException e) {
892 return -1;
893 }
894 if (VDBG) {
895 Log.v(LOG_TAG, "ims enable -s " + slotId);
896 }
897 return 0;
898 }
899
900 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700901 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700902 String opt;
903 while ((opt = getNextOption()) != null) {
904 switch (opt) {
905 case "-s": {
906 try {
907 slotId = Integer.parseInt(getNextArgRequired());
908 } catch (NumberFormatException e) {
909 getErrPrintWriter().println(
910 "ims disable requires an integer as a SLOT_ID.");
911 return -1;
912 }
913 break;
914 }
915 }
916 }
917 try {
918 mInterface.disableIms(slotId);
919 } catch (RemoteException e) {
920 return -1;
921 }
922 if (VDBG) {
923 Log.v(LOG_TAG, "ims disable -s " + slotId);
924 }
925 return 0;
926 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700927
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700928 private int handleCepChange() {
929 Log.i(LOG_TAG, "handleCepChange");
930 String opt = getNextArg();
931 if (opt == null) {
932 return -1;
933 }
934 boolean isCepEnabled = opt.equals("enable");
935
936 try {
937 mInterface.setCepEnabled(isCepEnabled);
938 } catch (RemoteException e) {
939 return -1;
940 }
941 return 0;
942 }
943
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700944 private int getDefaultSlot() {
945 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
946 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
947 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
948 // If there is no default, default to slot 0.
949 slotId = DEFAULT_PHONE_ID;
950 }
951 return slotId;
952 }
sqian2fff4a32018-11-05 14:18:37 -0800953
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100954 // Parse options related to Carrier Config Commands.
955 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100956 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100957 CcOptionParseResult result = new CcOptionParseResult();
958 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
959 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100960
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100961 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100962 while ((opt = getNextOption()) != null) {
963 switch (opt) {
964 case "-s": {
965 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100966 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
967 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
968 errPw.println(tag + "No valid subscription found.");
969 return null;
970 }
971
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100972 } catch (IllegalArgumentException e) {
973 // Missing slot id
974 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100975 return null;
976 }
977 break;
978 }
979 case "-p": {
980 if (allowOptionPersistent) {
981 result.mPersistent = true;
982 } else {
983 errPw.println(tag + "Unexpected option " + opt);
984 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100985 }
986 break;
987 }
988 default: {
989 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100990 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100991 }
992 }
993 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100994 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100995 }
996
997 private int slotStringToSubId(String tag, String slotString) {
998 int slotId = -1;
999 try {
1000 slotId = Integer.parseInt(slotString);
1001 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001002 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1003 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1004 }
1005
1006 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001007 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1008 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1009 }
1010
Qiong Liuf25799b2020-09-10 10:13:46 +08001011 Phone phone = PhoneFactory.getPhone(slotId);
1012 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001013 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1014 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1015 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001016 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001017 }
1018
Hall Liud892bec2018-11-30 14:51:45 -08001019 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001020 // adb can run as root or as shell, depending on whether the device is rooted.
1021 return Binder.getCallingUid() == Process.SHELL_UID
1022 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001023 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001024
1025 private int handleCcCommand() {
1026 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1027 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001028 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001029 getErrPrintWriter().println("cc: Permission denied.");
1030 return -1;
1031 }
1032
1033 String arg = getNextArg();
1034 if (arg == null) {
1035 onHelpCc();
1036 return 0;
1037 }
1038
1039 switch (arg) {
1040 case CC_GET_VALUE: {
1041 return handleCcGetValue();
1042 }
1043 case CC_SET_VALUE: {
1044 return handleCcSetValue();
1045 }
1046 case CC_CLEAR_VALUES: {
1047 return handleCcClearValues();
1048 }
1049 default: {
1050 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1051 }
1052 }
1053 return -1;
1054 }
1055
1056 // cc get-value
1057 private int handleCcGetValue() {
1058 PrintWriter errPw = getErrPrintWriter();
1059 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1060 String key = null;
1061
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001062 // Parse all options
1063 CcOptionParseResult options = parseCcOptions(tag, false);
1064 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001065 return -1;
1066 }
1067
1068 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001069 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001070 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001071 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001072 return -1;
1073 }
1074
1075 // Get the key.
1076 key = getNextArg();
1077 if (key != null) {
1078 // A key was provided. Verify if it is a valid key
1079 if (!bundle.containsKey(key)) {
1080 errPw.println(tag + key + " is not a valid key.");
1081 return -1;
1082 }
1083
1084 // Print the carrier config value for key.
1085 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1086 } else {
1087 // No key provided. Show all values.
1088 // Iterate over a sorted list of all carrier config keys and print them.
1089 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1090 for (String k : sortedSet) {
1091 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1092 }
1093 }
1094 return 0;
1095 }
1096
1097 // cc set-value
1098 private int handleCcSetValue() {
1099 PrintWriter errPw = getErrPrintWriter();
1100 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1101
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001102 // Parse all options
1103 CcOptionParseResult options = parseCcOptions(tag, true);
1104 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001105 return -1;
1106 }
1107
1108 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001109 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001110 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001111 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001112 return -1;
1113 }
1114
1115 // Get the key.
1116 String key = getNextArg();
1117 if (key == null || key.equals("")) {
1118 errPw.println(tag + "KEY is missing");
1119 return -1;
1120 }
1121
1122 // Verify if the key is valid
1123 if (!originalValues.containsKey(key)) {
1124 errPw.println(tag + key + " is not a valid key.");
1125 return -1;
1126 }
1127
1128 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1129 ArrayList<String> valueList = new ArrayList<String>();
1130 while (peekNextArg() != null) {
1131 valueList.add(getNextArg());
1132 }
1133
1134 // Find the type of the carrier config value
1135 CcType type = getType(tag, key, originalValues);
1136 if (type == CcType.UNKNOWN) {
1137 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1138 return -1;
1139 }
1140
1141 // Create an override bundle containing the key and value that should be overriden.
1142 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1143 if (overrideBundle == null) {
1144 return -1;
1145 }
1146
1147 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001148 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001149
1150 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001151 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001152 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001153 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001154 return -1;
1155 }
1156
1157 // Print the original and new value.
1158 String originalValueString = ccValueToString(key, type, originalValues);
1159 String newValueString = ccValueToString(key, type, newValues);
1160 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1161 getOutPrintWriter().println("New value: \n" + newValueString);
1162
1163 return 0;
1164 }
1165
1166 // cc clear-values
1167 private int handleCcClearValues() {
1168 PrintWriter errPw = getErrPrintWriter();
1169 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1170
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001171 // Parse all options
1172 CcOptionParseResult options = parseCcOptions(tag, false);
1173 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001174 return -1;
1175 }
1176
1177 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001178 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001179 getOutPrintWriter()
1180 .println("All previously set carrier config override values has been cleared");
1181 return 0;
1182 }
1183
1184 private CcType getType(String tag, String key, PersistableBundle bundle) {
1185 // Find the type by checking the type of the current value stored in the bundle.
1186 Object value = bundle.get(key);
1187
1188 if (CC_TYPE_MAP.containsKey(key)) {
1189 return CC_TYPE_MAP.get(key);
1190 } else if (value != null) {
1191 if (value instanceof Boolean) {
1192 return CcType.BOOLEAN;
1193 } else if (value instanceof Double) {
1194 return CcType.DOUBLE;
1195 } else if (value instanceof double[]) {
1196 return CcType.DOUBLE_ARRAY;
1197 } else if (value instanceof Integer) {
1198 return CcType.INT;
1199 } else if (value instanceof int[]) {
1200 return CcType.INT_ARRAY;
1201 } else if (value instanceof Long) {
1202 return CcType.LONG;
1203 } else if (value instanceof long[]) {
1204 return CcType.LONG_ARRAY;
1205 } else if (value instanceof String) {
1206 return CcType.STRING;
1207 } else if (value instanceof String[]) {
1208 return CcType.STRING_ARRAY;
1209 }
1210 } else {
1211 // Current value was null and can therefore not be used in order to find the type.
1212 // Check the name of the key to infer the type. This check is not needed for primitive
1213 // data types (boolean, double, int and long), since they can not be null.
1214 if (key.endsWith("double_array")) {
1215 return CcType.DOUBLE_ARRAY;
1216 }
1217 if (key.endsWith("int_array")) {
1218 return CcType.INT_ARRAY;
1219 }
1220 if (key.endsWith("long_array")) {
1221 return CcType.LONG_ARRAY;
1222 }
1223 if (key.endsWith("string")) {
1224 return CcType.STRING;
1225 }
1226 if (key.endsWith("string_array") || key.endsWith("strings")) {
1227 return CcType.STRING_ARRAY;
1228 }
1229 }
1230
1231 // Not possible to infer the type by looking at the current value or the key.
1232 PrintWriter errPw = getErrPrintWriter();
1233 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1234 return CcType.UNKNOWN;
1235 }
1236
1237 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1238 String result;
1239 StringBuilder valueString = new StringBuilder();
1240 String typeString = type.toString();
1241 Object value = bundle.get(key);
1242
1243 if (value == null) {
1244 valueString.append("null");
1245 } else {
1246 switch (type) {
1247 case DOUBLE_ARRAY: {
1248 // Format the string representation of the int array as value1 value2......
1249 double[] valueArray = (double[]) value;
1250 for (int i = 0; i < valueArray.length; i++) {
1251 if (i != 0) {
1252 valueString.append(" ");
1253 }
1254 valueString.append(valueArray[i]);
1255 }
1256 break;
1257 }
1258 case INT_ARRAY: {
1259 // Format the string representation of the int array as value1 value2......
1260 int[] valueArray = (int[]) value;
1261 for (int i = 0; i < valueArray.length; i++) {
1262 if (i != 0) {
1263 valueString.append(" ");
1264 }
1265 valueString.append(valueArray[i]);
1266 }
1267 break;
1268 }
1269 case LONG_ARRAY: {
1270 // Format the string representation of the int array as value1 value2......
1271 long[] valueArray = (long[]) value;
1272 for (int i = 0; i < valueArray.length; i++) {
1273 if (i != 0) {
1274 valueString.append(" ");
1275 }
1276 valueString.append(valueArray[i]);
1277 }
1278 break;
1279 }
1280 case STRING: {
1281 valueString.append("\"" + value.toString() + "\"");
1282 break;
1283 }
1284 case STRING_ARRAY: {
1285 // Format the string representation of the string array as "value1" "value2"....
1286 String[] valueArray = (String[]) value;
1287 for (int i = 0; i < valueArray.length; i++) {
1288 if (i != 0) {
1289 valueString.append(" ");
1290 }
1291 if (valueArray[i] != null) {
1292 valueString.append("\"" + valueArray[i] + "\"");
1293 } else {
1294 valueString.append("null");
1295 }
1296 }
1297 break;
1298 }
1299 default: {
1300 valueString.append(value.toString());
1301 }
1302 }
1303 }
1304 return String.format("%-70s %-15s %s", key, typeString, valueString);
1305 }
1306
1307 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1308 ArrayList<String> valueList) {
1309 PrintWriter errPw = getErrPrintWriter();
1310 PersistableBundle bundle = new PersistableBundle();
1311
1312 // First verify that a valid number of values has been provided for the type.
1313 switch (type) {
1314 case BOOLEAN:
1315 case DOUBLE:
1316 case INT:
1317 case LONG: {
1318 if (valueList.size() != 1) {
1319 errPw.println(tag + "Expected 1 value for type " + type
1320 + ". Found: " + valueList.size());
1321 return null;
1322 }
1323 break;
1324 }
1325 case STRING: {
1326 if (valueList.size() > 1) {
1327 errPw.println(tag + "Expected 0 or 1 values for type " + type
1328 + ". Found: " + valueList.size());
1329 return null;
1330 }
1331 break;
1332 }
1333 }
1334
1335 // Parse the value according to type and add it to the Bundle.
1336 switch (type) {
1337 case BOOLEAN: {
1338 if ("true".equalsIgnoreCase(valueList.get(0))) {
1339 bundle.putBoolean(key, true);
1340 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1341 bundle.putBoolean(key, false);
1342 } else {
1343 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1344 return null;
1345 }
1346 break;
1347 }
1348 case DOUBLE: {
1349 try {
1350 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1351 } catch (NumberFormatException nfe) {
1352 // Not a valid double
1353 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1354 return null;
1355 }
1356 break;
1357 }
1358 case DOUBLE_ARRAY: {
1359 double[] valueDoubleArray = null;
1360 if (valueList.size() > 0) {
1361 valueDoubleArray = new double[valueList.size()];
1362 for (int i = 0; i < valueList.size(); i++) {
1363 try {
1364 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1365 } catch (NumberFormatException nfe) {
1366 // Not a valid double
1367 errPw.println(
1368 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1369 return null;
1370 }
1371 }
1372 }
1373 bundle.putDoubleArray(key, valueDoubleArray);
1374 break;
1375 }
1376 case INT: {
1377 try {
1378 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1379 } catch (NumberFormatException nfe) {
1380 // Not a valid integer
1381 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1382 return null;
1383 }
1384 break;
1385 }
1386 case INT_ARRAY: {
1387 int[] valueIntArray = null;
1388 if (valueList.size() > 0) {
1389 valueIntArray = new int[valueList.size()];
1390 for (int i = 0; i < valueList.size(); i++) {
1391 try {
1392 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1393 } catch (NumberFormatException nfe) {
1394 // Not a valid integer
1395 errPw.println(tag
1396 + "Unable to parse " + valueList.get(i) + " as an integer.");
1397 return null;
1398 }
1399 }
1400 }
1401 bundle.putIntArray(key, valueIntArray);
1402 break;
1403 }
1404 case LONG: {
1405 try {
1406 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1407 } catch (NumberFormatException nfe) {
1408 // Not a valid long
1409 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1410 return null;
1411 }
1412 break;
1413 }
1414 case LONG_ARRAY: {
1415 long[] valueLongArray = null;
1416 if (valueList.size() > 0) {
1417 valueLongArray = new long[valueList.size()];
1418 for (int i = 0; i < valueList.size(); i++) {
1419 try {
1420 valueLongArray[i] = Long.parseLong(valueList.get(i));
1421 } catch (NumberFormatException nfe) {
1422 // Not a valid long
1423 errPw.println(
1424 tag + "Unable to parse " + valueList.get(i) + " as a long");
1425 return null;
1426 }
1427 }
1428 }
1429 bundle.putLongArray(key, valueLongArray);
1430 break;
1431 }
1432 case STRING: {
1433 String value = null;
1434 if (valueList.size() > 0) {
1435 value = valueList.get(0);
1436 }
1437 bundle.putString(key, value);
1438 break;
1439 }
1440 case STRING_ARRAY: {
1441 String[] valueStringArray = null;
1442 if (valueList.size() > 0) {
1443 valueStringArray = new String[valueList.size()];
1444 valueList.toArray(valueStringArray);
1445 }
1446 bundle.putStringArray(key, valueStringArray);
1447 break;
1448 }
1449 }
1450 return bundle;
1451 }
Shuo Qian489d9282020-07-09 11:30:03 -07001452
1453 private int handleEndBlockSuppressionCommand() {
1454 if (!checkShellUid()) {
1455 return -1;
1456 }
1457
1458 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1459 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1460 }
1461 return 0;
1462 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001463
Michele Berionne38c1afa2020-12-28 20:23:16 +00001464 private int handleRestartModemCommand() {
1465 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1466 // non user build.
1467 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1468 getErrPrintWriter().println("RestartModem: Permission denied.");
1469 return -1;
1470 }
1471
1472 boolean result = TelephonyManager.getDefault().rebootRadio();
1473 getOutPrintWriter().println(result);
1474
1475 return result ? 0 : -1;
1476 }
1477
Michele Berionned9fbae52020-11-13 02:36:59 +00001478 private int handleUnattendedReboot() {
1479 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1480 // non user build.
1481 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1482 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1483 return -1;
1484 }
1485
1486 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1487 getOutPrintWriter().println("result: " + result);
1488
1489 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1490 }
1491
Hui Wang0866fcc2020-10-12 12:14:23 -07001492 private int handleGbaCommand() {
1493 String arg = getNextArg();
1494 if (arg == null) {
1495 onHelpGba();
1496 return 0;
1497 }
1498
1499 switch (arg) {
1500 case GBA_SET_SERVICE: {
1501 return handleGbaSetServiceCommand();
1502 }
1503 case GBA_GET_SERVICE: {
1504 return handleGbaGetServiceCommand();
1505 }
1506 case GBA_SET_RELEASE_TIME: {
1507 return handleGbaSetReleaseCommand();
1508 }
1509 case GBA_GET_RELEASE_TIME: {
1510 return handleGbaGetReleaseCommand();
1511 }
1512 }
1513
1514 return -1;
1515 }
1516
1517 private int getSubId(String cmd) {
1518 int slotId = getDefaultSlot();
1519 String opt = getNextOption();
1520 if (opt != null && opt.equals("-s")) {
1521 try {
1522 slotId = Integer.parseInt(getNextArgRequired());
1523 } catch (NumberFormatException e) {
1524 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1525 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1526 }
1527 }
1528 int[] subIds = SubscriptionManager.getSubId(slotId);
1529 return subIds[0];
1530 }
1531
1532 private int handleGbaSetServiceCommand() {
1533 int subId = getSubId("gba set-service");
1534 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1535 return -1;
1536 }
1537
1538 String packageName = getNextArg();
1539 try {
1540 if (packageName == null) {
1541 packageName = "";
1542 }
1543 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1544 if (VDBG) {
1545 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1546 + packageName + ", result=" + result);
1547 }
1548 getOutPrintWriter().println(result);
1549 } catch (RemoteException e) {
1550 Log.w(LOG_TAG, "gba set-service " + subId + " "
1551 + packageName + ", error" + e.getMessage());
1552 getErrPrintWriter().println("Exception: " + e.getMessage());
1553 return -1;
1554 }
1555 return 0;
1556 }
1557
1558 private int handleGbaGetServiceCommand() {
1559 String result;
1560
1561 int subId = getSubId("gba get-service");
1562 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1563 return -1;
1564 }
1565
1566 try {
1567 result = mInterface.getBoundGbaService(subId);
1568 } catch (RemoteException e) {
1569 return -1;
1570 }
1571 if (VDBG) {
1572 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1573 }
1574 getOutPrintWriter().println(result);
1575 return 0;
1576 }
1577
1578 private int handleGbaSetReleaseCommand() {
1579 //the release time value could be -1
1580 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1581 : SubscriptionManager.getDefaultSubscriptionId();
1582 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1583 return -1;
1584 }
1585
1586 String intervalStr = getNextArg();
1587 if (intervalStr == null) {
1588 return -1;
1589 }
1590
1591 try {
1592 int interval = Integer.parseInt(intervalStr);
1593 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1594 if (VDBG) {
1595 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1596 + intervalStr + ", result=" + result);
1597 }
1598 getOutPrintWriter().println(result);
1599 } catch (NumberFormatException | RemoteException e) {
1600 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1601 + intervalStr + ", error" + e.getMessage());
1602 getErrPrintWriter().println("Exception: " + e.getMessage());
1603 return -1;
1604 }
1605 return 0;
1606 }
1607
1608 private int handleGbaGetReleaseCommand() {
1609 int subId = getSubId("gba get-release");
1610 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1611 return -1;
1612 }
1613
1614 int result = 0;
1615 try {
1616 result = mInterface.getGbaReleaseTime(subId);
1617 } catch (RemoteException e) {
1618 return -1;
1619 }
1620 if (VDBG) {
1621 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1622 }
1623 getOutPrintWriter().println(result);
1624 return 0;
1625 }
Hui Wang068ab862020-10-31 05:12:53 +00001626
1627 private int handleSingleRegistrationConfigCommand() {
1628 String arg = getNextArg();
1629 if (arg == null) {
1630 onHelpSrc();
1631 return 0;
1632 }
1633
1634 switch (arg) {
Hui Wang19a21872021-02-19 20:45:36 -08001635 case SRC_SET_TEST_ENABLED: {
1636 return handleSrcSetTestEnabledCommand();
1637 }
1638 case SRC_GET_TEST_ENABLED: {
1639 return handleSrcGetTestEnabledCommand();
1640 }
Hui Wang068ab862020-10-31 05:12:53 +00001641 case SRC_SET_DEVICE_ENABLED: {
1642 return handleSrcSetDeviceEnabledCommand();
1643 }
1644 case SRC_GET_DEVICE_ENABLED: {
1645 return handleSrcGetDeviceEnabledCommand();
1646 }
1647 case SRC_SET_CARRIER_ENABLED: {
1648 return handleSrcSetCarrierEnabledCommand();
1649 }
1650 case SRC_GET_CARRIER_ENABLED: {
1651 return handleSrcGetCarrierEnabledCommand();
1652 }
1653 }
1654
1655 return -1;
1656 }
1657
James.cf Linbcdf8b32021-01-14 16:44:13 +08001658 private int handleRcsUceCommand() {
1659 String arg = getNextArg();
1660 if (arg == null) {
1661 Log.w(LOG_TAG, "cannot get uce parameter");
1662 return -1;
1663 }
1664
1665 switch (arg) {
1666 case UCE_REMOVE_EAB_CONTACT:
1667 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001668 case UCE_GET_EAB_CONTACT:
1669 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001670 case UCE_GET_DEVICE_ENABLED:
1671 return handleUceGetDeviceEnabledCommand();
1672 case UCE_SET_DEVICE_ENABLED:
1673 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001674 }
1675 return -1;
1676 }
1677
1678 private int handleRemovingEabContactCommand() {
1679 int subId = getSubId("uce remove-eab-contact");
1680 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1681 return -1;
1682 }
1683
1684 String phoneNumber = getNextArgRequired();
1685 if (TextUtils.isEmpty(phoneNumber)) {
1686 return -1;
1687 }
1688 int result = 0;
1689 try {
1690 result = mInterface.removeContactFromEab(subId, phoneNumber);
1691 } catch (RemoteException e) {
1692 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1693 getErrPrintWriter().println("Exception: " + e.getMessage());
1694 return -1;
1695 }
1696
1697 if (VDBG) {
1698 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1699 }
calvinpan293ea1b2021-02-04 17:52:13 +08001700 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001701 }
1702
calvinpane4a8a1d2021-01-25 13:51:18 +08001703 private int handleGettingEabContactCommand() {
1704 String phoneNumber = getNextArgRequired();
1705 if (TextUtils.isEmpty(phoneNumber)) {
1706 return -1;
1707 }
1708 String result = "";
1709 try {
1710 result = mInterface.getContactFromEab(phoneNumber);
1711
1712 } catch (RemoteException e) {
1713 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1714 getErrPrintWriter().println("Exception: " + e.getMessage());
1715 return -1;
1716 }
1717
1718 if (VDBG) {
1719 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1720 }
calvinpan293ea1b2021-02-04 17:52:13 +08001721 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001722 return 0;
1723 }
1724
1725 private int handleUceGetDeviceEnabledCommand() {
1726 boolean result = false;
1727 try {
1728 result = mInterface.getDeviceUceEnabled();
1729 } catch (RemoteException e) {
1730 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1731 return -1;
1732 }
1733 if (VDBG) {
1734 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1735 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001736 getOutPrintWriter().println(result);
1737 return 0;
1738 }
1739
James.cf Lin4b784aa2021-01-31 03:25:15 +08001740 private int handleUceSetDeviceEnabledCommand() {
1741 String enabledStr = getNextArg();
1742 if (TextUtils.isEmpty(enabledStr)) {
1743 return -1;
1744 }
1745
1746 try {
1747 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1748 mInterface.setDeviceUceEnabled(isEnabled);
1749 if (VDBG) {
1750 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1751 }
1752 } catch (NumberFormatException | RemoteException e) {
1753 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1754 getErrPrintWriter().println("Exception: " + e.getMessage());
1755 return -1;
1756 }
1757 return 0;
1758 }
1759
Hui Wang19a21872021-02-19 20:45:36 -08001760 private int handleSrcSetTestEnabledCommand() {
1761 String enabledStr = getNextArg();
1762 if (enabledStr == null) {
1763 return -1;
1764 }
1765
1766 try {
1767 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1768 if (VDBG) {
1769 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1770 }
1771 getOutPrintWriter().println("Done");
1772 } catch (NumberFormatException | RemoteException e) {
1773 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1774 getErrPrintWriter().println("Exception: " + e.getMessage());
1775 return -1;
1776 }
1777 return 0;
1778 }
1779
1780 private int handleSrcGetTestEnabledCommand() {
1781 boolean result = false;
1782 try {
1783 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1784 } catch (RemoteException e) {
1785 return -1;
1786 }
1787 if (VDBG) {
1788 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1789 }
1790 getOutPrintWriter().println(result);
1791 return 0;
1792 }
1793
Hui Wang068ab862020-10-31 05:12:53 +00001794 private int handleSrcSetDeviceEnabledCommand() {
1795 String enabledStr = getNextArg();
1796 if (enabledStr == null) {
1797 return -1;
1798 }
1799
1800 try {
1801 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1802 if (VDBG) {
1803 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1804 }
1805 getOutPrintWriter().println("Done");
1806 } catch (NumberFormatException | RemoteException e) {
1807 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1808 getErrPrintWriter().println("Exception: " + e.getMessage());
1809 return -1;
1810 }
1811 return 0;
1812 }
1813
1814 private int handleSrcGetDeviceEnabledCommand() {
1815 boolean result = false;
1816 try {
1817 result = mInterface.getDeviceSingleRegistrationEnabled();
1818 } catch (RemoteException e) {
1819 return -1;
1820 }
1821 if (VDBG) {
1822 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1823 }
1824 getOutPrintWriter().println(result);
1825 return 0;
1826 }
1827
1828 private int handleSrcSetCarrierEnabledCommand() {
1829 //the release time value could be -1
1830 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1831 : SubscriptionManager.getDefaultSubscriptionId();
1832 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1833 return -1;
1834 }
1835
1836 String enabledStr = getNextArg();
1837 if (enabledStr == null) {
1838 return -1;
1839 }
1840
1841 try {
1842 boolean result =
1843 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1844 if (VDBG) {
1845 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1846 + enabledStr + ", result=" + result);
1847 }
1848 getOutPrintWriter().println(result);
1849 } catch (NumberFormatException | RemoteException e) {
1850 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1851 + enabledStr + ", error" + e.getMessage());
1852 getErrPrintWriter().println("Exception: " + e.getMessage());
1853 return -1;
1854 }
1855 return 0;
1856 }
1857
1858 private int handleSrcGetCarrierEnabledCommand() {
1859 int subId = getSubId("src get-carrier-enabled");
1860 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1861 return -1;
1862 }
1863
1864 boolean result = false;
1865 try {
1866 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1867 } catch (RemoteException e) {
1868 return -1;
1869 }
1870 if (VDBG) {
1871 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1872 }
1873 getOutPrintWriter().println(result);
1874 return 0;
1875 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -08001876
1877 private int handleHasCarrierPrivilegesCommand() {
1878 String packageName = getNextArgRequired();
1879
1880 boolean hasCarrierPrivileges;
1881 try {
1882 hasCarrierPrivileges =
1883 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
1884 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
1885 } catch (RemoteException e) {
1886 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
1887 getErrPrintWriter().println("Exception: " + e.getMessage());
1888 return -1;
1889 }
1890
1891 getOutPrintWriter().println(hasCarrierPrivileges);
1892 return 0;
1893 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001894}