blob: 07de4431cbd09ba52beb69fad8502700c131b236 [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";
Shuo Qian479dd9e2021-02-22 18:32:21 -080068 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080069 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070070 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne38c1afa2020-12-28 20:23:16 +000071 private static final String RESTART_MODEM = "restart-modem";
Michele Berionned9fbae52020-11-13 02:36:59 +000072 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010073 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080074 private static final String DATA_TEST_MODE = "data";
75 private static final String DATA_ENABLE = "enable";
76 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080077
Brad Ebinger999d3302020-11-25 14:31:39 -080078 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
79 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
80 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070081 private static final String IMS_ENABLE = "enable";
82 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070083 // Used to disable or enable processing of conference event package data from the network.
84 // This is handy for testing scenarios where CEP data does not exist on a network which does
85 // support CEP data.
86 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070087
Hall Liud892bec2018-11-30 14:51:45 -080088 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080089 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080090
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010091 private static final String CC_GET_VALUE = "get-value";
92 private static final String CC_SET_VALUE = "set-value";
93 private static final String CC_CLEAR_VALUES = "clear-values";
94
Hui Wang0866fcc2020-10-12 12:14:23 -070095 private static final String GBA_SUBCOMMAND = "gba";
96 private static final String GBA_SET_SERVICE = "set-service";
97 private static final String GBA_GET_SERVICE = "get-service";
98 private static final String GBA_SET_RELEASE_TIME = "set-release";
99 private static final String GBA_GET_RELEASE_TIME = "get-release";
100
Hui Wang068ab862020-10-31 05:12:53 +0000101 private static final String SINGLE_REGISTATION_CONFIG = "src";
102 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
103 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
104 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
105 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wang19a21872021-02-19 20:45:36 -0800106 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
107 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wang068ab862020-10-31 05:12:53 +0000108
Tyler Gunn92479152021-01-20 16:30:10 -0800109 private static final String D2D_SUBCOMMAND = "d2d";
110 private static final String D2D_SEND = "send";
111
James.cf Linbcdf8b32021-01-14 16:44:13 +0800112 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800113 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800114 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800115 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
116 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800117
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800118 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
119 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
120
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700121 // Take advantage of existing methods that already contain permissions checks when possible.
122 private final ITelephony mInterface;
123
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100124 private SubscriptionManager mSubscriptionManager;
125 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700126 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127
128 private enum CcType {
129 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
130 STRING_ARRAY, UNKNOWN
131 }
132
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100133 private class CcOptionParseResult {
134 public int mSubId;
135 public boolean mPersistent;
136 }
137
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100138 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
139 // keys by looking at the end of the string which usually tells the type.
140 // For instance: "xxxx_string", "xxxx_string_array", etc.
141 // The carrier config keys in this map does not follow this convention. It is therefore not
142 // possible to infer the type for these keys by looking at the string.
143 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
144 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
146 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
147 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
148 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
149 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
150 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
151 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
152 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
153 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
154 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
155 CcType.STRING);
156 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
157 CcType.STRING_ARRAY);
158 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
159 CcType.STRING_ARRAY);
160 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
161 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
162 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
163 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
164 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
165 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
166 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
167 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
168 }
169 };
170
171 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700172 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100173 mCarrierConfigManager =
174 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
175 mSubscriptionManager = (SubscriptionManager)
176 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700177 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700178 }
179
180 @Override
181 public int onCommand(String cmd) {
182 if (cmd == null) {
183 return handleDefaultCommands(null);
184 }
185
186 switch (cmd) {
187 case IMS_SUBCOMMAND: {
188 return handleImsCommand();
189 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800190 case RCS_UCE_COMMAND:
191 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800192 case NUMBER_VERIFICATION_SUBCOMMAND:
193 return handleNumberVerificationCommand();
Shuo Qian479dd9e2021-02-22 18:32:21 -0800194 case EMERGENCY_CALLBACK_MODE:
195 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800196 case EMERGENCY_NUMBER_TEST_MODE:
197 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100198 case CARRIER_CONFIG_SUBCOMMAND: {
199 return handleCcCommand();
200 }
Shuo Qianf5125122019-12-16 17:03:07 -0800201 case DATA_TEST_MODE:
202 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700203 case END_BLOCK_SUPPRESSION:
204 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700205 case GBA_SUBCOMMAND:
206 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800207 case D2D_SUBCOMMAND:
208 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000209 case SINGLE_REGISTATION_CONFIG:
210 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000211 case RESTART_MODEM:
212 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000213 case UNATTENDED_REBOOT:
214 return handleUnattendedReboot();
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800215 case HAS_CARRIER_PRIVILEGES_COMMAND:
216 return handleHasCarrierPrivilegesCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700217 default: {
218 return handleDefaultCommands(cmd);
219 }
220 }
221 }
222
223 @Override
224 public void onHelp() {
225 PrintWriter pw = getOutPrintWriter();
226 pw.println("Telephony Commands:");
227 pw.println(" help");
228 pw.println(" Print this help text.");
229 pw.println(" ims");
230 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800231 pw.println(" uce");
232 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800233 pw.println(" emergency-number-test-mode");
234 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700235 pw.println(" end-block-suppression");
236 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800237 pw.println(" data");
238 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100239 pw.println(" cc");
240 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700241 pw.println(" gba");
242 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000243 pw.println(" src");
244 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000245 pw.println(" restart-modem");
246 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000247 pw.println(" unattended-reboot");
248 pw.println(" Prepare for unattended reboot.");
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800249 pw.println(" has-carrier-privileges [package]");
250 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700251 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800252 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800253 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700254 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800255 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100256 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700257 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000258 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800259 onHelpD2D();
260 }
261
262 private void onHelpD2D() {
263 PrintWriter pw = getOutPrintWriter();
264 pw.println("D2D Comms Commands:");
265 pw.println(" d2d send TYPE VALUE");
266 pw.println(" Sends a D2D message of specified type and value.");
267 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
268 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
269 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
270 MESSAGE_CALL_AUDIO_CODEC));
271 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
272 + Communicator.messageToString(
273 MESSAGE_DEVICE_BATTERY_STATE));
274 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
275 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700276 }
277
278 private void onHelpIms() {
279 PrintWriter pw = getOutPrintWriter();
280 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800281 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700282 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
283 pw.println(" ImsService. Options are:");
284 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
285 pw.println(" is specified, it will choose the default voice SIM slot.");
286 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
287 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800288 pw.println(" -f: Set the feature that this override if for, if no option is");
289 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700290 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
291 pw.println(" Gets the package name of the currently defined ImsService.");
292 pw.println(" Options are:");
293 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
294 pw.println(" is specified, it will choose the default voice SIM slot.");
295 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000296 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800297 pw.println(" -f: The feature type that the query will be requested for. If none is");
298 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800299 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
300 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
301 pw.println(" configuration overrides. Options are:");
302 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
303 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700304 pw.println(" ims enable [-s SLOT_ID]");
305 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
306 pw.println(" if none is specified.");
307 pw.println(" ims disable [-s SLOT_ID]");
308 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
309 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700310 pw.println(" ims conference-event-package [enable/disable]");
311 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700312 }
313
James.cf Linbcdf8b32021-01-14 16:44:13 +0800314 private void onHelpUce() {
315 PrintWriter pw = getOutPrintWriter();
316 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800317 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
318 pw.println(" Get the EAB contacts from the EAB database.");
319 pw.println(" Options are:");
320 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
321 pw.println(" Expected output format :");
322 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800323 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
324 pw.println(" Remove the EAB contacts from the EAB database.");
325 pw.println(" Options are:");
326 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
327 pw.println(" is specified, it will choose the default voice SIM slot.");
328 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800329 pw.println(" uce get-device-enabled");
330 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
331 pw.println(" uce set-device-enabled true|false");
332 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
333 pw.println(" The value could be true, false.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800334 }
335
Hall Liud892bec2018-11-30 14:51:45 -0800336 private void onHelpNumberVerification() {
337 PrintWriter pw = getOutPrintWriter();
338 pw.println("Number verification commands");
339 pw.println(" numverify override-package PACKAGE_NAME;");
340 pw.println(" Set the authorized package for number verification.");
341 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800342 pw.println(" numverify fake-call NUMBER;");
343 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
344 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800345 }
346
Shuo Qianf5125122019-12-16 17:03:07 -0800347 private void onHelpDataTestMode() {
348 PrintWriter pw = getOutPrintWriter();
349 pw.println("Mobile Data Test Mode Commands:");
350 pw.println(" data enable: enable mobile data connectivity");
351 pw.println(" data disable: disable mobile data connectivity");
352 }
353
sqian9d4df8b2019-01-15 18:32:07 -0800354 private void onHelpEmergencyNumber() {
355 PrintWriter pw = getOutPrintWriter();
356 pw.println("Emergency Number Test Mode Commands:");
357 pw.println(" emergency-number-test-mode ");
358 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
359 + " the test mode");
360 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700361 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800362 pw.println(" -c: clear the emergency number list in the test mode.");
363 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700364 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800365 pw.println(" -p: get the full emergency number list in the test mode.");
366 }
367
Shuo Qian489d9282020-07-09 11:30:03 -0700368 private void onHelpEndBlockSupperssion() {
369 PrintWriter pw = getOutPrintWriter();
370 pw.println("End Block Suppression command:");
371 pw.println(" end-block-suppression: disable suppressing blocking by contact");
372 pw.println(" with emergency services.");
373 }
374
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100375 private void onHelpCc() {
376 PrintWriter pw = getOutPrintWriter();
377 pw.println("Carrier Config Commands:");
378 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
379 pw.println(" Print carrier config values.");
380 pw.println(" Options are:");
381 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
382 pw.println(" is specified, it will choose the default voice SIM slot.");
383 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
384 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100385 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100386 pw.println(" Set carrier config KEY to NEW_VALUE.");
387 pw.println(" Options are:");
388 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
389 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100390 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100391 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
392 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
393 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
394 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
395 pw.println(" cc clear-values [-s SLOT_ID]");
396 pw.println(" Clear all carrier override values that has previously been set");
397 pw.println(" with set-value");
398 pw.println(" Options are:");
399 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
400 pw.println(" is specified, it will choose the default voice SIM slot.");
401 }
402
Hui Wang0866fcc2020-10-12 12:14:23 -0700403 private void onHelpGba() {
404 PrintWriter pw = getOutPrintWriter();
405 pw.println("Gba Commands:");
406 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
407 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
408 pw.println(" Options are:");
409 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
410 pw.println(" is specified, it will choose the default voice SIM slot.");
411 pw.println(" gba get-service [-s SLOT_ID]");
412 pw.println(" Gets the package name of the currently defined GbaService.");
413 pw.println(" Options are:");
414 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
415 pw.println(" is specified, it will choose the default voice SIM slot.");
416 pw.println(" gba set-release [-s SLOT_ID] n");
417 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
418 pw.println(" Do not release/unbind if n is -1.");
419 pw.println(" Options are:");
420 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
421 pw.println(" is specified, it will choose the default voice SIM slot.");
422 pw.println(" gba get-release [-s SLOT_ID]");
423 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
424 pw.println(" Options are:");
425 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
426 pw.println(" is specified, it will choose the default voice SIM slot.");
427 }
428
Hui Wang068ab862020-10-31 05:12:53 +0000429 private void onHelpSrc() {
430 PrintWriter pw = getOutPrintWriter();
431 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wang19a21872021-02-19 20:45:36 -0800432 pw.println(" src set-test-enabled true|false");
433 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
434 pw.println(" The value could be true, false, or null(undefined).");
435 pw.println(" src get-test-enabled");
436 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang068ab862020-10-31 05:12:53 +0000437 pw.println(" src set-device-enabled true|false|null");
438 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
439 pw.println(" The value could be true, false, or null(undefined).");
440 pw.println(" src get-device-enabled");
441 pw.println(" Gets the device config for RCS VoLTE single registration.");
442 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
443 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
444 pw.println(" The value could be true, false, or null(undefined).");
445 pw.println(" Options are:");
446 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
447 pw.println(" is specified, it will choose the default voice SIM slot.");
448 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
449 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
450 pw.println(" Options are:");
451 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
452 pw.println(" is specified, it will choose the default voice SIM slot.");
453 }
454
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700455 private int handleImsCommand() {
456 String arg = getNextArg();
457 if (arg == null) {
458 onHelpIms();
459 return 0;
460 }
461
462 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800463 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700464 return handleImsSetServiceCommand();
465 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800466 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700467 return handleImsGetServiceCommand();
468 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800469 case IMS_CLEAR_SERVICE_OVERRIDE: {
470 return handleImsClearCarrierServiceCommand();
471 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700472 case IMS_ENABLE: {
473 return handleEnableIms();
474 }
475 case IMS_DISABLE: {
476 return handleDisableIms();
477 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700478 case IMS_CEP: {
479 return handleCepChange();
480 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700481 }
482
483 return -1;
484 }
485
Shuo Qianf5125122019-12-16 17:03:07 -0800486 private int handleDataTestModeCommand() {
487 PrintWriter errPw = getErrPrintWriter();
488 String arg = getNextArgRequired();
489 if (arg == null) {
490 onHelpDataTestMode();
491 return 0;
492 }
493 switch (arg) {
494 case DATA_ENABLE: {
495 try {
496 mInterface.enableDataConnectivity();
497 } catch (RemoteException ex) {
498 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
499 errPw.println("Exception: " + ex.getMessage());
500 return -1;
501 }
502 break;
503 }
504 case DATA_DISABLE: {
505 try {
506 mInterface.disableDataConnectivity();
507 } catch (RemoteException ex) {
508 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
509 errPw.println("Exception: " + ex.getMessage());
510 return -1;
511 }
512 break;
513 }
514 default:
515 onHelpDataTestMode();
516 break;
517 }
518 return 0;
519 }
520
Shuo Qian479dd9e2021-02-22 18:32:21 -0800521 private int handleEmergencyCallbackModeCommand() {
522 PrintWriter errPw = getErrPrintWriter();
523 try {
524 mInterface.startEmergencyCallbackMode();
525 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
526 } catch (RemoteException ex) {
527 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
528 errPw.println("Exception: " + ex.getMessage());
529 return -1;
530 }
531 return 0;
532 }
533
sqian9d4df8b2019-01-15 18:32:07 -0800534 private int handleEmergencyNumberTestModeCommand() {
535 PrintWriter errPw = getErrPrintWriter();
536 String opt = getNextOption();
537 if (opt == null) {
538 onHelpEmergencyNumber();
539 return 0;
540 }
541
542 switch (opt) {
543 case "-a": {
544 String emergencyNumberCmd = getNextArgRequired();
545 if (emergencyNumberCmd == null
546 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700547 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800548 + " to be specified after -a in the command ");
549 return -1;
550 }
551 try {
552 mInterface.updateEmergencyNumberListTestMode(
553 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
554 new EmergencyNumber(emergencyNumberCmd, "", "",
555 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
556 new ArrayList<String>(),
557 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
558 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
559 } catch (RemoteException ex) {
560 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
561 + ", error " + ex.getMessage());
562 errPw.println("Exception: " + ex.getMessage());
563 return -1;
564 }
565 break;
566 }
567 case "-c": {
568 try {
569 mInterface.updateEmergencyNumberListTestMode(
570 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
571 } catch (RemoteException ex) {
572 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
573 errPw.println("Exception: " + ex.getMessage());
574 return -1;
575 }
576 break;
577 }
578 case "-r": {
579 String emergencyNumberCmd = getNextArgRequired();
580 if (emergencyNumberCmd == null
581 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700582 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800583 + " to be specified after -r in the command ");
584 return -1;
585 }
586 try {
587 mInterface.updateEmergencyNumberListTestMode(
588 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
589 new EmergencyNumber(emergencyNumberCmd, "", "",
590 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
591 new ArrayList<String>(),
592 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
593 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
594 } catch (RemoteException ex) {
595 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
596 + ", error " + ex.getMessage());
597 errPw.println("Exception: " + ex.getMessage());
598 return -1;
599 }
600 break;
601 }
602 case "-p": {
603 try {
604 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
605 } catch (RemoteException ex) {
606 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
607 errPw.println("Exception: " + ex.getMessage());
608 return -1;
609 }
610 break;
611 }
612 default:
613 onHelpEmergencyNumber();
614 break;
615 }
616 return 0;
617 }
618
Hall Liud892bec2018-11-30 14:51:45 -0800619 private int handleNumberVerificationCommand() {
620 String arg = getNextArg();
621 if (arg == null) {
622 onHelpNumberVerification();
623 return 0;
624 }
625
Hall Liuca5af3a2018-12-04 16:58:23 -0800626 if (!checkShellUid()) {
627 return -1;
628 }
629
Hall Liud892bec2018-11-30 14:51:45 -0800630 switch (arg) {
631 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800632 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
633 return 0;
634 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800635 case NUMBER_VERIFICATION_FAKE_CALL: {
636 boolean val = NumberVerificationManager.getInstance()
637 .checkIncomingCall(getNextArg());
638 getOutPrintWriter().println(val ? "1" : "0");
639 return 0;
640 }
Hall Liud892bec2018-11-30 14:51:45 -0800641 }
642
643 return -1;
644 }
645
Tyler Gunn92479152021-01-20 16:30:10 -0800646 private int handleD2dCommand() {
647 String arg = getNextArg();
648 if (arg == null) {
649 onHelpD2D();
650 return 0;
651 }
652
653 switch (arg) {
654 case D2D_SEND: {
655 return handleD2dSendCommand();
656 }
657 }
658
659 return -1;
660 }
661
662 private int handleD2dSendCommand() {
663 PrintWriter errPw = getErrPrintWriter();
664 String opt;
665 int messageType = -1;
666 int messageValue = -1;
667
668
669 String arg = getNextArg();
670 if (arg == null) {
671 onHelpD2D();
672 return 0;
673 }
674 try {
675 messageType = Integer.parseInt(arg);
676 } catch (NumberFormatException e) {
677 errPw.println("message type must be a valid integer");
678 return -1;
679 }
680
681 arg = getNextArg();
682 if (arg == null) {
683 onHelpD2D();
684 return 0;
685 }
686 try {
687 messageValue = Integer.parseInt(arg);
688 } catch (NumberFormatException e) {
689 errPw.println("message value must be a valid integer");
690 return -1;
691 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800692
Tyler Gunn92479152021-01-20 16:30:10 -0800693 try {
694 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
695 } catch (RemoteException e) {
696 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
697 errPw.println("Exception: " + e.getMessage());
698 return -1;
699 }
700
701 return 0;
702 }
703
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700704 // ims set-ims-service
705 private int handleImsSetServiceCommand() {
706 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700707 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700708 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800709 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700710
711 String opt;
712 while ((opt = getNextOption()) != null) {
713 switch (opt) {
714 case "-s": {
715 try {
716 slotId = Integer.parseInt(getNextArgRequired());
717 } catch (NumberFormatException e) {
718 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
719 return -1;
720 }
721 break;
722 }
723 case "-c": {
724 isCarrierService = true;
725 break;
726 }
727 case "-d": {
728 isCarrierService = false;
729 break;
730 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800731 case "-f": {
732 String featureString = getNextArgRequired();
733 String[] features = featureString.split(",");
734 for (int i = 0; i < features.length; i++) {
735 try {
736 Integer result = Integer.parseInt(features[i]);
737 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
738 || result >= ImsFeature.FEATURE_MAX) {
739 errPw.println("ims set-ims-service -f " + result
740 + " is an invalid feature.");
741 return -1;
742 }
743 featuresList.add(result);
744 } catch (NumberFormatException e) {
745 errPw.println("ims set-ims-service -f tried to parse " + features[i]
746 + " as an integer.");
747 return -1;
748 }
749 }
750 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700751 }
752 }
753 // Mandatory param, either -c or -d
754 if (isCarrierService == null) {
755 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
756 return -1;
757 }
758
759 String packageName = getNextArg();
760
761 try {
762 if (packageName == null) {
763 packageName = "";
764 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800765 int[] featureArray = new int[featuresList.size()];
766 for (int i = 0; i < featuresList.size(); i++) {
767 featureArray[i] = featuresList.get(i);
768 }
769 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
770 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700771 if (VDBG) {
772 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800773 + (isCarrierService ? "-c " : "-d ")
774 + "-f " + featuresList + " "
775 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700776 }
777 getOutPrintWriter().println(result);
778 } catch (RemoteException e) {
779 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800780 + (isCarrierService ? "-c " : "-d ")
781 + "-f " + featuresList + " "
782 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700783 errPw.println("Exception: " + e.getMessage());
784 return -1;
785 }
786 return 0;
787 }
788
Brad Ebinger999d3302020-11-25 14:31:39 -0800789 // ims clear-ims-service-override
790 private int handleImsClearCarrierServiceCommand() {
791 PrintWriter errPw = getErrPrintWriter();
792 int slotId = getDefaultSlot();
793
794 String opt;
795 while ((opt = getNextOption()) != null) {
796 switch (opt) {
797 case "-s": {
798 try {
799 slotId = Integer.parseInt(getNextArgRequired());
800 } catch (NumberFormatException e) {
801 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
802 return -1;
803 }
804 break;
805 }
806 }
807 }
808
809 try {
810 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
811 if (VDBG) {
812 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
813 + ", result=" + result);
814 }
815 getOutPrintWriter().println(result);
816 } catch (RemoteException e) {
817 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
818 + ", error" + e.getMessage());
819 errPw.println("Exception: " + e.getMessage());
820 return -1;
821 }
822 return 0;
823 }
824
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700825 // ims get-ims-service
826 private int handleImsGetServiceCommand() {
827 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700828 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700829 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800830 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700831
832 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 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
840 return -1;
841 }
842 break;
843 }
844 case "-c": {
845 isCarrierService = true;
846 break;
847 }
848 case "-d": {
849 isCarrierService = false;
850 break;
851 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800852 case "-f": {
853 try {
854 featureType = Integer.parseInt(getNextArg());
855 } catch (NumberFormatException e) {
856 errPw.println("ims get-ims-service -f requires valid integer as feature.");
857 return -1;
858 }
859 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
860 || featureType >= ImsFeature.FEATURE_MAX) {
861 errPw.println("ims get-ims-service -f invalid feature.");
862 return -1;
863 }
864 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700865 }
866 }
867 // Mandatory param, either -c or -d
868 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800869 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700870 return -1;
871 }
872
873 String result;
874 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800875 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700876 } catch (RemoteException e) {
877 return -1;
878 }
879 if (VDBG) {
880 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800881 + (isCarrierService ? "-c " : "-d ")
882 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
883 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700884 }
885 getOutPrintWriter().println(result);
886 return 0;
887 }
888
889 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700890 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700891 String opt;
892 while ((opt = getNextOption()) != null) {
893 switch (opt) {
894 case "-s": {
895 try {
896 slotId = Integer.parseInt(getNextArgRequired());
897 } catch (NumberFormatException e) {
898 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
899 return -1;
900 }
901 break;
902 }
903 }
904 }
905 try {
906 mInterface.enableIms(slotId);
907 } catch (RemoteException e) {
908 return -1;
909 }
910 if (VDBG) {
911 Log.v(LOG_TAG, "ims enable -s " + slotId);
912 }
913 return 0;
914 }
915
916 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700917 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700918 String opt;
919 while ((opt = getNextOption()) != null) {
920 switch (opt) {
921 case "-s": {
922 try {
923 slotId = Integer.parseInt(getNextArgRequired());
924 } catch (NumberFormatException e) {
925 getErrPrintWriter().println(
926 "ims disable requires an integer as a SLOT_ID.");
927 return -1;
928 }
929 break;
930 }
931 }
932 }
933 try {
934 mInterface.disableIms(slotId);
935 } catch (RemoteException e) {
936 return -1;
937 }
938 if (VDBG) {
939 Log.v(LOG_TAG, "ims disable -s " + slotId);
940 }
941 return 0;
942 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700943
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700944 private int handleCepChange() {
945 Log.i(LOG_TAG, "handleCepChange");
946 String opt = getNextArg();
947 if (opt == null) {
948 return -1;
949 }
950 boolean isCepEnabled = opt.equals("enable");
951
952 try {
953 mInterface.setCepEnabled(isCepEnabled);
954 } catch (RemoteException e) {
955 return -1;
956 }
957 return 0;
958 }
959
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700960 private int getDefaultSlot() {
961 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
962 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
963 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
964 // If there is no default, default to slot 0.
965 slotId = DEFAULT_PHONE_ID;
966 }
967 return slotId;
968 }
sqian2fff4a32018-11-05 14:18:37 -0800969
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100970 // Parse options related to Carrier Config Commands.
971 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100972 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100973 CcOptionParseResult result = new CcOptionParseResult();
974 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
975 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100976
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100977 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100978 while ((opt = getNextOption()) != null) {
979 switch (opt) {
980 case "-s": {
981 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100982 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
983 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
984 errPw.println(tag + "No valid subscription found.");
985 return null;
986 }
987
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100988 } catch (IllegalArgumentException e) {
989 // Missing slot id
990 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100991 return null;
992 }
993 break;
994 }
995 case "-p": {
996 if (allowOptionPersistent) {
997 result.mPersistent = true;
998 } else {
999 errPw.println(tag + "Unexpected option " + opt);
1000 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001001 }
1002 break;
1003 }
1004 default: {
1005 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001006 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001007 }
1008 }
1009 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001010 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001011 }
1012
1013 private int slotStringToSubId(String tag, String slotString) {
1014 int slotId = -1;
1015 try {
1016 slotId = Integer.parseInt(slotString);
1017 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001018 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1019 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1020 }
1021
1022 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001023 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1024 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1025 }
1026
Qiong Liuf25799b2020-09-10 10:13:46 +08001027 Phone phone = PhoneFactory.getPhone(slotId);
1028 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001029 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1030 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1031 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001032 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001033 }
1034
Hall Liud892bec2018-11-30 14:51:45 -08001035 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001036 // adb can run as root or as shell, depending on whether the device is rooted.
1037 return Binder.getCallingUid() == Process.SHELL_UID
1038 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001039 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001040
1041 private int handleCcCommand() {
1042 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1043 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001044 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001045 getErrPrintWriter().println("cc: Permission denied.");
1046 return -1;
1047 }
1048
1049 String arg = getNextArg();
1050 if (arg == null) {
1051 onHelpCc();
1052 return 0;
1053 }
1054
1055 switch (arg) {
1056 case CC_GET_VALUE: {
1057 return handleCcGetValue();
1058 }
1059 case CC_SET_VALUE: {
1060 return handleCcSetValue();
1061 }
1062 case CC_CLEAR_VALUES: {
1063 return handleCcClearValues();
1064 }
1065 default: {
1066 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1067 }
1068 }
1069 return -1;
1070 }
1071
1072 // cc get-value
1073 private int handleCcGetValue() {
1074 PrintWriter errPw = getErrPrintWriter();
1075 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1076 String key = null;
1077
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001078 // Parse all options
1079 CcOptionParseResult options = parseCcOptions(tag, false);
1080 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001081 return -1;
1082 }
1083
1084 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001085 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001086 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001087 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001088 return -1;
1089 }
1090
1091 // Get the key.
1092 key = getNextArg();
1093 if (key != null) {
1094 // A key was provided. Verify if it is a valid key
1095 if (!bundle.containsKey(key)) {
1096 errPw.println(tag + key + " is not a valid key.");
1097 return -1;
1098 }
1099
1100 // Print the carrier config value for key.
1101 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1102 } else {
1103 // No key provided. Show all values.
1104 // Iterate over a sorted list of all carrier config keys and print them.
1105 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1106 for (String k : sortedSet) {
1107 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1108 }
1109 }
1110 return 0;
1111 }
1112
1113 // cc set-value
1114 private int handleCcSetValue() {
1115 PrintWriter errPw = getErrPrintWriter();
1116 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1117
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001118 // Parse all options
1119 CcOptionParseResult options = parseCcOptions(tag, true);
1120 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001121 return -1;
1122 }
1123
1124 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001125 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001126 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001127 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001128 return -1;
1129 }
1130
1131 // Get the key.
1132 String key = getNextArg();
1133 if (key == null || key.equals("")) {
1134 errPw.println(tag + "KEY is missing");
1135 return -1;
1136 }
1137
1138 // Verify if the key is valid
1139 if (!originalValues.containsKey(key)) {
1140 errPw.println(tag + key + " is not a valid key.");
1141 return -1;
1142 }
1143
1144 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1145 ArrayList<String> valueList = new ArrayList<String>();
1146 while (peekNextArg() != null) {
1147 valueList.add(getNextArg());
1148 }
1149
1150 // Find the type of the carrier config value
1151 CcType type = getType(tag, key, originalValues);
1152 if (type == CcType.UNKNOWN) {
1153 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1154 return -1;
1155 }
1156
1157 // Create an override bundle containing the key and value that should be overriden.
1158 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1159 if (overrideBundle == null) {
1160 return -1;
1161 }
1162
1163 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001164 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001165
1166 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001167 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001168 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001169 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001170 return -1;
1171 }
1172
1173 // Print the original and new value.
1174 String originalValueString = ccValueToString(key, type, originalValues);
1175 String newValueString = ccValueToString(key, type, newValues);
1176 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1177 getOutPrintWriter().println("New value: \n" + newValueString);
1178
1179 return 0;
1180 }
1181
1182 // cc clear-values
1183 private int handleCcClearValues() {
1184 PrintWriter errPw = getErrPrintWriter();
1185 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1186
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001187 // Parse all options
1188 CcOptionParseResult options = parseCcOptions(tag, false);
1189 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001190 return -1;
1191 }
1192
1193 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001194 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001195 getOutPrintWriter()
1196 .println("All previously set carrier config override values has been cleared");
1197 return 0;
1198 }
1199
1200 private CcType getType(String tag, String key, PersistableBundle bundle) {
1201 // Find the type by checking the type of the current value stored in the bundle.
1202 Object value = bundle.get(key);
1203
1204 if (CC_TYPE_MAP.containsKey(key)) {
1205 return CC_TYPE_MAP.get(key);
1206 } else if (value != null) {
1207 if (value instanceof Boolean) {
1208 return CcType.BOOLEAN;
1209 } else if (value instanceof Double) {
1210 return CcType.DOUBLE;
1211 } else if (value instanceof double[]) {
1212 return CcType.DOUBLE_ARRAY;
1213 } else if (value instanceof Integer) {
1214 return CcType.INT;
1215 } else if (value instanceof int[]) {
1216 return CcType.INT_ARRAY;
1217 } else if (value instanceof Long) {
1218 return CcType.LONG;
1219 } else if (value instanceof long[]) {
1220 return CcType.LONG_ARRAY;
1221 } else if (value instanceof String) {
1222 return CcType.STRING;
1223 } else if (value instanceof String[]) {
1224 return CcType.STRING_ARRAY;
1225 }
1226 } else {
1227 // Current value was null and can therefore not be used in order to find the type.
1228 // Check the name of the key to infer the type. This check is not needed for primitive
1229 // data types (boolean, double, int and long), since they can not be null.
1230 if (key.endsWith("double_array")) {
1231 return CcType.DOUBLE_ARRAY;
1232 }
1233 if (key.endsWith("int_array")) {
1234 return CcType.INT_ARRAY;
1235 }
1236 if (key.endsWith("long_array")) {
1237 return CcType.LONG_ARRAY;
1238 }
1239 if (key.endsWith("string")) {
1240 return CcType.STRING;
1241 }
1242 if (key.endsWith("string_array") || key.endsWith("strings")) {
1243 return CcType.STRING_ARRAY;
1244 }
1245 }
1246
1247 // Not possible to infer the type by looking at the current value or the key.
1248 PrintWriter errPw = getErrPrintWriter();
1249 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1250 return CcType.UNKNOWN;
1251 }
1252
1253 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1254 String result;
1255 StringBuilder valueString = new StringBuilder();
1256 String typeString = type.toString();
1257 Object value = bundle.get(key);
1258
1259 if (value == null) {
1260 valueString.append("null");
1261 } else {
1262 switch (type) {
1263 case DOUBLE_ARRAY: {
1264 // Format the string representation of the int array as value1 value2......
1265 double[] valueArray = (double[]) value;
1266 for (int i = 0; i < valueArray.length; i++) {
1267 if (i != 0) {
1268 valueString.append(" ");
1269 }
1270 valueString.append(valueArray[i]);
1271 }
1272 break;
1273 }
1274 case INT_ARRAY: {
1275 // Format the string representation of the int array as value1 value2......
1276 int[] valueArray = (int[]) value;
1277 for (int i = 0; i < valueArray.length; i++) {
1278 if (i != 0) {
1279 valueString.append(" ");
1280 }
1281 valueString.append(valueArray[i]);
1282 }
1283 break;
1284 }
1285 case LONG_ARRAY: {
1286 // Format the string representation of the int array as value1 value2......
1287 long[] valueArray = (long[]) value;
1288 for (int i = 0; i < valueArray.length; i++) {
1289 if (i != 0) {
1290 valueString.append(" ");
1291 }
1292 valueString.append(valueArray[i]);
1293 }
1294 break;
1295 }
1296 case STRING: {
1297 valueString.append("\"" + value.toString() + "\"");
1298 break;
1299 }
1300 case STRING_ARRAY: {
1301 // Format the string representation of the string array as "value1" "value2"....
1302 String[] valueArray = (String[]) value;
1303 for (int i = 0; i < valueArray.length; i++) {
1304 if (i != 0) {
1305 valueString.append(" ");
1306 }
1307 if (valueArray[i] != null) {
1308 valueString.append("\"" + valueArray[i] + "\"");
1309 } else {
1310 valueString.append("null");
1311 }
1312 }
1313 break;
1314 }
1315 default: {
1316 valueString.append(value.toString());
1317 }
1318 }
1319 }
1320 return String.format("%-70s %-15s %s", key, typeString, valueString);
1321 }
1322
1323 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1324 ArrayList<String> valueList) {
1325 PrintWriter errPw = getErrPrintWriter();
1326 PersistableBundle bundle = new PersistableBundle();
1327
1328 // First verify that a valid number of values has been provided for the type.
1329 switch (type) {
1330 case BOOLEAN:
1331 case DOUBLE:
1332 case INT:
1333 case LONG: {
1334 if (valueList.size() != 1) {
1335 errPw.println(tag + "Expected 1 value for type " + type
1336 + ". Found: " + valueList.size());
1337 return null;
1338 }
1339 break;
1340 }
1341 case STRING: {
1342 if (valueList.size() > 1) {
1343 errPw.println(tag + "Expected 0 or 1 values for type " + type
1344 + ". Found: " + valueList.size());
1345 return null;
1346 }
1347 break;
1348 }
1349 }
1350
1351 // Parse the value according to type and add it to the Bundle.
1352 switch (type) {
1353 case BOOLEAN: {
1354 if ("true".equalsIgnoreCase(valueList.get(0))) {
1355 bundle.putBoolean(key, true);
1356 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1357 bundle.putBoolean(key, false);
1358 } else {
1359 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1360 return null;
1361 }
1362 break;
1363 }
1364 case DOUBLE: {
1365 try {
1366 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1367 } catch (NumberFormatException nfe) {
1368 // Not a valid double
1369 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1370 return null;
1371 }
1372 break;
1373 }
1374 case DOUBLE_ARRAY: {
1375 double[] valueDoubleArray = null;
1376 if (valueList.size() > 0) {
1377 valueDoubleArray = new double[valueList.size()];
1378 for (int i = 0; i < valueList.size(); i++) {
1379 try {
1380 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1381 } catch (NumberFormatException nfe) {
1382 // Not a valid double
1383 errPw.println(
1384 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1385 return null;
1386 }
1387 }
1388 }
1389 bundle.putDoubleArray(key, valueDoubleArray);
1390 break;
1391 }
1392 case INT: {
1393 try {
1394 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1395 } catch (NumberFormatException nfe) {
1396 // Not a valid integer
1397 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1398 return null;
1399 }
1400 break;
1401 }
1402 case INT_ARRAY: {
1403 int[] valueIntArray = null;
1404 if (valueList.size() > 0) {
1405 valueIntArray = new int[valueList.size()];
1406 for (int i = 0; i < valueList.size(); i++) {
1407 try {
1408 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1409 } catch (NumberFormatException nfe) {
1410 // Not a valid integer
1411 errPw.println(tag
1412 + "Unable to parse " + valueList.get(i) + " as an integer.");
1413 return null;
1414 }
1415 }
1416 }
1417 bundle.putIntArray(key, valueIntArray);
1418 break;
1419 }
1420 case LONG: {
1421 try {
1422 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1423 } catch (NumberFormatException nfe) {
1424 // Not a valid long
1425 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1426 return null;
1427 }
1428 break;
1429 }
1430 case LONG_ARRAY: {
1431 long[] valueLongArray = null;
1432 if (valueList.size() > 0) {
1433 valueLongArray = new long[valueList.size()];
1434 for (int i = 0; i < valueList.size(); i++) {
1435 try {
1436 valueLongArray[i] = Long.parseLong(valueList.get(i));
1437 } catch (NumberFormatException nfe) {
1438 // Not a valid long
1439 errPw.println(
1440 tag + "Unable to parse " + valueList.get(i) + " as a long");
1441 return null;
1442 }
1443 }
1444 }
1445 bundle.putLongArray(key, valueLongArray);
1446 break;
1447 }
1448 case STRING: {
1449 String value = null;
1450 if (valueList.size() > 0) {
1451 value = valueList.get(0);
1452 }
1453 bundle.putString(key, value);
1454 break;
1455 }
1456 case STRING_ARRAY: {
1457 String[] valueStringArray = null;
1458 if (valueList.size() > 0) {
1459 valueStringArray = new String[valueList.size()];
1460 valueList.toArray(valueStringArray);
1461 }
1462 bundle.putStringArray(key, valueStringArray);
1463 break;
1464 }
1465 }
1466 return bundle;
1467 }
Shuo Qian489d9282020-07-09 11:30:03 -07001468
1469 private int handleEndBlockSuppressionCommand() {
1470 if (!checkShellUid()) {
1471 return -1;
1472 }
1473
1474 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1475 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1476 }
1477 return 0;
1478 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001479
Michele Berionne38c1afa2020-12-28 20:23:16 +00001480 private int handleRestartModemCommand() {
1481 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1482 // non user build.
1483 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1484 getErrPrintWriter().println("RestartModem: Permission denied.");
1485 return -1;
1486 }
1487
1488 boolean result = TelephonyManager.getDefault().rebootRadio();
1489 getOutPrintWriter().println(result);
1490
1491 return result ? 0 : -1;
1492 }
1493
Michele Berionned9fbae52020-11-13 02:36:59 +00001494 private int handleUnattendedReboot() {
1495 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1496 // non user build.
1497 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1498 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1499 return -1;
1500 }
1501
1502 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1503 getOutPrintWriter().println("result: " + result);
1504
1505 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1506 }
1507
Hui Wang0866fcc2020-10-12 12:14:23 -07001508 private int handleGbaCommand() {
1509 String arg = getNextArg();
1510 if (arg == null) {
1511 onHelpGba();
1512 return 0;
1513 }
1514
1515 switch (arg) {
1516 case GBA_SET_SERVICE: {
1517 return handleGbaSetServiceCommand();
1518 }
1519 case GBA_GET_SERVICE: {
1520 return handleGbaGetServiceCommand();
1521 }
1522 case GBA_SET_RELEASE_TIME: {
1523 return handleGbaSetReleaseCommand();
1524 }
1525 case GBA_GET_RELEASE_TIME: {
1526 return handleGbaGetReleaseCommand();
1527 }
1528 }
1529
1530 return -1;
1531 }
1532
1533 private int getSubId(String cmd) {
1534 int slotId = getDefaultSlot();
1535 String opt = getNextOption();
1536 if (opt != null && opt.equals("-s")) {
1537 try {
1538 slotId = Integer.parseInt(getNextArgRequired());
1539 } catch (NumberFormatException e) {
1540 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1541 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1542 }
1543 }
1544 int[] subIds = SubscriptionManager.getSubId(slotId);
1545 return subIds[0];
1546 }
1547
1548 private int handleGbaSetServiceCommand() {
1549 int subId = getSubId("gba set-service");
1550 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1551 return -1;
1552 }
1553
1554 String packageName = getNextArg();
1555 try {
1556 if (packageName == null) {
1557 packageName = "";
1558 }
1559 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1560 if (VDBG) {
1561 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1562 + packageName + ", result=" + result);
1563 }
1564 getOutPrintWriter().println(result);
1565 } catch (RemoteException e) {
1566 Log.w(LOG_TAG, "gba set-service " + subId + " "
1567 + packageName + ", error" + e.getMessage());
1568 getErrPrintWriter().println("Exception: " + e.getMessage());
1569 return -1;
1570 }
1571 return 0;
1572 }
1573
1574 private int handleGbaGetServiceCommand() {
1575 String result;
1576
1577 int subId = getSubId("gba get-service");
1578 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1579 return -1;
1580 }
1581
1582 try {
1583 result = mInterface.getBoundGbaService(subId);
1584 } catch (RemoteException e) {
1585 return -1;
1586 }
1587 if (VDBG) {
1588 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1589 }
1590 getOutPrintWriter().println(result);
1591 return 0;
1592 }
1593
1594 private int handleGbaSetReleaseCommand() {
1595 //the release time value could be -1
1596 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1597 : SubscriptionManager.getDefaultSubscriptionId();
1598 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1599 return -1;
1600 }
1601
1602 String intervalStr = getNextArg();
1603 if (intervalStr == null) {
1604 return -1;
1605 }
1606
1607 try {
1608 int interval = Integer.parseInt(intervalStr);
1609 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1610 if (VDBG) {
1611 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1612 + intervalStr + ", result=" + result);
1613 }
1614 getOutPrintWriter().println(result);
1615 } catch (NumberFormatException | RemoteException e) {
1616 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1617 + intervalStr + ", error" + e.getMessage());
1618 getErrPrintWriter().println("Exception: " + e.getMessage());
1619 return -1;
1620 }
1621 return 0;
1622 }
1623
1624 private int handleGbaGetReleaseCommand() {
1625 int subId = getSubId("gba get-release");
1626 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1627 return -1;
1628 }
1629
1630 int result = 0;
1631 try {
1632 result = mInterface.getGbaReleaseTime(subId);
1633 } catch (RemoteException e) {
1634 return -1;
1635 }
1636 if (VDBG) {
1637 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1638 }
1639 getOutPrintWriter().println(result);
1640 return 0;
1641 }
Hui Wang068ab862020-10-31 05:12:53 +00001642
1643 private int handleSingleRegistrationConfigCommand() {
1644 String arg = getNextArg();
1645 if (arg == null) {
1646 onHelpSrc();
1647 return 0;
1648 }
1649
1650 switch (arg) {
Hui Wang19a21872021-02-19 20:45:36 -08001651 case SRC_SET_TEST_ENABLED: {
1652 return handleSrcSetTestEnabledCommand();
1653 }
1654 case SRC_GET_TEST_ENABLED: {
1655 return handleSrcGetTestEnabledCommand();
1656 }
Hui Wang068ab862020-10-31 05:12:53 +00001657 case SRC_SET_DEVICE_ENABLED: {
1658 return handleSrcSetDeviceEnabledCommand();
1659 }
1660 case SRC_GET_DEVICE_ENABLED: {
1661 return handleSrcGetDeviceEnabledCommand();
1662 }
1663 case SRC_SET_CARRIER_ENABLED: {
1664 return handleSrcSetCarrierEnabledCommand();
1665 }
1666 case SRC_GET_CARRIER_ENABLED: {
1667 return handleSrcGetCarrierEnabledCommand();
1668 }
1669 }
1670
1671 return -1;
1672 }
1673
James.cf Linbcdf8b32021-01-14 16:44:13 +08001674 private int handleRcsUceCommand() {
1675 String arg = getNextArg();
1676 if (arg == null) {
1677 Log.w(LOG_TAG, "cannot get uce parameter");
1678 return -1;
1679 }
1680
1681 switch (arg) {
1682 case UCE_REMOVE_EAB_CONTACT:
1683 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001684 case UCE_GET_EAB_CONTACT:
1685 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001686 case UCE_GET_DEVICE_ENABLED:
1687 return handleUceGetDeviceEnabledCommand();
1688 case UCE_SET_DEVICE_ENABLED:
1689 return handleUceSetDeviceEnabledCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001690 }
1691 return -1;
1692 }
1693
1694 private int handleRemovingEabContactCommand() {
1695 int subId = getSubId("uce remove-eab-contact");
1696 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1697 return -1;
1698 }
1699
1700 String phoneNumber = getNextArgRequired();
1701 if (TextUtils.isEmpty(phoneNumber)) {
1702 return -1;
1703 }
1704 int result = 0;
1705 try {
1706 result = mInterface.removeContactFromEab(subId, phoneNumber);
1707 } catch (RemoteException e) {
1708 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1709 getErrPrintWriter().println("Exception: " + e.getMessage());
1710 return -1;
1711 }
1712
1713 if (VDBG) {
1714 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1715 }
calvinpan293ea1b2021-02-04 17:52:13 +08001716 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001717 }
1718
calvinpane4a8a1d2021-01-25 13:51:18 +08001719 private int handleGettingEabContactCommand() {
1720 String phoneNumber = getNextArgRequired();
1721 if (TextUtils.isEmpty(phoneNumber)) {
1722 return -1;
1723 }
1724 String result = "";
1725 try {
1726 result = mInterface.getContactFromEab(phoneNumber);
1727
1728 } catch (RemoteException e) {
1729 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1730 getErrPrintWriter().println("Exception: " + e.getMessage());
1731 return -1;
1732 }
1733
1734 if (VDBG) {
1735 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1736 }
calvinpan293ea1b2021-02-04 17:52:13 +08001737 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001738 return 0;
1739 }
1740
1741 private int handleUceGetDeviceEnabledCommand() {
1742 boolean result = false;
1743 try {
1744 result = mInterface.getDeviceUceEnabled();
1745 } catch (RemoteException e) {
1746 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1747 return -1;
1748 }
1749 if (VDBG) {
1750 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1751 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001752 getOutPrintWriter().println(result);
1753 return 0;
1754 }
1755
James.cf Lin4b784aa2021-01-31 03:25:15 +08001756 private int handleUceSetDeviceEnabledCommand() {
1757 String enabledStr = getNextArg();
1758 if (TextUtils.isEmpty(enabledStr)) {
1759 return -1;
1760 }
1761
1762 try {
1763 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1764 mInterface.setDeviceUceEnabled(isEnabled);
1765 if (VDBG) {
1766 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1767 }
1768 } catch (NumberFormatException | RemoteException e) {
1769 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1770 getErrPrintWriter().println("Exception: " + e.getMessage());
1771 return -1;
1772 }
1773 return 0;
1774 }
1775
Hui Wang19a21872021-02-19 20:45:36 -08001776 private int handleSrcSetTestEnabledCommand() {
1777 String enabledStr = getNextArg();
1778 if (enabledStr == null) {
1779 return -1;
1780 }
1781
1782 try {
1783 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1784 if (VDBG) {
1785 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1786 }
1787 getOutPrintWriter().println("Done");
1788 } catch (NumberFormatException | RemoteException e) {
1789 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1790 getErrPrintWriter().println("Exception: " + e.getMessage());
1791 return -1;
1792 }
1793 return 0;
1794 }
1795
1796 private int handleSrcGetTestEnabledCommand() {
1797 boolean result = false;
1798 try {
1799 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1800 } catch (RemoteException e) {
1801 return -1;
1802 }
1803 if (VDBG) {
1804 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1805 }
1806 getOutPrintWriter().println(result);
1807 return 0;
1808 }
1809
Hui Wang068ab862020-10-31 05:12:53 +00001810 private int handleSrcSetDeviceEnabledCommand() {
1811 String enabledStr = getNextArg();
1812 if (enabledStr == null) {
1813 return -1;
1814 }
1815
1816 try {
1817 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1818 if (VDBG) {
1819 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1820 }
1821 getOutPrintWriter().println("Done");
1822 } catch (NumberFormatException | RemoteException e) {
1823 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1824 getErrPrintWriter().println("Exception: " + e.getMessage());
1825 return -1;
1826 }
1827 return 0;
1828 }
1829
1830 private int handleSrcGetDeviceEnabledCommand() {
1831 boolean result = false;
1832 try {
1833 result = mInterface.getDeviceSingleRegistrationEnabled();
1834 } catch (RemoteException e) {
1835 return -1;
1836 }
1837 if (VDBG) {
1838 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1839 }
1840 getOutPrintWriter().println(result);
1841 return 0;
1842 }
1843
1844 private int handleSrcSetCarrierEnabledCommand() {
1845 //the release time value could be -1
1846 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1847 : SubscriptionManager.getDefaultSubscriptionId();
1848 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1849 return -1;
1850 }
1851
1852 String enabledStr = getNextArg();
1853 if (enabledStr == null) {
1854 return -1;
1855 }
1856
1857 try {
1858 boolean result =
1859 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1860 if (VDBG) {
1861 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1862 + enabledStr + ", result=" + result);
1863 }
1864 getOutPrintWriter().println(result);
1865 } catch (NumberFormatException | RemoteException e) {
1866 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1867 + enabledStr + ", error" + e.getMessage());
1868 getErrPrintWriter().println("Exception: " + e.getMessage());
1869 return -1;
1870 }
1871 return 0;
1872 }
1873
1874 private int handleSrcGetCarrierEnabledCommand() {
1875 int subId = getSubId("src get-carrier-enabled");
1876 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1877 return -1;
1878 }
1879
1880 boolean result = false;
1881 try {
1882 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1883 } catch (RemoteException e) {
1884 return -1;
1885 }
1886 if (VDBG) {
1887 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1888 }
1889 getOutPrintWriter().println(result);
1890 return 0;
1891 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -08001892
1893 private int handleHasCarrierPrivilegesCommand() {
1894 String packageName = getNextArgRequired();
1895
1896 boolean hasCarrierPrivileges;
1897 try {
1898 hasCarrierPrivileges =
1899 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
1900 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
1901 } catch (RemoteException e) {
1902 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
1903 getErrPrintWriter().println("Exception: " + e.getMessage());
1904 return -1;
1905 }
1906
1907 getOutPrintWriter().println(hasCarrierPrivileges);
1908 return 0;
1909 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001910}