blob: 1e87fbe60c2b467a406cb2697c13c98e78fcdc80 [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";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010071 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080072 private static final String DATA_TEST_MODE = "data";
73 private static final String DATA_ENABLE = "enable";
74 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080075
Brad Ebinger999d3302020-11-25 14:31:39 -080076 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
77 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
78 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070079 private static final String IMS_ENABLE = "enable";
80 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070081 // Used to disable or enable processing of conference event package data from the network.
82 // This is handy for testing scenarios where CEP data does not exist on a network which does
83 // support CEP data.
84 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085
Hall Liud892bec2018-11-30 14:51:45 -080086 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080087 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080088
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010089 private static final String CC_GET_VALUE = "get-value";
90 private static final String CC_SET_VALUE = "set-value";
91 private static final String CC_CLEAR_VALUES = "clear-values";
92
Hui Wang0866fcc2020-10-12 12:14:23 -070093 private static final String GBA_SUBCOMMAND = "gba";
94 private static final String GBA_SET_SERVICE = "set-service";
95 private static final String GBA_GET_SERVICE = "get-service";
96 private static final String GBA_SET_RELEASE_TIME = "set-release";
97 private static final String GBA_GET_RELEASE_TIME = "get-release";
98
Hui Wang068ab862020-10-31 05:12:53 +000099 private static final String SINGLE_REGISTATION_CONFIG = "src";
100 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
101 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
102 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
103 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
104
Tyler Gunn92479152021-01-20 16:30:10 -0800105 private static final String D2D_SUBCOMMAND = "d2d";
106 private static final String D2D_SEND = "send";
107
James.cf Linbcdf8b32021-01-14 16:44:13 +0800108 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800109 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800110 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
111
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700112 // Take advantage of existing methods that already contain permissions checks when possible.
113 private final ITelephony mInterface;
114
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100115 private SubscriptionManager mSubscriptionManager;
116 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700117 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100118
119 private enum CcType {
120 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
121 STRING_ARRAY, UNKNOWN
122 }
123
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100124 private class CcOptionParseResult {
125 public int mSubId;
126 public boolean mPersistent;
127 }
128
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100129 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
130 // keys by looking at the end of the string which usually tells the type.
131 // For instance: "xxxx_string", "xxxx_string_array", etc.
132 // The carrier config keys in this map does not follow this convention. It is therefore not
133 // possible to infer the type for these keys by looking at the string.
134 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
135 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
136 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
137 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
138 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
139 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
140 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
141 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
142 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
143 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
144 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
145 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
146 CcType.STRING);
147 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
148 CcType.STRING_ARRAY);
149 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
150 CcType.STRING_ARRAY);
151 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
152 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
153 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
154 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
155 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
156 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
157 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
158 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
159 }
160 };
161
162 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700163 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100164 mCarrierConfigManager =
165 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
166 mSubscriptionManager = (SubscriptionManager)
167 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700168 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700169 }
170
171 @Override
172 public int onCommand(String cmd) {
173 if (cmd == null) {
174 return handleDefaultCommands(null);
175 }
176
177 switch (cmd) {
178 case IMS_SUBCOMMAND: {
179 return handleImsCommand();
180 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800181 case RCS_UCE_COMMAND:
182 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800183 case NUMBER_VERIFICATION_SUBCOMMAND:
184 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800185 case EMERGENCY_NUMBER_TEST_MODE:
186 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100187 case CARRIER_CONFIG_SUBCOMMAND: {
188 return handleCcCommand();
189 }
Shuo Qianf5125122019-12-16 17:03:07 -0800190 case DATA_TEST_MODE:
191 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700192 case END_BLOCK_SUPPRESSION:
193 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700194 case GBA_SUBCOMMAND:
195 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800196 case D2D_SUBCOMMAND:
197 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000198 case SINGLE_REGISTATION_CONFIG:
199 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000200 case RESTART_MODEM:
201 return handleRestartModemCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700202 default: {
203 return handleDefaultCommands(cmd);
204 }
205 }
206 }
207
208 @Override
209 public void onHelp() {
210 PrintWriter pw = getOutPrintWriter();
211 pw.println("Telephony Commands:");
212 pw.println(" help");
213 pw.println(" Print this help text.");
214 pw.println(" ims");
215 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800216 pw.println(" uce");
217 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800218 pw.println(" emergency-number-test-mode");
219 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700220 pw.println(" end-block-suppression");
221 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800222 pw.println(" data");
223 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100224 pw.println(" cc");
225 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700226 pw.println(" gba");
227 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000228 pw.println(" src");
229 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000230 pw.println(" restart-modem");
231 pw.println(" Restart modem command.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700232 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800233 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800234 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700235 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800236 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100237 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700238 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000239 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800240 onHelpD2D();
241 }
242
243 private void onHelpD2D() {
244 PrintWriter pw = getOutPrintWriter();
245 pw.println("D2D Comms Commands:");
246 pw.println(" d2d send TYPE VALUE");
247 pw.println(" Sends a D2D message of specified type and value.");
248 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
249 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
250 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
251 MESSAGE_CALL_AUDIO_CODEC));
252 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
253 + Communicator.messageToString(
254 MESSAGE_DEVICE_BATTERY_STATE));
255 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
256 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700257 }
258
259 private void onHelpIms() {
260 PrintWriter pw = getOutPrintWriter();
261 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800262 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700263 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
264 pw.println(" ImsService. Options are:");
265 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
266 pw.println(" is specified, it will choose the default voice SIM slot.");
267 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
268 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800269 pw.println(" -f: Set the feature that this override if for, if no option is");
270 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700271 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
272 pw.println(" Gets the package name of the currently defined ImsService.");
273 pw.println(" Options are:");
274 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
275 pw.println(" is specified, it will choose the default voice SIM slot.");
276 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000277 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800278 pw.println(" -f: The feature type that the query will be requested for. If none is");
279 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800280 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
281 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
282 pw.println(" configuration overrides. Options are:");
283 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
284 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700285 pw.println(" ims enable [-s SLOT_ID]");
286 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
287 pw.println(" if none is specified.");
288 pw.println(" ims disable [-s SLOT_ID]");
289 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
290 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700291 pw.println(" ims conference-event-package [enable/disable]");
292 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700293 }
294
James.cf Linbcdf8b32021-01-14 16:44:13 +0800295 private void onHelpUce() {
296 PrintWriter pw = getOutPrintWriter();
297 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800298 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
299 pw.println(" Get the EAB contacts from the EAB database.");
300 pw.println(" Options are:");
301 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
302 pw.println(" Expected output format :");
303 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800304 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
305 pw.println(" Remove the EAB contacts from the EAB database.");
306 pw.println(" Options are:");
307 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
308 pw.println(" is specified, it will choose the default voice SIM slot.");
309 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
310 }
311
Hall Liud892bec2018-11-30 14:51:45 -0800312 private void onHelpNumberVerification() {
313 PrintWriter pw = getOutPrintWriter();
314 pw.println("Number verification commands");
315 pw.println(" numverify override-package PACKAGE_NAME;");
316 pw.println(" Set the authorized package for number verification.");
317 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800318 pw.println(" numverify fake-call NUMBER;");
319 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
320 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800321 }
322
Shuo Qianf5125122019-12-16 17:03:07 -0800323 private void onHelpDataTestMode() {
324 PrintWriter pw = getOutPrintWriter();
325 pw.println("Mobile Data Test Mode Commands:");
326 pw.println(" data enable: enable mobile data connectivity");
327 pw.println(" data disable: disable mobile data connectivity");
328 }
329
sqian9d4df8b2019-01-15 18:32:07 -0800330 private void onHelpEmergencyNumber() {
331 PrintWriter pw = getOutPrintWriter();
332 pw.println("Emergency Number Test Mode Commands:");
333 pw.println(" emergency-number-test-mode ");
334 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
335 + " the test mode");
336 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700337 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800338 pw.println(" -c: clear the emergency number list in the test mode.");
339 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700340 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800341 pw.println(" -p: get the full emergency number list in the test mode.");
342 }
343
Shuo Qian489d9282020-07-09 11:30:03 -0700344 private void onHelpEndBlockSupperssion() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("End Block Suppression command:");
347 pw.println(" end-block-suppression: disable suppressing blocking by contact");
348 pw.println(" with emergency services.");
349 }
350
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100351 private void onHelpCc() {
352 PrintWriter pw = getOutPrintWriter();
353 pw.println("Carrier Config Commands:");
354 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
355 pw.println(" Print carrier config values.");
356 pw.println(" Options are:");
357 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
358 pw.println(" is specified, it will choose the default voice SIM slot.");
359 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
360 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100361 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100362 pw.println(" Set carrier config KEY to NEW_VALUE.");
363 pw.println(" Options are:");
364 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
365 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100366 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100367 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
368 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
369 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
370 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
371 pw.println(" cc clear-values [-s SLOT_ID]");
372 pw.println(" Clear all carrier override values that has previously been set");
373 pw.println(" with set-value");
374 pw.println(" Options are:");
375 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
376 pw.println(" is specified, it will choose the default voice SIM slot.");
377 }
378
Hui Wang0866fcc2020-10-12 12:14:23 -0700379 private void onHelpGba() {
380 PrintWriter pw = getOutPrintWriter();
381 pw.println("Gba Commands:");
382 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
383 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
384 pw.println(" Options are:");
385 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
386 pw.println(" is specified, it will choose the default voice SIM slot.");
387 pw.println(" gba get-service [-s SLOT_ID]");
388 pw.println(" Gets the package name of the currently defined GbaService.");
389 pw.println(" Options are:");
390 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
391 pw.println(" is specified, it will choose the default voice SIM slot.");
392 pw.println(" gba set-release [-s SLOT_ID] n");
393 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
394 pw.println(" Do not release/unbind if n is -1.");
395 pw.println(" Options are:");
396 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
397 pw.println(" is specified, it will choose the default voice SIM slot.");
398 pw.println(" gba get-release [-s SLOT_ID]");
399 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
400 pw.println(" Options are:");
401 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
402 pw.println(" is specified, it will choose the default voice SIM slot.");
403 }
404
Hui Wang068ab862020-10-31 05:12:53 +0000405 private void onHelpSrc() {
406 PrintWriter pw = getOutPrintWriter();
407 pw.println("RCS VoLTE Single Registration Config Commands:");
408 pw.println(" src set-device-enabled true|false|null");
409 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
410 pw.println(" The value could be true, false, or null(undefined).");
411 pw.println(" src get-device-enabled");
412 pw.println(" Gets the device config for RCS VoLTE single registration.");
413 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
414 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
415 pw.println(" The value could be true, false, or null(undefined).");
416 pw.println(" Options are:");
417 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
418 pw.println(" is specified, it will choose the default voice SIM slot.");
419 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
420 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
421 pw.println(" Options are:");
422 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
423 pw.println(" is specified, it will choose the default voice SIM slot.");
424 }
425
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700426 private int handleImsCommand() {
427 String arg = getNextArg();
428 if (arg == null) {
429 onHelpIms();
430 return 0;
431 }
432
433 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800434 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700435 return handleImsSetServiceCommand();
436 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800437 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700438 return handleImsGetServiceCommand();
439 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800440 case IMS_CLEAR_SERVICE_OVERRIDE: {
441 return handleImsClearCarrierServiceCommand();
442 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700443 case IMS_ENABLE: {
444 return handleEnableIms();
445 }
446 case IMS_DISABLE: {
447 return handleDisableIms();
448 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700449 case IMS_CEP: {
450 return handleCepChange();
451 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700452 }
453
454 return -1;
455 }
456
Shuo Qianf5125122019-12-16 17:03:07 -0800457 private int handleDataTestModeCommand() {
458 PrintWriter errPw = getErrPrintWriter();
459 String arg = getNextArgRequired();
460 if (arg == null) {
461 onHelpDataTestMode();
462 return 0;
463 }
464 switch (arg) {
465 case DATA_ENABLE: {
466 try {
467 mInterface.enableDataConnectivity();
468 } catch (RemoteException ex) {
469 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
470 errPw.println("Exception: " + ex.getMessage());
471 return -1;
472 }
473 break;
474 }
475 case DATA_DISABLE: {
476 try {
477 mInterface.disableDataConnectivity();
478 } catch (RemoteException ex) {
479 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
480 errPw.println("Exception: " + ex.getMessage());
481 return -1;
482 }
483 break;
484 }
485 default:
486 onHelpDataTestMode();
487 break;
488 }
489 return 0;
490 }
491
sqian9d4df8b2019-01-15 18:32:07 -0800492 private int handleEmergencyNumberTestModeCommand() {
493 PrintWriter errPw = getErrPrintWriter();
494 String opt = getNextOption();
495 if (opt == null) {
496 onHelpEmergencyNumber();
497 return 0;
498 }
499
500 switch (opt) {
501 case "-a": {
502 String emergencyNumberCmd = getNextArgRequired();
503 if (emergencyNumberCmd == null
504 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700505 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800506 + " to be specified after -a in the command ");
507 return -1;
508 }
509 try {
510 mInterface.updateEmergencyNumberListTestMode(
511 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
512 new EmergencyNumber(emergencyNumberCmd, "", "",
513 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
514 new ArrayList<String>(),
515 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
516 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
517 } catch (RemoteException ex) {
518 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
519 + ", error " + ex.getMessage());
520 errPw.println("Exception: " + ex.getMessage());
521 return -1;
522 }
523 break;
524 }
525 case "-c": {
526 try {
527 mInterface.updateEmergencyNumberListTestMode(
528 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
529 } catch (RemoteException ex) {
530 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
531 errPw.println("Exception: " + ex.getMessage());
532 return -1;
533 }
534 break;
535 }
536 case "-r": {
537 String emergencyNumberCmd = getNextArgRequired();
538 if (emergencyNumberCmd == null
539 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700540 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800541 + " to be specified after -r in the command ");
542 return -1;
543 }
544 try {
545 mInterface.updateEmergencyNumberListTestMode(
546 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
547 new EmergencyNumber(emergencyNumberCmd, "", "",
548 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
549 new ArrayList<String>(),
550 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
551 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
552 } catch (RemoteException ex) {
553 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
554 + ", error " + ex.getMessage());
555 errPw.println("Exception: " + ex.getMessage());
556 return -1;
557 }
558 break;
559 }
560 case "-p": {
561 try {
562 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
563 } catch (RemoteException ex) {
564 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
565 errPw.println("Exception: " + ex.getMessage());
566 return -1;
567 }
568 break;
569 }
570 default:
571 onHelpEmergencyNumber();
572 break;
573 }
574 return 0;
575 }
576
Hall Liud892bec2018-11-30 14:51:45 -0800577 private int handleNumberVerificationCommand() {
578 String arg = getNextArg();
579 if (arg == null) {
580 onHelpNumberVerification();
581 return 0;
582 }
583
Hall Liuca5af3a2018-12-04 16:58:23 -0800584 if (!checkShellUid()) {
585 return -1;
586 }
587
Hall Liud892bec2018-11-30 14:51:45 -0800588 switch (arg) {
589 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800590 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
591 return 0;
592 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800593 case NUMBER_VERIFICATION_FAKE_CALL: {
594 boolean val = NumberVerificationManager.getInstance()
595 .checkIncomingCall(getNextArg());
596 getOutPrintWriter().println(val ? "1" : "0");
597 return 0;
598 }
Hall Liud892bec2018-11-30 14:51:45 -0800599 }
600
601 return -1;
602 }
603
Tyler Gunn92479152021-01-20 16:30:10 -0800604 private int handleD2dCommand() {
605 String arg = getNextArg();
606 if (arg == null) {
607 onHelpD2D();
608 return 0;
609 }
610
611 switch (arg) {
612 case D2D_SEND: {
613 return handleD2dSendCommand();
614 }
615 }
616
617 return -1;
618 }
619
620 private int handleD2dSendCommand() {
621 PrintWriter errPw = getErrPrintWriter();
622 String opt;
623 int messageType = -1;
624 int messageValue = -1;
625
626
627 String arg = getNextArg();
628 if (arg == null) {
629 onHelpD2D();
630 return 0;
631 }
632 try {
633 messageType = Integer.parseInt(arg);
634 } catch (NumberFormatException e) {
635 errPw.println("message type must be a valid integer");
636 return -1;
637 }
638
639 arg = getNextArg();
640 if (arg == null) {
641 onHelpD2D();
642 return 0;
643 }
644 try {
645 messageValue = Integer.parseInt(arg);
646 } catch (NumberFormatException e) {
647 errPw.println("message value must be a valid integer");
648 return -1;
649 }
650
651 try {
652 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
653 } catch (RemoteException e) {
654 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
655 errPw.println("Exception: " + e.getMessage());
656 return -1;
657 }
658
659 return 0;
660 }
661
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700662 // ims set-ims-service
663 private int handleImsSetServiceCommand() {
664 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700665 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700666 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800667 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700668
669 String opt;
670 while ((opt = getNextOption()) != null) {
671 switch (opt) {
672 case "-s": {
673 try {
674 slotId = Integer.parseInt(getNextArgRequired());
675 } catch (NumberFormatException e) {
676 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
677 return -1;
678 }
679 break;
680 }
681 case "-c": {
682 isCarrierService = true;
683 break;
684 }
685 case "-d": {
686 isCarrierService = false;
687 break;
688 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800689 case "-f": {
690 String featureString = getNextArgRequired();
691 String[] features = featureString.split(",");
692 for (int i = 0; i < features.length; i++) {
693 try {
694 Integer result = Integer.parseInt(features[i]);
695 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
696 || result >= ImsFeature.FEATURE_MAX) {
697 errPw.println("ims set-ims-service -f " + result
698 + " is an invalid feature.");
699 return -1;
700 }
701 featuresList.add(result);
702 } catch (NumberFormatException e) {
703 errPw.println("ims set-ims-service -f tried to parse " + features[i]
704 + " as an integer.");
705 return -1;
706 }
707 }
708 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700709 }
710 }
711 // Mandatory param, either -c or -d
712 if (isCarrierService == null) {
713 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
714 return -1;
715 }
716
717 String packageName = getNextArg();
718
719 try {
720 if (packageName == null) {
721 packageName = "";
722 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800723 int[] featureArray = new int[featuresList.size()];
724 for (int i = 0; i < featuresList.size(); i++) {
725 featureArray[i] = featuresList.get(i);
726 }
727 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
728 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700729 if (VDBG) {
730 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800731 + (isCarrierService ? "-c " : "-d ")
732 + "-f " + featuresList + " "
733 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700734 }
735 getOutPrintWriter().println(result);
736 } catch (RemoteException e) {
737 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800738 + (isCarrierService ? "-c " : "-d ")
739 + "-f " + featuresList + " "
740 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700741 errPw.println("Exception: " + e.getMessage());
742 return -1;
743 }
744 return 0;
745 }
746
Brad Ebinger999d3302020-11-25 14:31:39 -0800747 // ims clear-ims-service-override
748 private int handleImsClearCarrierServiceCommand() {
749 PrintWriter errPw = getErrPrintWriter();
750 int slotId = getDefaultSlot();
751
752 String opt;
753 while ((opt = getNextOption()) != null) {
754 switch (opt) {
755 case "-s": {
756 try {
757 slotId = Integer.parseInt(getNextArgRequired());
758 } catch (NumberFormatException e) {
759 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
760 return -1;
761 }
762 break;
763 }
764 }
765 }
766
767 try {
768 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
769 if (VDBG) {
770 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
771 + ", result=" + result);
772 }
773 getOutPrintWriter().println(result);
774 } catch (RemoteException e) {
775 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
776 + ", error" + e.getMessage());
777 errPw.println("Exception: " + e.getMessage());
778 return -1;
779 }
780 return 0;
781 }
782
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700783 // ims get-ims-service
784 private int handleImsGetServiceCommand() {
785 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700786 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700787 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800788 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700789
790 String opt;
791 while ((opt = getNextOption()) != null) {
792 switch (opt) {
793 case "-s": {
794 try {
795 slotId = Integer.parseInt(getNextArgRequired());
796 } catch (NumberFormatException e) {
797 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
798 return -1;
799 }
800 break;
801 }
802 case "-c": {
803 isCarrierService = true;
804 break;
805 }
806 case "-d": {
807 isCarrierService = false;
808 break;
809 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800810 case "-f": {
811 try {
812 featureType = Integer.parseInt(getNextArg());
813 } catch (NumberFormatException e) {
814 errPw.println("ims get-ims-service -f requires valid integer as feature.");
815 return -1;
816 }
817 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
818 || featureType >= ImsFeature.FEATURE_MAX) {
819 errPw.println("ims get-ims-service -f invalid feature.");
820 return -1;
821 }
822 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700823 }
824 }
825 // Mandatory param, either -c or -d
826 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800827 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700828 return -1;
829 }
830
831 String result;
832 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800833 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700834 } catch (RemoteException e) {
835 return -1;
836 }
837 if (VDBG) {
838 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800839 + (isCarrierService ? "-c " : "-d ")
840 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
841 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700842 }
843 getOutPrintWriter().println(result);
844 return 0;
845 }
846
847 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700848 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700849 String opt;
850 while ((opt = getNextOption()) != null) {
851 switch (opt) {
852 case "-s": {
853 try {
854 slotId = Integer.parseInt(getNextArgRequired());
855 } catch (NumberFormatException e) {
856 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
857 return -1;
858 }
859 break;
860 }
861 }
862 }
863 try {
864 mInterface.enableIms(slotId);
865 } catch (RemoteException e) {
866 return -1;
867 }
868 if (VDBG) {
869 Log.v(LOG_TAG, "ims enable -s " + slotId);
870 }
871 return 0;
872 }
873
874 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700875 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700876 String opt;
877 while ((opt = getNextOption()) != null) {
878 switch (opt) {
879 case "-s": {
880 try {
881 slotId = Integer.parseInt(getNextArgRequired());
882 } catch (NumberFormatException e) {
883 getErrPrintWriter().println(
884 "ims disable requires an integer as a SLOT_ID.");
885 return -1;
886 }
887 break;
888 }
889 }
890 }
891 try {
892 mInterface.disableIms(slotId);
893 } catch (RemoteException e) {
894 return -1;
895 }
896 if (VDBG) {
897 Log.v(LOG_TAG, "ims disable -s " + slotId);
898 }
899 return 0;
900 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700901
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700902 private int handleCepChange() {
903 Log.i(LOG_TAG, "handleCepChange");
904 String opt = getNextArg();
905 if (opt == null) {
906 return -1;
907 }
908 boolean isCepEnabled = opt.equals("enable");
909
910 try {
911 mInterface.setCepEnabled(isCepEnabled);
912 } catch (RemoteException e) {
913 return -1;
914 }
915 return 0;
916 }
917
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700918 private int getDefaultSlot() {
919 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
920 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
921 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
922 // If there is no default, default to slot 0.
923 slotId = DEFAULT_PHONE_ID;
924 }
925 return slotId;
926 }
sqian2fff4a32018-11-05 14:18:37 -0800927
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100928 // Parse options related to Carrier Config Commands.
929 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100930 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100931 CcOptionParseResult result = new CcOptionParseResult();
932 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
933 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100934
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100935 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100936 while ((opt = getNextOption()) != null) {
937 switch (opt) {
938 case "-s": {
939 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100940 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
941 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
942 errPw.println(tag + "No valid subscription found.");
943 return null;
944 }
945
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100946 } catch (IllegalArgumentException e) {
947 // Missing slot id
948 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100949 return null;
950 }
951 break;
952 }
953 case "-p": {
954 if (allowOptionPersistent) {
955 result.mPersistent = true;
956 } else {
957 errPw.println(tag + "Unexpected option " + opt);
958 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100959 }
960 break;
961 }
962 default: {
963 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100964 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100965 }
966 }
967 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100968 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100969 }
970
971 private int slotStringToSubId(String tag, String slotString) {
972 int slotId = -1;
973 try {
974 slotId = Integer.parseInt(slotString);
975 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +0800976 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
977 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
978 }
979
980 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100981 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
982 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
983 }
984
Qiong Liuf25799b2020-09-10 10:13:46 +0800985 Phone phone = PhoneFactory.getPhone(slotId);
986 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100987 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
988 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
989 }
Qiong Liuf25799b2020-09-10 10:13:46 +0800990 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100991 }
992
Hall Liud892bec2018-11-30 14:51:45 -0800993 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -0800994 // adb can run as root or as shell, depending on whether the device is rooted.
995 return Binder.getCallingUid() == Process.SHELL_UID
996 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -0800997 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100998
999 private int handleCcCommand() {
1000 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1001 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001002 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001003 getErrPrintWriter().println("cc: Permission denied.");
1004 return -1;
1005 }
1006
1007 String arg = getNextArg();
1008 if (arg == null) {
1009 onHelpCc();
1010 return 0;
1011 }
1012
1013 switch (arg) {
1014 case CC_GET_VALUE: {
1015 return handleCcGetValue();
1016 }
1017 case CC_SET_VALUE: {
1018 return handleCcSetValue();
1019 }
1020 case CC_CLEAR_VALUES: {
1021 return handleCcClearValues();
1022 }
1023 default: {
1024 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1025 }
1026 }
1027 return -1;
1028 }
1029
1030 // cc get-value
1031 private int handleCcGetValue() {
1032 PrintWriter errPw = getErrPrintWriter();
1033 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1034 String key = null;
1035
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001036 // Parse all options
1037 CcOptionParseResult options = parseCcOptions(tag, false);
1038 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001039 return -1;
1040 }
1041
1042 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001043 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001044 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001045 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001046 return -1;
1047 }
1048
1049 // Get the key.
1050 key = getNextArg();
1051 if (key != null) {
1052 // A key was provided. Verify if it is a valid key
1053 if (!bundle.containsKey(key)) {
1054 errPw.println(tag + key + " is not a valid key.");
1055 return -1;
1056 }
1057
1058 // Print the carrier config value for key.
1059 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1060 } else {
1061 // No key provided. Show all values.
1062 // Iterate over a sorted list of all carrier config keys and print them.
1063 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1064 for (String k : sortedSet) {
1065 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1066 }
1067 }
1068 return 0;
1069 }
1070
1071 // cc set-value
1072 private int handleCcSetValue() {
1073 PrintWriter errPw = getErrPrintWriter();
1074 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1075
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001076 // Parse all options
1077 CcOptionParseResult options = parseCcOptions(tag, true);
1078 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001079 return -1;
1080 }
1081
1082 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001083 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001084 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001085 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001086 return -1;
1087 }
1088
1089 // Get the key.
1090 String key = getNextArg();
1091 if (key == null || key.equals("")) {
1092 errPw.println(tag + "KEY is missing");
1093 return -1;
1094 }
1095
1096 // Verify if the key is valid
1097 if (!originalValues.containsKey(key)) {
1098 errPw.println(tag + key + " is not a valid key.");
1099 return -1;
1100 }
1101
1102 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1103 ArrayList<String> valueList = new ArrayList<String>();
1104 while (peekNextArg() != null) {
1105 valueList.add(getNextArg());
1106 }
1107
1108 // Find the type of the carrier config value
1109 CcType type = getType(tag, key, originalValues);
1110 if (type == CcType.UNKNOWN) {
1111 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1112 return -1;
1113 }
1114
1115 // Create an override bundle containing the key and value that should be overriden.
1116 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1117 if (overrideBundle == null) {
1118 return -1;
1119 }
1120
1121 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001122 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001123
1124 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001125 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001126 if (newValues == 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 // Print the original and new value.
1132 String originalValueString = ccValueToString(key, type, originalValues);
1133 String newValueString = ccValueToString(key, type, newValues);
1134 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1135 getOutPrintWriter().println("New value: \n" + newValueString);
1136
1137 return 0;
1138 }
1139
1140 // cc clear-values
1141 private int handleCcClearValues() {
1142 PrintWriter errPw = getErrPrintWriter();
1143 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1144
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001145 // Parse all options
1146 CcOptionParseResult options = parseCcOptions(tag, false);
1147 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001148 return -1;
1149 }
1150
1151 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001152 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001153 getOutPrintWriter()
1154 .println("All previously set carrier config override values has been cleared");
1155 return 0;
1156 }
1157
1158 private CcType getType(String tag, String key, PersistableBundle bundle) {
1159 // Find the type by checking the type of the current value stored in the bundle.
1160 Object value = bundle.get(key);
1161
1162 if (CC_TYPE_MAP.containsKey(key)) {
1163 return CC_TYPE_MAP.get(key);
1164 } else if (value != null) {
1165 if (value instanceof Boolean) {
1166 return CcType.BOOLEAN;
1167 } else if (value instanceof Double) {
1168 return CcType.DOUBLE;
1169 } else if (value instanceof double[]) {
1170 return CcType.DOUBLE_ARRAY;
1171 } else if (value instanceof Integer) {
1172 return CcType.INT;
1173 } else if (value instanceof int[]) {
1174 return CcType.INT_ARRAY;
1175 } else if (value instanceof Long) {
1176 return CcType.LONG;
1177 } else if (value instanceof long[]) {
1178 return CcType.LONG_ARRAY;
1179 } else if (value instanceof String) {
1180 return CcType.STRING;
1181 } else if (value instanceof String[]) {
1182 return CcType.STRING_ARRAY;
1183 }
1184 } else {
1185 // Current value was null and can therefore not be used in order to find the type.
1186 // Check the name of the key to infer the type. This check is not needed for primitive
1187 // data types (boolean, double, int and long), since they can not be null.
1188 if (key.endsWith("double_array")) {
1189 return CcType.DOUBLE_ARRAY;
1190 }
1191 if (key.endsWith("int_array")) {
1192 return CcType.INT_ARRAY;
1193 }
1194 if (key.endsWith("long_array")) {
1195 return CcType.LONG_ARRAY;
1196 }
1197 if (key.endsWith("string")) {
1198 return CcType.STRING;
1199 }
1200 if (key.endsWith("string_array") || key.endsWith("strings")) {
1201 return CcType.STRING_ARRAY;
1202 }
1203 }
1204
1205 // Not possible to infer the type by looking at the current value or the key.
1206 PrintWriter errPw = getErrPrintWriter();
1207 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1208 return CcType.UNKNOWN;
1209 }
1210
1211 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1212 String result;
1213 StringBuilder valueString = new StringBuilder();
1214 String typeString = type.toString();
1215 Object value = bundle.get(key);
1216
1217 if (value == null) {
1218 valueString.append("null");
1219 } else {
1220 switch (type) {
1221 case DOUBLE_ARRAY: {
1222 // Format the string representation of the int array as value1 value2......
1223 double[] valueArray = (double[]) value;
1224 for (int i = 0; i < valueArray.length; i++) {
1225 if (i != 0) {
1226 valueString.append(" ");
1227 }
1228 valueString.append(valueArray[i]);
1229 }
1230 break;
1231 }
1232 case INT_ARRAY: {
1233 // Format the string representation of the int array as value1 value2......
1234 int[] valueArray = (int[]) value;
1235 for (int i = 0; i < valueArray.length; i++) {
1236 if (i != 0) {
1237 valueString.append(" ");
1238 }
1239 valueString.append(valueArray[i]);
1240 }
1241 break;
1242 }
1243 case LONG_ARRAY: {
1244 // Format the string representation of the int array as value1 value2......
1245 long[] valueArray = (long[]) value;
1246 for (int i = 0; i < valueArray.length; i++) {
1247 if (i != 0) {
1248 valueString.append(" ");
1249 }
1250 valueString.append(valueArray[i]);
1251 }
1252 break;
1253 }
1254 case STRING: {
1255 valueString.append("\"" + value.toString() + "\"");
1256 break;
1257 }
1258 case STRING_ARRAY: {
1259 // Format the string representation of the string array as "value1" "value2"....
1260 String[] valueArray = (String[]) value;
1261 for (int i = 0; i < valueArray.length; i++) {
1262 if (i != 0) {
1263 valueString.append(" ");
1264 }
1265 if (valueArray[i] != null) {
1266 valueString.append("\"" + valueArray[i] + "\"");
1267 } else {
1268 valueString.append("null");
1269 }
1270 }
1271 break;
1272 }
1273 default: {
1274 valueString.append(value.toString());
1275 }
1276 }
1277 }
1278 return String.format("%-70s %-15s %s", key, typeString, valueString);
1279 }
1280
1281 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1282 ArrayList<String> valueList) {
1283 PrintWriter errPw = getErrPrintWriter();
1284 PersistableBundle bundle = new PersistableBundle();
1285
1286 // First verify that a valid number of values has been provided for the type.
1287 switch (type) {
1288 case BOOLEAN:
1289 case DOUBLE:
1290 case INT:
1291 case LONG: {
1292 if (valueList.size() != 1) {
1293 errPw.println(tag + "Expected 1 value for type " + type
1294 + ". Found: " + valueList.size());
1295 return null;
1296 }
1297 break;
1298 }
1299 case STRING: {
1300 if (valueList.size() > 1) {
1301 errPw.println(tag + "Expected 0 or 1 values for type " + type
1302 + ". Found: " + valueList.size());
1303 return null;
1304 }
1305 break;
1306 }
1307 }
1308
1309 // Parse the value according to type and add it to the Bundle.
1310 switch (type) {
1311 case BOOLEAN: {
1312 if ("true".equalsIgnoreCase(valueList.get(0))) {
1313 bundle.putBoolean(key, true);
1314 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1315 bundle.putBoolean(key, false);
1316 } else {
1317 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1318 return null;
1319 }
1320 break;
1321 }
1322 case DOUBLE: {
1323 try {
1324 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1325 } catch (NumberFormatException nfe) {
1326 // Not a valid double
1327 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1328 return null;
1329 }
1330 break;
1331 }
1332 case DOUBLE_ARRAY: {
1333 double[] valueDoubleArray = null;
1334 if (valueList.size() > 0) {
1335 valueDoubleArray = new double[valueList.size()];
1336 for (int i = 0; i < valueList.size(); i++) {
1337 try {
1338 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1339 } catch (NumberFormatException nfe) {
1340 // Not a valid double
1341 errPw.println(
1342 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1343 return null;
1344 }
1345 }
1346 }
1347 bundle.putDoubleArray(key, valueDoubleArray);
1348 break;
1349 }
1350 case INT: {
1351 try {
1352 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1353 } catch (NumberFormatException nfe) {
1354 // Not a valid integer
1355 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1356 return null;
1357 }
1358 break;
1359 }
1360 case INT_ARRAY: {
1361 int[] valueIntArray = null;
1362 if (valueList.size() > 0) {
1363 valueIntArray = new int[valueList.size()];
1364 for (int i = 0; i < valueList.size(); i++) {
1365 try {
1366 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1367 } catch (NumberFormatException nfe) {
1368 // Not a valid integer
1369 errPw.println(tag
1370 + "Unable to parse " + valueList.get(i) + " as an integer.");
1371 return null;
1372 }
1373 }
1374 }
1375 bundle.putIntArray(key, valueIntArray);
1376 break;
1377 }
1378 case LONG: {
1379 try {
1380 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1381 } catch (NumberFormatException nfe) {
1382 // Not a valid long
1383 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1384 return null;
1385 }
1386 break;
1387 }
1388 case LONG_ARRAY: {
1389 long[] valueLongArray = null;
1390 if (valueList.size() > 0) {
1391 valueLongArray = new long[valueList.size()];
1392 for (int i = 0; i < valueList.size(); i++) {
1393 try {
1394 valueLongArray[i] = Long.parseLong(valueList.get(i));
1395 } catch (NumberFormatException nfe) {
1396 // Not a valid long
1397 errPw.println(
1398 tag + "Unable to parse " + valueList.get(i) + " as a long");
1399 return null;
1400 }
1401 }
1402 }
1403 bundle.putLongArray(key, valueLongArray);
1404 break;
1405 }
1406 case STRING: {
1407 String value = null;
1408 if (valueList.size() > 0) {
1409 value = valueList.get(0);
1410 }
1411 bundle.putString(key, value);
1412 break;
1413 }
1414 case STRING_ARRAY: {
1415 String[] valueStringArray = null;
1416 if (valueList.size() > 0) {
1417 valueStringArray = new String[valueList.size()];
1418 valueList.toArray(valueStringArray);
1419 }
1420 bundle.putStringArray(key, valueStringArray);
1421 break;
1422 }
1423 }
1424 return bundle;
1425 }
Shuo Qian489d9282020-07-09 11:30:03 -07001426
1427 private int handleEndBlockSuppressionCommand() {
1428 if (!checkShellUid()) {
1429 return -1;
1430 }
1431
1432 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1433 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1434 }
1435 return 0;
1436 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001437
Michele Berionne38c1afa2020-12-28 20:23:16 +00001438 private int handleRestartModemCommand() {
1439 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1440 // non user build.
1441 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1442 getErrPrintWriter().println("RestartModem: Permission denied.");
1443 return -1;
1444 }
1445
1446 boolean result = TelephonyManager.getDefault().rebootRadio();
1447 getOutPrintWriter().println(result);
1448
1449 return result ? 0 : -1;
1450 }
1451
Hui Wang0866fcc2020-10-12 12:14:23 -07001452 private int handleGbaCommand() {
1453 String arg = getNextArg();
1454 if (arg == null) {
1455 onHelpGba();
1456 return 0;
1457 }
1458
1459 switch (arg) {
1460 case GBA_SET_SERVICE: {
1461 return handleGbaSetServiceCommand();
1462 }
1463 case GBA_GET_SERVICE: {
1464 return handleGbaGetServiceCommand();
1465 }
1466 case GBA_SET_RELEASE_TIME: {
1467 return handleGbaSetReleaseCommand();
1468 }
1469 case GBA_GET_RELEASE_TIME: {
1470 return handleGbaGetReleaseCommand();
1471 }
1472 }
1473
1474 return -1;
1475 }
1476
1477 private int getSubId(String cmd) {
1478 int slotId = getDefaultSlot();
1479 String opt = getNextOption();
1480 if (opt != null && opt.equals("-s")) {
1481 try {
1482 slotId = Integer.parseInt(getNextArgRequired());
1483 } catch (NumberFormatException e) {
1484 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1485 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1486 }
1487 }
1488 int[] subIds = SubscriptionManager.getSubId(slotId);
1489 return subIds[0];
1490 }
1491
1492 private int handleGbaSetServiceCommand() {
1493 int subId = getSubId("gba set-service");
1494 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1495 return -1;
1496 }
1497
1498 String packageName = getNextArg();
1499 try {
1500 if (packageName == null) {
1501 packageName = "";
1502 }
1503 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1504 if (VDBG) {
1505 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1506 + packageName + ", result=" + result);
1507 }
1508 getOutPrintWriter().println(result);
1509 } catch (RemoteException e) {
1510 Log.w(LOG_TAG, "gba set-service " + subId + " "
1511 + packageName + ", error" + e.getMessage());
1512 getErrPrintWriter().println("Exception: " + e.getMessage());
1513 return -1;
1514 }
1515 return 0;
1516 }
1517
1518 private int handleGbaGetServiceCommand() {
1519 String result;
1520
1521 int subId = getSubId("gba get-service");
1522 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1523 return -1;
1524 }
1525
1526 try {
1527 result = mInterface.getBoundGbaService(subId);
1528 } catch (RemoteException e) {
1529 return -1;
1530 }
1531 if (VDBG) {
1532 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1533 }
1534 getOutPrintWriter().println(result);
1535 return 0;
1536 }
1537
1538 private int handleGbaSetReleaseCommand() {
1539 //the release time value could be -1
1540 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1541 : SubscriptionManager.getDefaultSubscriptionId();
1542 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1543 return -1;
1544 }
1545
1546 String intervalStr = getNextArg();
1547 if (intervalStr == null) {
1548 return -1;
1549 }
1550
1551 try {
1552 int interval = Integer.parseInt(intervalStr);
1553 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1554 if (VDBG) {
1555 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1556 + intervalStr + ", result=" + result);
1557 }
1558 getOutPrintWriter().println(result);
1559 } catch (NumberFormatException | RemoteException e) {
1560 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1561 + intervalStr + ", error" + e.getMessage());
1562 getErrPrintWriter().println("Exception: " + e.getMessage());
1563 return -1;
1564 }
1565 return 0;
1566 }
1567
1568 private int handleGbaGetReleaseCommand() {
1569 int subId = getSubId("gba get-release");
1570 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1571 return -1;
1572 }
1573
1574 int result = 0;
1575 try {
1576 result = mInterface.getGbaReleaseTime(subId);
1577 } catch (RemoteException e) {
1578 return -1;
1579 }
1580 if (VDBG) {
1581 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1582 }
1583 getOutPrintWriter().println(result);
1584 return 0;
1585 }
Hui Wang068ab862020-10-31 05:12:53 +00001586
1587 private int handleSingleRegistrationConfigCommand() {
1588 String arg = getNextArg();
1589 if (arg == null) {
1590 onHelpSrc();
1591 return 0;
1592 }
1593
1594 switch (arg) {
1595 case SRC_SET_DEVICE_ENABLED: {
1596 return handleSrcSetDeviceEnabledCommand();
1597 }
1598 case SRC_GET_DEVICE_ENABLED: {
1599 return handleSrcGetDeviceEnabledCommand();
1600 }
1601 case SRC_SET_CARRIER_ENABLED: {
1602 return handleSrcSetCarrierEnabledCommand();
1603 }
1604 case SRC_GET_CARRIER_ENABLED: {
1605 return handleSrcGetCarrierEnabledCommand();
1606 }
1607 }
1608
1609 return -1;
1610 }
1611
James.cf Linbcdf8b32021-01-14 16:44:13 +08001612 private int handleRcsUceCommand() {
1613 String arg = getNextArg();
1614 if (arg == null) {
1615 Log.w(LOG_TAG, "cannot get uce parameter");
1616 return -1;
1617 }
1618
1619 switch (arg) {
1620 case UCE_REMOVE_EAB_CONTACT:
1621 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001622 case UCE_GET_EAB_CONTACT:
1623 return handleGettingEabContactCommand();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001624 }
1625 return -1;
1626 }
1627
1628 private int handleRemovingEabContactCommand() {
1629 int subId = getSubId("uce remove-eab-contact");
1630 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1631 return -1;
1632 }
1633
1634 String phoneNumber = getNextArgRequired();
1635 if (TextUtils.isEmpty(phoneNumber)) {
1636 return -1;
1637 }
1638 int result = 0;
1639 try {
1640 result = mInterface.removeContactFromEab(subId, phoneNumber);
1641 } catch (RemoteException e) {
1642 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1643 getErrPrintWriter().println("Exception: " + e.getMessage());
1644 return -1;
1645 }
1646
1647 if (VDBG) {
1648 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1649 }
1650 return result;
1651 }
1652
calvinpane4a8a1d2021-01-25 13:51:18 +08001653 private int handleGettingEabContactCommand() {
1654 String phoneNumber = getNextArgRequired();
1655 if (TextUtils.isEmpty(phoneNumber)) {
1656 return -1;
1657 }
1658 String result = "";
1659 try {
1660 result = mInterface.getContactFromEab(phoneNumber);
1661
1662 } catch (RemoteException e) {
1663 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1664 getErrPrintWriter().println("Exception: " + e.getMessage());
1665 return -1;
1666 }
1667
1668 if (VDBG) {
1669 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1670 }
1671 getOutPrintWriter().println(result);
1672 return 0;
1673 }
1674
Hui Wang068ab862020-10-31 05:12:53 +00001675 private int handleSrcSetDeviceEnabledCommand() {
1676 String enabledStr = getNextArg();
1677 if (enabledStr == null) {
1678 return -1;
1679 }
1680
1681 try {
1682 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1683 if (VDBG) {
1684 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1685 }
1686 getOutPrintWriter().println("Done");
1687 } catch (NumberFormatException | RemoteException e) {
1688 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1689 getErrPrintWriter().println("Exception: " + e.getMessage());
1690 return -1;
1691 }
1692 return 0;
1693 }
1694
1695 private int handleSrcGetDeviceEnabledCommand() {
1696 boolean result = false;
1697 try {
1698 result = mInterface.getDeviceSingleRegistrationEnabled();
1699 } catch (RemoteException e) {
1700 return -1;
1701 }
1702 if (VDBG) {
1703 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1704 }
1705 getOutPrintWriter().println(result);
1706 return 0;
1707 }
1708
1709 private int handleSrcSetCarrierEnabledCommand() {
1710 //the release time value could be -1
1711 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1712 : SubscriptionManager.getDefaultSubscriptionId();
1713 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1714 return -1;
1715 }
1716
1717 String enabledStr = getNextArg();
1718 if (enabledStr == null) {
1719 return -1;
1720 }
1721
1722 try {
1723 boolean result =
1724 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
1725 if (VDBG) {
1726 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1727 + enabledStr + ", result=" + result);
1728 }
1729 getOutPrintWriter().println(result);
1730 } catch (NumberFormatException | RemoteException e) {
1731 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
1732 + enabledStr + ", error" + e.getMessage());
1733 getErrPrintWriter().println("Exception: " + e.getMessage());
1734 return -1;
1735 }
1736 return 0;
1737 }
1738
1739 private int handleSrcGetCarrierEnabledCommand() {
1740 int subId = getSubId("src get-carrier-enabled");
1741 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1742 return -1;
1743 }
1744
1745 boolean result = false;
1746 try {
1747 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
1748 } catch (RemoteException e) {
1749 return -1;
1750 }
1751 if (VDBG) {
1752 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
1753 }
1754 getOutPrintWriter().println(result);
1755 return 0;
1756 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001757}