blob: 87dc868212aa2a1a44916a7e029ddfeec16ed221 [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;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000029import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070030import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010031import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.telephony.SubscriptionManager;
Michele Berionne38c1afa2020-12-28 20:23:16 +000033import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080034import android.telephony.emergency.EmergencyNumber;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000035import android.telephony.ims.ImsException;
36import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080037import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080038import android.text.TextUtils;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000039import android.util.ArrayMap;
40import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070041import android.util.Log;
42
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000043import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070044import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080045import com.android.internal.telephony.Phone;
46import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080047import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080048import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080049import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080050import com.android.modules.utils.BasicShellCommandHandler;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070051
52import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080053import java.util.ArrayList;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000054import java.util.Arrays;
55import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010056import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080057import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010058import java.util.Map;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000059import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010060import java.util.TreeSet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070061
62/**
63 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
64 * permission checks have been done before onCommand was called. Make sure any commands processed
65 * here also contain the appropriate permissions checks.
66 */
67
Hall Liua1548bd2019-12-24 14:14:12 -080068public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070069
70 private static final String LOG_TAG = "TelephonyShellCommand";
71 // Don't commit with this true.
72 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070073 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070074
75 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080076 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080077 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070078 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne38c1afa2020-12-28 20:23:16 +000079 private static final String RESTART_MODEM = "restart-modem";
Michele Berionned9fbae52020-11-13 02:36:59 +000080 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010081 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080082 private static final String DATA_TEST_MODE = "data";
83 private static final String DATA_ENABLE = "enable";
84 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080085
Brad Ebinger999d3302020-11-25 14:31:39 -080086 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
87 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
88 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070089 private static final String IMS_ENABLE = "enable";
90 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070091 // Used to disable or enable processing of conference event package data from the network.
92 // This is handy for testing scenarios where CEP data does not exist on a network which does
93 // support CEP data.
94 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070095
Hall Liud892bec2018-11-30 14:51:45 -080096 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080097 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080098
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010099 private static final String CC_GET_VALUE = "get-value";
100 private static final String CC_SET_VALUE = "set-value";
101 private static final String CC_CLEAR_VALUES = "clear-values";
102
Hui Wang0866fcc2020-10-12 12:14:23 -0700103 private static final String GBA_SUBCOMMAND = "gba";
104 private static final String GBA_SET_SERVICE = "set-service";
105 private static final String GBA_GET_SERVICE = "get-service";
106 private static final String GBA_SET_RELEASE_TIME = "set-release";
107 private static final String GBA_GET_RELEASE_TIME = "get-release";
108
Hui Wang068ab862020-10-31 05:12:53 +0000109 private static final String SINGLE_REGISTATION_CONFIG = "src";
110 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
111 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
112 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
113 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wang19a21872021-02-19 20:45:36 -0800114 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
115 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wang068ab862020-10-31 05:12:53 +0000116
Tyler Gunn92479152021-01-20 16:30:10 -0800117 private static final String D2D_SUBCOMMAND = "d2d";
118 private static final String D2D_SEND = "send";
119
James.cf Linbcdf8b32021-01-14 16:44:13 +0800120 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800121 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800122 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800123 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
124 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000125 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
126 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800127
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800128 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
129 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
130
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700131 // Take advantage of existing methods that already contain permissions checks when possible.
132 private final ITelephony mInterface;
133
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100134 private SubscriptionManager mSubscriptionManager;
135 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700136 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100137
138 private enum CcType {
139 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
140 STRING_ARRAY, UNKNOWN
141 }
142
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100143 private class CcOptionParseResult {
144 public int mSubId;
145 public boolean mPersistent;
146 }
147
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100148 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
149 // keys by looking at the end of the string which usually tells the type.
150 // For instance: "xxxx_string", "xxxx_string_array", etc.
151 // The carrier config keys in this map does not follow this convention. It is therefore not
152 // possible to infer the type for these keys by looking at the string.
153 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
154 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
155 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
156 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
157 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
158 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
159 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
160 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
161 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
162 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
163 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
164 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
165 CcType.STRING);
166 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
167 CcType.STRING_ARRAY);
168 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
169 CcType.STRING_ARRAY);
170 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
171 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
172 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
173 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
174 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
175 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
176 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
177 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
178 }
179 };
180
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000181 /**
182 * Map from a shorthand string to the feature tags required in registration required in order
183 * for the RCS feature to be considered "capable".
184 */
185 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
186 static {
187 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
188 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
189 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
190 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
191 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
192 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
193 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
194 FeatureTags.FEATURE_TAG_VIDEO)));
195 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
196 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
197 map.put("call_comp",
198 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
199 map.put("call_comp_mmtel",
200 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
201 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
202 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
203 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
204 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
205 // version
206 map.put("chatbot", new ArraySet<>(Arrays.asList(
207 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
208 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
209 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
210 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
211 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
212 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
213 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
214 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
215 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
216 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
217 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
218 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
219 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
220 }
221
222
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100223 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700224 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100225 mCarrierConfigManager =
226 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
227 mSubscriptionManager = (SubscriptionManager)
228 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700229 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700230 }
231
232 @Override
233 public int onCommand(String cmd) {
234 if (cmd == null) {
235 return handleDefaultCommands(null);
236 }
237
238 switch (cmd) {
239 case IMS_SUBCOMMAND: {
240 return handleImsCommand();
241 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800242 case RCS_UCE_COMMAND:
243 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800244 case NUMBER_VERIFICATION_SUBCOMMAND:
245 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800246 case EMERGENCY_NUMBER_TEST_MODE:
247 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100248 case CARRIER_CONFIG_SUBCOMMAND: {
249 return handleCcCommand();
250 }
Shuo Qianf5125122019-12-16 17:03:07 -0800251 case DATA_TEST_MODE:
252 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700253 case END_BLOCK_SUPPRESSION:
254 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700255 case GBA_SUBCOMMAND:
256 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800257 case D2D_SUBCOMMAND:
258 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000259 case SINGLE_REGISTATION_CONFIG:
260 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000261 case RESTART_MODEM:
262 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000263 case UNATTENDED_REBOOT:
264 return handleUnattendedReboot();
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800265 case HAS_CARRIER_PRIVILEGES_COMMAND:
266 return handleHasCarrierPrivilegesCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700267 default: {
268 return handleDefaultCommands(cmd);
269 }
270 }
271 }
272
273 @Override
274 public void onHelp() {
275 PrintWriter pw = getOutPrintWriter();
276 pw.println("Telephony Commands:");
277 pw.println(" help");
278 pw.println(" Print this help text.");
279 pw.println(" ims");
280 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800281 pw.println(" uce");
282 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800283 pw.println(" emergency-number-test-mode");
284 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700285 pw.println(" end-block-suppression");
286 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800287 pw.println(" data");
288 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100289 pw.println(" cc");
290 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700291 pw.println(" gba");
292 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000293 pw.println(" src");
294 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000295 pw.println(" restart-modem");
296 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000297 pw.println(" unattended-reboot");
298 pw.println(" Prepare for unattended reboot.");
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800299 pw.println(" has-carrier-privileges [package]");
300 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700301 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800302 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800303 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700304 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800305 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100306 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700307 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000308 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800309 onHelpD2D();
310 }
311
312 private void onHelpD2D() {
313 PrintWriter pw = getOutPrintWriter();
314 pw.println("D2D Comms Commands:");
315 pw.println(" d2d send TYPE VALUE");
316 pw.println(" Sends a D2D message of specified type and value.");
317 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
318 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
319 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
320 MESSAGE_CALL_AUDIO_CODEC));
321 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
322 + Communicator.messageToString(
323 MESSAGE_DEVICE_BATTERY_STATE));
324 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
325 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700326 }
327
328 private void onHelpIms() {
329 PrintWriter pw = getOutPrintWriter();
330 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800331 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700332 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
333 pw.println(" ImsService. Options are:");
334 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
335 pw.println(" is specified, it will choose the default voice SIM slot.");
336 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
337 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800338 pw.println(" -f: Set the feature that this override if for, if no option is");
339 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700340 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
341 pw.println(" Gets the package name of the currently defined ImsService.");
342 pw.println(" Options are:");
343 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
344 pw.println(" is specified, it will choose the default voice SIM slot.");
345 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000346 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800347 pw.println(" -f: The feature type that the query will be requested for. If none is");
348 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800349 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
350 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
351 pw.println(" configuration overrides. Options are:");
352 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
353 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700354 pw.println(" ims enable [-s SLOT_ID]");
355 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
356 pw.println(" if none is specified.");
357 pw.println(" ims disable [-s SLOT_ID]");
358 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
359 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700360 pw.println(" ims conference-event-package [enable/disable]");
361 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700362 }
363
James.cf Linbcdf8b32021-01-14 16:44:13 +0800364 private void onHelpUce() {
365 PrintWriter pw = getOutPrintWriter();
366 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800367 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
368 pw.println(" Get the EAB contacts from the EAB database.");
369 pw.println(" Options are:");
370 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
371 pw.println(" Expected output format :");
372 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800373 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
374 pw.println(" Remove the EAB contacts from the EAB database.");
375 pw.println(" Options are:");
376 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
377 pw.println(" is specified, it will choose the default voice SIM slot.");
378 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800379 pw.println(" uce get-device-enabled");
380 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
381 pw.println(" uce set-device-enabled true|false");
382 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
383 pw.println(" The value could be true, false.");
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000384 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
385 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
386 pw.println(" Options are:");
387 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
388 pw.println(" is specified, it will choose the default voice SIM slot.");
389 pw.println(" add [CAPABILITY]: add a new capability");
390 pw.println(" remove [CAPABILITY]: remove a capability");
391 pw.println(" clear: clear all capability overrides");
392 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
393 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
394 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
395 pw.println(" chatbot_sa, chatbot_role] as well as full length");
396 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
397 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
398 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
399 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800400 }
401
Hall Liud892bec2018-11-30 14:51:45 -0800402 private void onHelpNumberVerification() {
403 PrintWriter pw = getOutPrintWriter();
404 pw.println("Number verification commands");
405 pw.println(" numverify override-package PACKAGE_NAME;");
406 pw.println(" Set the authorized package for number verification.");
407 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800408 pw.println(" numverify fake-call NUMBER;");
409 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
410 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800411 }
412
Shuo Qianf5125122019-12-16 17:03:07 -0800413 private void onHelpDataTestMode() {
414 PrintWriter pw = getOutPrintWriter();
415 pw.println("Mobile Data Test Mode Commands:");
416 pw.println(" data enable: enable mobile data connectivity");
417 pw.println(" data disable: disable mobile data connectivity");
418 }
419
sqian9d4df8b2019-01-15 18:32:07 -0800420 private void onHelpEmergencyNumber() {
421 PrintWriter pw = getOutPrintWriter();
422 pw.println("Emergency Number Test Mode Commands:");
423 pw.println(" emergency-number-test-mode ");
424 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
425 + " the test mode");
426 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700427 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800428 pw.println(" -c: clear the emergency number list in the test mode.");
429 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700430 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800431 pw.println(" -p: get the full emergency number list in the test mode.");
432 }
433
Shuo Qian489d9282020-07-09 11:30:03 -0700434 private void onHelpEndBlockSupperssion() {
435 PrintWriter pw = getOutPrintWriter();
436 pw.println("End Block Suppression command:");
437 pw.println(" end-block-suppression: disable suppressing blocking by contact");
438 pw.println(" with emergency services.");
439 }
440
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100441 private void onHelpCc() {
442 PrintWriter pw = getOutPrintWriter();
443 pw.println("Carrier Config Commands:");
444 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
445 pw.println(" Print carrier config values.");
446 pw.println(" Options are:");
447 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
448 pw.println(" is specified, it will choose the default voice SIM slot.");
449 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
450 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100451 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100452 pw.println(" Set carrier config KEY to NEW_VALUE.");
453 pw.println(" Options are:");
454 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
455 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100456 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100457 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
458 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
459 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
460 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
461 pw.println(" cc clear-values [-s SLOT_ID]");
462 pw.println(" Clear all carrier override values that has previously been set");
463 pw.println(" with set-value");
464 pw.println(" Options are:");
465 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
466 pw.println(" is specified, it will choose the default voice SIM slot.");
467 }
468
Hui Wang0866fcc2020-10-12 12:14:23 -0700469 private void onHelpGba() {
470 PrintWriter pw = getOutPrintWriter();
471 pw.println("Gba Commands:");
472 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
473 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
474 pw.println(" Options are:");
475 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
476 pw.println(" is specified, it will choose the default voice SIM slot.");
477 pw.println(" gba get-service [-s SLOT_ID]");
478 pw.println(" Gets the package name of the currently defined GbaService.");
479 pw.println(" Options are:");
480 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
481 pw.println(" is specified, it will choose the default voice SIM slot.");
482 pw.println(" gba set-release [-s SLOT_ID] n");
483 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
484 pw.println(" Do not release/unbind if n is -1.");
485 pw.println(" Options are:");
486 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
487 pw.println(" is specified, it will choose the default voice SIM slot.");
488 pw.println(" gba get-release [-s SLOT_ID]");
489 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
490 pw.println(" Options are:");
491 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
492 pw.println(" is specified, it will choose the default voice SIM slot.");
493 }
494
Hui Wang068ab862020-10-31 05:12:53 +0000495 private void onHelpSrc() {
496 PrintWriter pw = getOutPrintWriter();
497 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wang19a21872021-02-19 20:45:36 -0800498 pw.println(" src set-test-enabled true|false");
499 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
500 pw.println(" The value could be true, false, or null(undefined).");
501 pw.println(" src get-test-enabled");
502 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang068ab862020-10-31 05:12:53 +0000503 pw.println(" src set-device-enabled true|false|null");
504 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
505 pw.println(" The value could be true, false, or null(undefined).");
506 pw.println(" src get-device-enabled");
507 pw.println(" Gets the device config for RCS VoLTE single registration.");
508 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
509 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
510 pw.println(" The value could be true, false, or null(undefined).");
511 pw.println(" Options are:");
512 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
513 pw.println(" is specified, it will choose the default voice SIM slot.");
514 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
515 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
516 pw.println(" Options are:");
517 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
518 pw.println(" is specified, it will choose the default voice SIM slot.");
519 }
520
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700521 private int handleImsCommand() {
522 String arg = getNextArg();
523 if (arg == null) {
524 onHelpIms();
525 return 0;
526 }
527
528 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800529 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700530 return handleImsSetServiceCommand();
531 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800532 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700533 return handleImsGetServiceCommand();
534 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800535 case IMS_CLEAR_SERVICE_OVERRIDE: {
536 return handleImsClearCarrierServiceCommand();
537 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700538 case IMS_ENABLE: {
539 return handleEnableIms();
540 }
541 case IMS_DISABLE: {
542 return handleDisableIms();
543 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700544 case IMS_CEP: {
545 return handleCepChange();
546 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700547 }
548
549 return -1;
550 }
551
Shuo Qianf5125122019-12-16 17:03:07 -0800552 private int handleDataTestModeCommand() {
553 PrintWriter errPw = getErrPrintWriter();
554 String arg = getNextArgRequired();
555 if (arg == null) {
556 onHelpDataTestMode();
557 return 0;
558 }
559 switch (arg) {
560 case DATA_ENABLE: {
561 try {
562 mInterface.enableDataConnectivity();
563 } catch (RemoteException ex) {
564 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
565 errPw.println("Exception: " + ex.getMessage());
566 return -1;
567 }
568 break;
569 }
570 case DATA_DISABLE: {
571 try {
572 mInterface.disableDataConnectivity();
573 } catch (RemoteException ex) {
574 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
575 errPw.println("Exception: " + ex.getMessage());
576 return -1;
577 }
578 break;
579 }
580 default:
581 onHelpDataTestMode();
582 break;
583 }
584 return 0;
585 }
586
sqian9d4df8b2019-01-15 18:32:07 -0800587 private int handleEmergencyNumberTestModeCommand() {
588 PrintWriter errPw = getErrPrintWriter();
589 String opt = getNextOption();
590 if (opt == null) {
591 onHelpEmergencyNumber();
592 return 0;
593 }
594
595 switch (opt) {
596 case "-a": {
597 String emergencyNumberCmd = getNextArgRequired();
598 if (emergencyNumberCmd == null
599 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700600 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800601 + " to be specified after -a in the command ");
602 return -1;
603 }
604 try {
605 mInterface.updateEmergencyNumberListTestMode(
606 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
607 new EmergencyNumber(emergencyNumberCmd, "", "",
608 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
609 new ArrayList<String>(),
610 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
611 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
612 } catch (RemoteException ex) {
613 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
614 + ", error " + ex.getMessage());
615 errPw.println("Exception: " + ex.getMessage());
616 return -1;
617 }
618 break;
619 }
620 case "-c": {
621 try {
622 mInterface.updateEmergencyNumberListTestMode(
623 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
624 } catch (RemoteException ex) {
625 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
626 errPw.println("Exception: " + ex.getMessage());
627 return -1;
628 }
629 break;
630 }
631 case "-r": {
632 String emergencyNumberCmd = getNextArgRequired();
633 if (emergencyNumberCmd == null
634 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700635 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800636 + " to be specified after -r in the command ");
637 return -1;
638 }
639 try {
640 mInterface.updateEmergencyNumberListTestMode(
641 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
642 new EmergencyNumber(emergencyNumberCmd, "", "",
643 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
644 new ArrayList<String>(),
645 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
646 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
647 } catch (RemoteException ex) {
648 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
649 + ", error " + ex.getMessage());
650 errPw.println("Exception: " + ex.getMessage());
651 return -1;
652 }
653 break;
654 }
655 case "-p": {
656 try {
657 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
658 } catch (RemoteException ex) {
659 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
660 errPw.println("Exception: " + ex.getMessage());
661 return -1;
662 }
663 break;
664 }
665 default:
666 onHelpEmergencyNumber();
667 break;
668 }
669 return 0;
670 }
671
Hall Liud892bec2018-11-30 14:51:45 -0800672 private int handleNumberVerificationCommand() {
673 String arg = getNextArg();
674 if (arg == null) {
675 onHelpNumberVerification();
676 return 0;
677 }
678
Hall Liuca5af3a2018-12-04 16:58:23 -0800679 if (!checkShellUid()) {
680 return -1;
681 }
682
Hall Liud892bec2018-11-30 14:51:45 -0800683 switch (arg) {
684 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800685 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
686 return 0;
687 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800688 case NUMBER_VERIFICATION_FAKE_CALL: {
689 boolean val = NumberVerificationManager.getInstance()
690 .checkIncomingCall(getNextArg());
691 getOutPrintWriter().println(val ? "1" : "0");
692 return 0;
693 }
Hall Liud892bec2018-11-30 14:51:45 -0800694 }
695
696 return -1;
697 }
698
Tyler Gunn92479152021-01-20 16:30:10 -0800699 private int handleD2dCommand() {
700 String arg = getNextArg();
701 if (arg == null) {
702 onHelpD2D();
703 return 0;
704 }
705
706 switch (arg) {
707 case D2D_SEND: {
708 return handleD2dSendCommand();
709 }
710 }
711
712 return -1;
713 }
714
715 private int handleD2dSendCommand() {
716 PrintWriter errPw = getErrPrintWriter();
717 String opt;
718 int messageType = -1;
719 int messageValue = -1;
720
721
722 String arg = getNextArg();
723 if (arg == null) {
724 onHelpD2D();
725 return 0;
726 }
727 try {
728 messageType = Integer.parseInt(arg);
729 } catch (NumberFormatException e) {
730 errPw.println("message type must be a valid integer");
731 return -1;
732 }
733
734 arg = getNextArg();
735 if (arg == null) {
736 onHelpD2D();
737 return 0;
738 }
739 try {
740 messageValue = Integer.parseInt(arg);
741 } catch (NumberFormatException e) {
742 errPw.println("message value must be a valid integer");
743 return -1;
744 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800745
Tyler Gunn92479152021-01-20 16:30:10 -0800746 try {
747 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
748 } catch (RemoteException e) {
749 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
750 errPw.println("Exception: " + e.getMessage());
751 return -1;
752 }
753
754 return 0;
755 }
756
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700757 // ims set-ims-service
758 private int handleImsSetServiceCommand() {
759 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700760 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700761 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800762 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700763
764 String opt;
765 while ((opt = getNextOption()) != null) {
766 switch (opt) {
767 case "-s": {
768 try {
769 slotId = Integer.parseInt(getNextArgRequired());
770 } catch (NumberFormatException e) {
771 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
772 return -1;
773 }
774 break;
775 }
776 case "-c": {
777 isCarrierService = true;
778 break;
779 }
780 case "-d": {
781 isCarrierService = false;
782 break;
783 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800784 case "-f": {
785 String featureString = getNextArgRequired();
786 String[] features = featureString.split(",");
787 for (int i = 0; i < features.length; i++) {
788 try {
789 Integer result = Integer.parseInt(features[i]);
790 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
791 || result >= ImsFeature.FEATURE_MAX) {
792 errPw.println("ims set-ims-service -f " + result
793 + " is an invalid feature.");
794 return -1;
795 }
796 featuresList.add(result);
797 } catch (NumberFormatException e) {
798 errPw.println("ims set-ims-service -f tried to parse " + features[i]
799 + " as an integer.");
800 return -1;
801 }
802 }
803 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700804 }
805 }
806 // Mandatory param, either -c or -d
807 if (isCarrierService == null) {
808 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
809 return -1;
810 }
811
812 String packageName = getNextArg();
813
814 try {
815 if (packageName == null) {
816 packageName = "";
817 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800818 int[] featureArray = new int[featuresList.size()];
819 for (int i = 0; i < featuresList.size(); i++) {
820 featureArray[i] = featuresList.get(i);
821 }
822 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
823 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700824 if (VDBG) {
825 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800826 + (isCarrierService ? "-c " : "-d ")
827 + "-f " + featuresList + " "
828 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700829 }
830 getOutPrintWriter().println(result);
831 } catch (RemoteException e) {
832 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800833 + (isCarrierService ? "-c " : "-d ")
834 + "-f " + featuresList + " "
835 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700836 errPw.println("Exception: " + e.getMessage());
837 return -1;
838 }
839 return 0;
840 }
841
Brad Ebinger999d3302020-11-25 14:31:39 -0800842 // ims clear-ims-service-override
843 private int handleImsClearCarrierServiceCommand() {
844 PrintWriter errPw = getErrPrintWriter();
845 int slotId = getDefaultSlot();
846
847 String opt;
848 while ((opt = getNextOption()) != null) {
849 switch (opt) {
850 case "-s": {
851 try {
852 slotId = Integer.parseInt(getNextArgRequired());
853 } catch (NumberFormatException e) {
854 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
855 return -1;
856 }
857 break;
858 }
859 }
860 }
861
862 try {
863 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
864 if (VDBG) {
865 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
866 + ", result=" + result);
867 }
868 getOutPrintWriter().println(result);
869 } catch (RemoteException e) {
870 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
871 + ", error" + e.getMessage());
872 errPw.println("Exception: " + e.getMessage());
873 return -1;
874 }
875 return 0;
876 }
877
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700878 // ims get-ims-service
879 private int handleImsGetServiceCommand() {
880 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700881 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700882 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800883 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700884
885 String opt;
886 while ((opt = getNextOption()) != null) {
887 switch (opt) {
888 case "-s": {
889 try {
890 slotId = Integer.parseInt(getNextArgRequired());
891 } catch (NumberFormatException e) {
892 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
893 return -1;
894 }
895 break;
896 }
897 case "-c": {
898 isCarrierService = true;
899 break;
900 }
901 case "-d": {
902 isCarrierService = false;
903 break;
904 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800905 case "-f": {
906 try {
907 featureType = Integer.parseInt(getNextArg());
908 } catch (NumberFormatException e) {
909 errPw.println("ims get-ims-service -f requires valid integer as feature.");
910 return -1;
911 }
912 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
913 || featureType >= ImsFeature.FEATURE_MAX) {
914 errPw.println("ims get-ims-service -f invalid feature.");
915 return -1;
916 }
917 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700918 }
919 }
920 // Mandatory param, either -c or -d
921 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800922 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700923 return -1;
924 }
925
926 String result;
927 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800928 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700929 } catch (RemoteException e) {
930 return -1;
931 }
932 if (VDBG) {
933 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800934 + (isCarrierService ? "-c " : "-d ")
935 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
936 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700937 }
938 getOutPrintWriter().println(result);
939 return 0;
940 }
941
942 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700943 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700944 String opt;
945 while ((opt = getNextOption()) != null) {
946 switch (opt) {
947 case "-s": {
948 try {
949 slotId = Integer.parseInt(getNextArgRequired());
950 } catch (NumberFormatException e) {
951 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
952 return -1;
953 }
954 break;
955 }
956 }
957 }
958 try {
959 mInterface.enableIms(slotId);
960 } catch (RemoteException e) {
961 return -1;
962 }
963 if (VDBG) {
964 Log.v(LOG_TAG, "ims enable -s " + slotId);
965 }
966 return 0;
967 }
968
969 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700970 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700971 String opt;
972 while ((opt = getNextOption()) != null) {
973 switch (opt) {
974 case "-s": {
975 try {
976 slotId = Integer.parseInt(getNextArgRequired());
977 } catch (NumberFormatException e) {
978 getErrPrintWriter().println(
979 "ims disable requires an integer as a SLOT_ID.");
980 return -1;
981 }
982 break;
983 }
984 }
985 }
986 try {
987 mInterface.disableIms(slotId);
988 } catch (RemoteException e) {
989 return -1;
990 }
991 if (VDBG) {
992 Log.v(LOG_TAG, "ims disable -s " + slotId);
993 }
994 return 0;
995 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700996
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700997 private int handleCepChange() {
998 Log.i(LOG_TAG, "handleCepChange");
999 String opt = getNextArg();
1000 if (opt == null) {
1001 return -1;
1002 }
1003 boolean isCepEnabled = opt.equals("enable");
1004
1005 try {
1006 mInterface.setCepEnabled(isCepEnabled);
1007 } catch (RemoteException e) {
1008 return -1;
1009 }
1010 return 0;
1011 }
1012
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001013 private int getDefaultSlot() {
1014 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1015 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1016 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1017 // If there is no default, default to slot 0.
1018 slotId = DEFAULT_PHONE_ID;
1019 }
1020 return slotId;
1021 }
sqian2fff4a32018-11-05 14:18:37 -08001022
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001023 // Parse options related to Carrier Config Commands.
1024 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001025 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001026 CcOptionParseResult result = new CcOptionParseResult();
1027 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1028 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001029
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001030 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001031 while ((opt = getNextOption()) != null) {
1032 switch (opt) {
1033 case "-s": {
1034 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001035 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1036 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1037 errPw.println(tag + "No valid subscription found.");
1038 return null;
1039 }
1040
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001041 } catch (IllegalArgumentException e) {
1042 // Missing slot id
1043 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001044 return null;
1045 }
1046 break;
1047 }
1048 case "-p": {
1049 if (allowOptionPersistent) {
1050 result.mPersistent = true;
1051 } else {
1052 errPw.println(tag + "Unexpected option " + opt);
1053 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001054 }
1055 break;
1056 }
1057 default: {
1058 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001059 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001060 }
1061 }
1062 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001063 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001064 }
1065
1066 private int slotStringToSubId(String tag, String slotString) {
1067 int slotId = -1;
1068 try {
1069 slotId = Integer.parseInt(slotString);
1070 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001071 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1072 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1073 }
1074
1075 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001076 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1077 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1078 }
1079
Qiong Liuf25799b2020-09-10 10:13:46 +08001080 Phone phone = PhoneFactory.getPhone(slotId);
1081 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001082 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1083 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1084 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001085 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001086 }
1087
Hall Liud892bec2018-11-30 14:51:45 -08001088 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001089 // adb can run as root or as shell, depending on whether the device is rooted.
1090 return Binder.getCallingUid() == Process.SHELL_UID
1091 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001092 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001093
1094 private int handleCcCommand() {
1095 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1096 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001097 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001098 getErrPrintWriter().println("cc: Permission denied.");
1099 return -1;
1100 }
1101
1102 String arg = getNextArg();
1103 if (arg == null) {
1104 onHelpCc();
1105 return 0;
1106 }
1107
1108 switch (arg) {
1109 case CC_GET_VALUE: {
1110 return handleCcGetValue();
1111 }
1112 case CC_SET_VALUE: {
1113 return handleCcSetValue();
1114 }
1115 case CC_CLEAR_VALUES: {
1116 return handleCcClearValues();
1117 }
1118 default: {
1119 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1120 }
1121 }
1122 return -1;
1123 }
1124
1125 // cc get-value
1126 private int handleCcGetValue() {
1127 PrintWriter errPw = getErrPrintWriter();
1128 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1129 String key = null;
1130
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001131 // Parse all options
1132 CcOptionParseResult options = parseCcOptions(tag, false);
1133 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001134 return -1;
1135 }
1136
1137 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001138 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001139 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001140 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001141 return -1;
1142 }
1143
1144 // Get the key.
1145 key = getNextArg();
1146 if (key != null) {
1147 // A key was provided. Verify if it is a valid key
1148 if (!bundle.containsKey(key)) {
1149 errPw.println(tag + key + " is not a valid key.");
1150 return -1;
1151 }
1152
1153 // Print the carrier config value for key.
1154 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1155 } else {
1156 // No key provided. Show all values.
1157 // Iterate over a sorted list of all carrier config keys and print them.
1158 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1159 for (String k : sortedSet) {
1160 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1161 }
1162 }
1163 return 0;
1164 }
1165
1166 // cc set-value
1167 private int handleCcSetValue() {
1168 PrintWriter errPw = getErrPrintWriter();
1169 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1170
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001171 // Parse all options
1172 CcOptionParseResult options = parseCcOptions(tag, true);
1173 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001174 return -1;
1175 }
1176
1177 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001178 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001179 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001180 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001181 return -1;
1182 }
1183
1184 // Get the key.
1185 String key = getNextArg();
1186 if (key == null || key.equals("")) {
1187 errPw.println(tag + "KEY is missing");
1188 return -1;
1189 }
1190
1191 // Verify if the key is valid
1192 if (!originalValues.containsKey(key)) {
1193 errPw.println(tag + key + " is not a valid key.");
1194 return -1;
1195 }
1196
1197 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1198 ArrayList<String> valueList = new ArrayList<String>();
1199 while (peekNextArg() != null) {
1200 valueList.add(getNextArg());
1201 }
1202
1203 // Find the type of the carrier config value
1204 CcType type = getType(tag, key, originalValues);
1205 if (type == CcType.UNKNOWN) {
1206 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1207 return -1;
1208 }
1209
1210 // Create an override bundle containing the key and value that should be overriden.
1211 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1212 if (overrideBundle == null) {
1213 return -1;
1214 }
1215
1216 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001217 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001218
1219 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001220 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001221 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001222 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001223 return -1;
1224 }
1225
1226 // Print the original and new value.
1227 String originalValueString = ccValueToString(key, type, originalValues);
1228 String newValueString = ccValueToString(key, type, newValues);
1229 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1230 getOutPrintWriter().println("New value: \n" + newValueString);
1231
1232 return 0;
1233 }
1234
1235 // cc clear-values
1236 private int handleCcClearValues() {
1237 PrintWriter errPw = getErrPrintWriter();
1238 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1239
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001240 // Parse all options
1241 CcOptionParseResult options = parseCcOptions(tag, false);
1242 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001243 return -1;
1244 }
1245
1246 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001247 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001248 getOutPrintWriter()
1249 .println("All previously set carrier config override values has been cleared");
1250 return 0;
1251 }
1252
1253 private CcType getType(String tag, String key, PersistableBundle bundle) {
1254 // Find the type by checking the type of the current value stored in the bundle.
1255 Object value = bundle.get(key);
1256
1257 if (CC_TYPE_MAP.containsKey(key)) {
1258 return CC_TYPE_MAP.get(key);
1259 } else if (value != null) {
1260 if (value instanceof Boolean) {
1261 return CcType.BOOLEAN;
1262 } else if (value instanceof Double) {
1263 return CcType.DOUBLE;
1264 } else if (value instanceof double[]) {
1265 return CcType.DOUBLE_ARRAY;
1266 } else if (value instanceof Integer) {
1267 return CcType.INT;
1268 } else if (value instanceof int[]) {
1269 return CcType.INT_ARRAY;
1270 } else if (value instanceof Long) {
1271 return CcType.LONG;
1272 } else if (value instanceof long[]) {
1273 return CcType.LONG_ARRAY;
1274 } else if (value instanceof String) {
1275 return CcType.STRING;
1276 } else if (value instanceof String[]) {
1277 return CcType.STRING_ARRAY;
1278 }
1279 } else {
1280 // Current value was null and can therefore not be used in order to find the type.
1281 // Check the name of the key to infer the type. This check is not needed for primitive
1282 // data types (boolean, double, int and long), since they can not be null.
1283 if (key.endsWith("double_array")) {
1284 return CcType.DOUBLE_ARRAY;
1285 }
1286 if (key.endsWith("int_array")) {
1287 return CcType.INT_ARRAY;
1288 }
1289 if (key.endsWith("long_array")) {
1290 return CcType.LONG_ARRAY;
1291 }
1292 if (key.endsWith("string")) {
1293 return CcType.STRING;
1294 }
1295 if (key.endsWith("string_array") || key.endsWith("strings")) {
1296 return CcType.STRING_ARRAY;
1297 }
1298 }
1299
1300 // Not possible to infer the type by looking at the current value or the key.
1301 PrintWriter errPw = getErrPrintWriter();
1302 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1303 return CcType.UNKNOWN;
1304 }
1305
1306 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1307 String result;
1308 StringBuilder valueString = new StringBuilder();
1309 String typeString = type.toString();
1310 Object value = bundle.get(key);
1311
1312 if (value == null) {
1313 valueString.append("null");
1314 } else {
1315 switch (type) {
1316 case DOUBLE_ARRAY: {
1317 // Format the string representation of the int array as value1 value2......
1318 double[] valueArray = (double[]) value;
1319 for (int i = 0; i < valueArray.length; i++) {
1320 if (i != 0) {
1321 valueString.append(" ");
1322 }
1323 valueString.append(valueArray[i]);
1324 }
1325 break;
1326 }
1327 case INT_ARRAY: {
1328 // Format the string representation of the int array as value1 value2......
1329 int[] valueArray = (int[]) value;
1330 for (int i = 0; i < valueArray.length; i++) {
1331 if (i != 0) {
1332 valueString.append(" ");
1333 }
1334 valueString.append(valueArray[i]);
1335 }
1336 break;
1337 }
1338 case LONG_ARRAY: {
1339 // Format the string representation of the int array as value1 value2......
1340 long[] valueArray = (long[]) value;
1341 for (int i = 0; i < valueArray.length; i++) {
1342 if (i != 0) {
1343 valueString.append(" ");
1344 }
1345 valueString.append(valueArray[i]);
1346 }
1347 break;
1348 }
1349 case STRING: {
1350 valueString.append("\"" + value.toString() + "\"");
1351 break;
1352 }
1353 case STRING_ARRAY: {
1354 // Format the string representation of the string array as "value1" "value2"....
1355 String[] valueArray = (String[]) value;
1356 for (int i = 0; i < valueArray.length; i++) {
1357 if (i != 0) {
1358 valueString.append(" ");
1359 }
1360 if (valueArray[i] != null) {
1361 valueString.append("\"" + valueArray[i] + "\"");
1362 } else {
1363 valueString.append("null");
1364 }
1365 }
1366 break;
1367 }
1368 default: {
1369 valueString.append(value.toString());
1370 }
1371 }
1372 }
1373 return String.format("%-70s %-15s %s", key, typeString, valueString);
1374 }
1375
1376 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1377 ArrayList<String> valueList) {
1378 PrintWriter errPw = getErrPrintWriter();
1379 PersistableBundle bundle = new PersistableBundle();
1380
1381 // First verify that a valid number of values has been provided for the type.
1382 switch (type) {
1383 case BOOLEAN:
1384 case DOUBLE:
1385 case INT:
1386 case LONG: {
1387 if (valueList.size() != 1) {
1388 errPw.println(tag + "Expected 1 value for type " + type
1389 + ". Found: " + valueList.size());
1390 return null;
1391 }
1392 break;
1393 }
1394 case STRING: {
1395 if (valueList.size() > 1) {
1396 errPw.println(tag + "Expected 0 or 1 values for type " + type
1397 + ". Found: " + valueList.size());
1398 return null;
1399 }
1400 break;
1401 }
1402 }
1403
1404 // Parse the value according to type and add it to the Bundle.
1405 switch (type) {
1406 case BOOLEAN: {
1407 if ("true".equalsIgnoreCase(valueList.get(0))) {
1408 bundle.putBoolean(key, true);
1409 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1410 bundle.putBoolean(key, false);
1411 } else {
1412 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1413 return null;
1414 }
1415 break;
1416 }
1417 case DOUBLE: {
1418 try {
1419 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1420 } catch (NumberFormatException nfe) {
1421 // Not a valid double
1422 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1423 return null;
1424 }
1425 break;
1426 }
1427 case DOUBLE_ARRAY: {
1428 double[] valueDoubleArray = null;
1429 if (valueList.size() > 0) {
1430 valueDoubleArray = new double[valueList.size()];
1431 for (int i = 0; i < valueList.size(); i++) {
1432 try {
1433 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1434 } catch (NumberFormatException nfe) {
1435 // Not a valid double
1436 errPw.println(
1437 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1438 return null;
1439 }
1440 }
1441 }
1442 bundle.putDoubleArray(key, valueDoubleArray);
1443 break;
1444 }
1445 case INT: {
1446 try {
1447 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1448 } catch (NumberFormatException nfe) {
1449 // Not a valid integer
1450 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1451 return null;
1452 }
1453 break;
1454 }
1455 case INT_ARRAY: {
1456 int[] valueIntArray = null;
1457 if (valueList.size() > 0) {
1458 valueIntArray = new int[valueList.size()];
1459 for (int i = 0; i < valueList.size(); i++) {
1460 try {
1461 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1462 } catch (NumberFormatException nfe) {
1463 // Not a valid integer
1464 errPw.println(tag
1465 + "Unable to parse " + valueList.get(i) + " as an integer.");
1466 return null;
1467 }
1468 }
1469 }
1470 bundle.putIntArray(key, valueIntArray);
1471 break;
1472 }
1473 case LONG: {
1474 try {
1475 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1476 } catch (NumberFormatException nfe) {
1477 // Not a valid long
1478 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1479 return null;
1480 }
1481 break;
1482 }
1483 case LONG_ARRAY: {
1484 long[] valueLongArray = null;
1485 if (valueList.size() > 0) {
1486 valueLongArray = new long[valueList.size()];
1487 for (int i = 0; i < valueList.size(); i++) {
1488 try {
1489 valueLongArray[i] = Long.parseLong(valueList.get(i));
1490 } catch (NumberFormatException nfe) {
1491 // Not a valid long
1492 errPw.println(
1493 tag + "Unable to parse " + valueList.get(i) + " as a long");
1494 return null;
1495 }
1496 }
1497 }
1498 bundle.putLongArray(key, valueLongArray);
1499 break;
1500 }
1501 case STRING: {
1502 String value = null;
1503 if (valueList.size() > 0) {
1504 value = valueList.get(0);
1505 }
1506 bundle.putString(key, value);
1507 break;
1508 }
1509 case STRING_ARRAY: {
1510 String[] valueStringArray = null;
1511 if (valueList.size() > 0) {
1512 valueStringArray = new String[valueList.size()];
1513 valueList.toArray(valueStringArray);
1514 }
1515 bundle.putStringArray(key, valueStringArray);
1516 break;
1517 }
1518 }
1519 return bundle;
1520 }
Shuo Qian489d9282020-07-09 11:30:03 -07001521
1522 private int handleEndBlockSuppressionCommand() {
1523 if (!checkShellUid()) {
1524 return -1;
1525 }
1526
1527 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1528 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1529 }
1530 return 0;
1531 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001532
Michele Berionne38c1afa2020-12-28 20:23:16 +00001533 private int handleRestartModemCommand() {
1534 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1535 // non user build.
1536 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1537 getErrPrintWriter().println("RestartModem: Permission denied.");
1538 return -1;
1539 }
1540
1541 boolean result = TelephonyManager.getDefault().rebootRadio();
1542 getOutPrintWriter().println(result);
1543
1544 return result ? 0 : -1;
1545 }
1546
Michele Berionned9fbae52020-11-13 02:36:59 +00001547 private int handleUnattendedReboot() {
1548 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1549 // non user build.
1550 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1551 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1552 return -1;
1553 }
1554
1555 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1556 getOutPrintWriter().println("result: " + result);
1557
1558 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1559 }
1560
Hui Wang0866fcc2020-10-12 12:14:23 -07001561 private int handleGbaCommand() {
1562 String arg = getNextArg();
1563 if (arg == null) {
1564 onHelpGba();
1565 return 0;
1566 }
1567
1568 switch (arg) {
1569 case GBA_SET_SERVICE: {
1570 return handleGbaSetServiceCommand();
1571 }
1572 case GBA_GET_SERVICE: {
1573 return handleGbaGetServiceCommand();
1574 }
1575 case GBA_SET_RELEASE_TIME: {
1576 return handleGbaSetReleaseCommand();
1577 }
1578 case GBA_GET_RELEASE_TIME: {
1579 return handleGbaGetReleaseCommand();
1580 }
1581 }
1582
1583 return -1;
1584 }
1585
1586 private int getSubId(String cmd) {
1587 int slotId = getDefaultSlot();
1588 String opt = getNextOption();
1589 if (opt != null && opt.equals("-s")) {
1590 try {
1591 slotId = Integer.parseInt(getNextArgRequired());
1592 } catch (NumberFormatException e) {
1593 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1594 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1595 }
1596 }
1597 int[] subIds = SubscriptionManager.getSubId(slotId);
1598 return subIds[0];
1599 }
1600
1601 private int handleGbaSetServiceCommand() {
1602 int subId = getSubId("gba set-service");
1603 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1604 return -1;
1605 }
1606
1607 String packageName = getNextArg();
1608 try {
1609 if (packageName == null) {
1610 packageName = "";
1611 }
1612 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1613 if (VDBG) {
1614 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1615 + packageName + ", result=" + result);
1616 }
1617 getOutPrintWriter().println(result);
1618 } catch (RemoteException e) {
1619 Log.w(LOG_TAG, "gba set-service " + subId + " "
1620 + packageName + ", error" + e.getMessage());
1621 getErrPrintWriter().println("Exception: " + e.getMessage());
1622 return -1;
1623 }
1624 return 0;
1625 }
1626
1627 private int handleGbaGetServiceCommand() {
1628 String result;
1629
1630 int subId = getSubId("gba get-service");
1631 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1632 return -1;
1633 }
1634
1635 try {
1636 result = mInterface.getBoundGbaService(subId);
1637 } catch (RemoteException e) {
1638 return -1;
1639 }
1640 if (VDBG) {
1641 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1642 }
1643 getOutPrintWriter().println(result);
1644 return 0;
1645 }
1646
1647 private int handleGbaSetReleaseCommand() {
1648 //the release time value could be -1
1649 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1650 : SubscriptionManager.getDefaultSubscriptionId();
1651 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1652 return -1;
1653 }
1654
1655 String intervalStr = getNextArg();
1656 if (intervalStr == null) {
1657 return -1;
1658 }
1659
1660 try {
1661 int interval = Integer.parseInt(intervalStr);
1662 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1663 if (VDBG) {
1664 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1665 + intervalStr + ", result=" + result);
1666 }
1667 getOutPrintWriter().println(result);
1668 } catch (NumberFormatException | RemoteException e) {
1669 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1670 + intervalStr + ", error" + e.getMessage());
1671 getErrPrintWriter().println("Exception: " + e.getMessage());
1672 return -1;
1673 }
1674 return 0;
1675 }
1676
1677 private int handleGbaGetReleaseCommand() {
1678 int subId = getSubId("gba get-release");
1679 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1680 return -1;
1681 }
1682
1683 int result = 0;
1684 try {
1685 result = mInterface.getGbaReleaseTime(subId);
1686 } catch (RemoteException e) {
1687 return -1;
1688 }
1689 if (VDBG) {
1690 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1691 }
1692 getOutPrintWriter().println(result);
1693 return 0;
1694 }
Hui Wang068ab862020-10-31 05:12:53 +00001695
1696 private int handleSingleRegistrationConfigCommand() {
1697 String arg = getNextArg();
1698 if (arg == null) {
1699 onHelpSrc();
1700 return 0;
1701 }
1702
1703 switch (arg) {
Hui Wang19a21872021-02-19 20:45:36 -08001704 case SRC_SET_TEST_ENABLED: {
1705 return handleSrcSetTestEnabledCommand();
1706 }
1707 case SRC_GET_TEST_ENABLED: {
1708 return handleSrcGetTestEnabledCommand();
1709 }
Hui Wang068ab862020-10-31 05:12:53 +00001710 case SRC_SET_DEVICE_ENABLED: {
1711 return handleSrcSetDeviceEnabledCommand();
1712 }
1713 case SRC_GET_DEVICE_ENABLED: {
1714 return handleSrcGetDeviceEnabledCommand();
1715 }
1716 case SRC_SET_CARRIER_ENABLED: {
1717 return handleSrcSetCarrierEnabledCommand();
1718 }
1719 case SRC_GET_CARRIER_ENABLED: {
1720 return handleSrcGetCarrierEnabledCommand();
1721 }
1722 }
1723
1724 return -1;
1725 }
1726
James.cf Linbcdf8b32021-01-14 16:44:13 +08001727 private int handleRcsUceCommand() {
1728 String arg = getNextArg();
1729 if (arg == null) {
Brad Ebingerd4c5bde2021-02-12 06:18:28 +00001730 onHelpUce();
1731 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001732 }
1733
1734 switch (arg) {
1735 case UCE_REMOVE_EAB_CONTACT:
1736 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001737 case UCE_GET_EAB_CONTACT:
1738 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001739 case UCE_GET_DEVICE_ENABLED:
1740 return handleUceGetDeviceEnabledCommand();
1741 case UCE_SET_DEVICE_ENABLED:
1742 return handleUceSetDeviceEnabledCommand();
Brad Ebingerd4c5bde2021-02-12 06:18:28 +00001743 case UCE_OVERRIDE_PUBLISH_CAPS:
1744 return handleUceOverridePublishCaps();
1745 case UCE_GET_LAST_PIDF_XML:
1746 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001747 }
1748 return -1;
1749 }
1750
1751 private int handleRemovingEabContactCommand() {
1752 int subId = getSubId("uce remove-eab-contact");
1753 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1754 return -1;
1755 }
1756
1757 String phoneNumber = getNextArgRequired();
1758 if (TextUtils.isEmpty(phoneNumber)) {
1759 return -1;
1760 }
1761 int result = 0;
1762 try {
1763 result = mInterface.removeContactFromEab(subId, phoneNumber);
1764 } catch (RemoteException e) {
1765 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1766 getErrPrintWriter().println("Exception: " + e.getMessage());
1767 return -1;
1768 }
1769
1770 if (VDBG) {
1771 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1772 }
calvinpan293ea1b2021-02-04 17:52:13 +08001773 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001774 }
1775
calvinpane4a8a1d2021-01-25 13:51:18 +08001776 private int handleGettingEabContactCommand() {
1777 String phoneNumber = getNextArgRequired();
1778 if (TextUtils.isEmpty(phoneNumber)) {
1779 return -1;
1780 }
1781 String result = "";
1782 try {
1783 result = mInterface.getContactFromEab(phoneNumber);
1784
1785 } catch (RemoteException e) {
1786 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1787 getErrPrintWriter().println("Exception: " + e.getMessage());
1788 return -1;
1789 }
1790
1791 if (VDBG) {
1792 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1793 }
calvinpan293ea1b2021-02-04 17:52:13 +08001794 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001795 return 0;
1796 }
1797
1798 private int handleUceGetDeviceEnabledCommand() {
1799 boolean result = false;
1800 try {
1801 result = mInterface.getDeviceUceEnabled();
1802 } catch (RemoteException e) {
1803 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1804 return -1;
1805 }
1806 if (VDBG) {
1807 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1808 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001809 getOutPrintWriter().println(result);
1810 return 0;
1811 }
1812
James.cf Lin4b784aa2021-01-31 03:25:15 +08001813 private int handleUceSetDeviceEnabledCommand() {
1814 String enabledStr = getNextArg();
1815 if (TextUtils.isEmpty(enabledStr)) {
1816 return -1;
1817 }
1818
1819 try {
1820 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1821 mInterface.setDeviceUceEnabled(isEnabled);
1822 if (VDBG) {
1823 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1824 }
1825 } catch (NumberFormatException | RemoteException e) {
1826 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1827 getErrPrintWriter().println("Exception: " + e.getMessage());
1828 return -1;
1829 }
1830 return 0;
1831 }
1832
Hui Wang19a21872021-02-19 20:45:36 -08001833 private int handleSrcSetTestEnabledCommand() {
1834 String enabledStr = getNextArg();
1835 if (enabledStr == null) {
1836 return -1;
1837 }
1838
1839 try {
1840 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1841 if (VDBG) {
1842 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1843 }
1844 getOutPrintWriter().println("Done");
1845 } catch (NumberFormatException | RemoteException e) {
1846 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1847 getErrPrintWriter().println("Exception: " + e.getMessage());
1848 return -1;
1849 }
1850 return 0;
1851 }
1852
1853 private int handleSrcGetTestEnabledCommand() {
1854 boolean result = false;
1855 try {
1856 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1857 } catch (RemoteException e) {
1858 return -1;
1859 }
1860 if (VDBG) {
1861 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1862 }
1863 getOutPrintWriter().println(result);
1864 return 0;
1865 }
1866
Brad Ebingerd4c5bde2021-02-12 06:18:28 +00001867 private int handleUceOverridePublishCaps() {
1868 int subId = getSubId("uce override-published-caps");
1869 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1870 return -1;
1871 }
1872 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
1873 String operation = getNextArgRequired();
1874 String caps = getNextArg();
1875 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
1876 && !"list".equals(operation)) {
1877 getErrPrintWriter().println("Invalid operation: " + operation);
1878 return -1;
1879 }
1880
1881 // add/remove requires capabilities to be specified.
1882 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
1883 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
1884 + "specified");
1885 return -1;
1886 }
1887
1888 ArraySet<String> capSet = new ArraySet<>();
1889 if (!TextUtils.isEmpty(caps)) {
1890 String[] capArray = caps.split(":");
1891 for (String cap : capArray) {
1892 // Allow unknown tags to be passed in as well.
1893 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
1894 }
1895 }
1896
1897 RcsContactUceCapability result = null;
1898 try {
1899 switch (operation) {
1900 case "add":
1901 result = mInterface.addUceRegistrationOverrideShell(subId,
1902 new ArrayList<>(capSet));
1903 break;
1904 case "remove":
1905 result = mInterface.removeUceRegistrationOverrideShell(subId,
1906 new ArrayList<>(capSet));
1907 break;
1908 case "clear":
1909 result = mInterface.clearUceRegistrationOverrideShell(subId);
1910 break;
1911 case "list":
1912 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
1913 break;
1914 }
1915 } catch (RemoteException e) {
1916 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
1917 getErrPrintWriter().println("Exception: " + e.getMessage());
1918 return -1;
1919 } catch (ServiceSpecificException sse) {
1920 // Reconstruct ImsException
1921 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
1922 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
1923 getErrPrintWriter().println("Exception: " + imsException);
1924 return -1;
1925 }
1926 if (result == null) {
1927 getErrPrintWriter().println("Service not available");
1928 return -1;
1929 }
1930 getOutPrintWriter().println(result);
1931 return 0;
1932 }
1933
1934 private int handleUceGetPidfXml() {
1935 int subId = getSubId("uce get-last-publish-pidf");
1936 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1937 return -1;
1938 }
1939
1940 String result;
1941 try {
1942 result = mInterface.getLastUcePidfXmlShell(subId);
1943 } catch (RemoteException e) {
1944 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
1945 getErrPrintWriter().println("Exception: " + e.getMessage());
1946 return -1;
1947 } catch (ServiceSpecificException sse) {
1948 // Reconstruct ImsException
1949 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
1950 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
1951 getErrPrintWriter().println("Exception: " + imsException);
1952 return -1;
1953 }
1954 if (result == null) {
1955 getErrPrintWriter().println("Service not available");
1956 return -1;
1957 }
1958 getOutPrintWriter().println(result);
1959 return 0;
1960 }
1961
Hui Wang068ab862020-10-31 05:12:53 +00001962 private int handleSrcSetDeviceEnabledCommand() {
1963 String enabledStr = getNextArg();
1964 if (enabledStr == null) {
1965 return -1;
1966 }
1967
1968 try {
1969 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
1970 if (VDBG) {
1971 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
1972 }
1973 getOutPrintWriter().println("Done");
1974 } catch (NumberFormatException | RemoteException e) {
1975 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
1976 getErrPrintWriter().println("Exception: " + e.getMessage());
1977 return -1;
1978 }
1979 return 0;
1980 }
1981
1982 private int handleSrcGetDeviceEnabledCommand() {
1983 boolean result = false;
1984 try {
1985 result = mInterface.getDeviceSingleRegistrationEnabled();
1986 } catch (RemoteException e) {
1987 return -1;
1988 }
1989 if (VDBG) {
1990 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
1991 }
1992 getOutPrintWriter().println(result);
1993 return 0;
1994 }
1995
1996 private int handleSrcSetCarrierEnabledCommand() {
1997 //the release time value could be -1
1998 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
1999 : SubscriptionManager.getDefaultSubscriptionId();
2000 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2001 return -1;
2002 }
2003
2004 String enabledStr = getNextArg();
2005 if (enabledStr == null) {
2006 return -1;
2007 }
2008
2009 try {
2010 boolean result =
2011 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2012 if (VDBG) {
2013 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2014 + enabledStr + ", result=" + result);
2015 }
2016 getOutPrintWriter().println(result);
2017 } catch (NumberFormatException | RemoteException e) {
2018 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2019 + enabledStr + ", error" + e.getMessage());
2020 getErrPrintWriter().println("Exception: " + e.getMessage());
2021 return -1;
2022 }
2023 return 0;
2024 }
2025
2026 private int handleSrcGetCarrierEnabledCommand() {
2027 int subId = getSubId("src get-carrier-enabled");
2028 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2029 return -1;
2030 }
2031
2032 boolean result = false;
2033 try {
2034 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2035 } catch (RemoteException e) {
2036 return -1;
2037 }
2038 if (VDBG) {
2039 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2040 }
2041 getOutPrintWriter().println(result);
2042 return 0;
2043 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -08002044
2045 private int handleHasCarrierPrivilegesCommand() {
2046 String packageName = getNextArgRequired();
2047
2048 boolean hasCarrierPrivileges;
2049 try {
2050 hasCarrierPrivileges =
2051 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2052 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2053 } catch (RemoteException e) {
2054 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2055 getErrPrintWriter().println("Exception: " + e.getMessage());
2056 return -1;
2057 }
2058
2059 getOutPrintWriter().println(hasCarrierPrivileges);
2060 return 0;
2061 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002062}