• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.phone;
18 
19 import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20 import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21 import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22 import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23 
24 import android.Manifest;
25 import android.content.Context;
26 import android.net.Uri;
27 import android.os.Binder;
28 import android.os.PersistableBundle;
29 import android.os.Process;
30 import android.os.RemoteException;
31 import android.os.ServiceSpecificException;
32 import android.provider.BlockedNumberContract;
33 import android.telephony.BarringInfo;
34 import android.telephony.CarrierConfigManager;
35 import android.telephony.SubscriptionInfo;
36 import android.telephony.SubscriptionManager;
37 import android.telephony.TelephonyManager;
38 import android.telephony.TelephonyRegistryManager;
39 import android.telephony.emergency.EmergencyNumber;
40 import android.telephony.ims.ImsException;
41 import android.telephony.ims.RcsContactUceCapability;
42 import android.telephony.ims.feature.ImsFeature;
43 import android.text.TextUtils;
44 import android.util.ArrayMap;
45 import android.util.ArraySet;
46 import android.util.Log;
47 import android.util.SparseArray;
48 
49 import com.android.ims.rcs.uce.util.FeatureTags;
50 import com.android.internal.telephony.ITelephony;
51 import com.android.internal.telephony.Phone;
52 import com.android.internal.telephony.PhoneFactory;
53 import com.android.internal.telephony.d2d.Communicator;
54 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
55 import com.android.internal.telephony.util.TelephonyUtils;
56 import com.android.modules.utils.BasicShellCommandHandler;
57 import com.android.phone.callcomposer.CallComposerPictureManager;
58 
59 import java.io.IOException;
60 import java.io.PrintWriter;
61 import java.util.ArrayList;
62 import java.util.Arrays;
63 import java.util.Collections;
64 import java.util.HashMap;
65 import java.util.List;
66 import java.util.Map;
67 import java.util.Set;
68 import java.util.TreeSet;
69 import java.util.UUID;
70 import java.util.concurrent.CompletableFuture;
71 
72 /**
73  * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
74  * permission checks have been done before onCommand was called. Make sure any commands processed
75  * here also contain the appropriate permissions checks.
76  */
77 
78 public class TelephonyShellCommand extends BasicShellCommandHandler {
79 
80     private static final String LOG_TAG = "TelephonyShellCommand";
81     // Don't commit with this true.
82     private static final boolean VDBG = true;
83     private static final int DEFAULT_PHONE_ID = 0;
84 
85     private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
86     private static final String IMS_SUBCOMMAND = "ims";
87     private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
88     private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
89     private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
90     private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
91     private static final String RESTART_MODEM = "restart-modem";
92     private static final String UNATTENDED_REBOOT = "unattended-reboot";
93     private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
94     private static final String DATA_TEST_MODE = "data";
95     private static final String ENABLE = "enable";
96     private static final String DISABLE = "disable";
97     private static final String QUERY = "query";
98 
99     private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
100     private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
101     private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
102 
103     private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
104     private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
105     private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
106     // Used to disable or enable processing of conference event package data from the network.
107     // This is handy for testing scenarios where CEP data does not exist on a network which does
108     // support CEP data.
109     private static final String IMS_CEP = "conference-event-package";
110 
111     private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
112     private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
113 
114     private static final String CC_GET_VALUE = "get-value";
115     private static final String CC_SET_VALUE = "set-value";
116     private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
117     private static final String CC_CLEAR_VALUES = "clear-values";
118 
119     private static final String GBA_SUBCOMMAND = "gba";
120     private static final String GBA_SET_SERVICE = "set-service";
121     private static final String GBA_GET_SERVICE = "get-service";
122     private static final String GBA_SET_RELEASE_TIME = "set-release";
123     private static final String GBA_GET_RELEASE_TIME = "get-release";
124 
125     private static final String SINGLE_REGISTATION_CONFIG = "src";
126     private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
127     private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
128     private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
129     private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
130     private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
131     private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
132     private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
133     private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
134 
135     private static final String D2D_SUBCOMMAND = "d2d";
136     private static final String D2D_SEND = "send";
137     private static final String D2D_TRANSPORT = "transport";
138     private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
139 
140     private static final String BARRING_SUBCOMMAND = "barring";
141     private static final String BARRING_SEND_INFO = "send";
142 
143     private static final String RCS_UCE_COMMAND = "uce";
144     private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
145     private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
146     private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
147     private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
148     private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
149     private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
150     private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
151     private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
152             "remove-request-disallowed-status";
153     private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
154             "set-capabilities-request-timeout";
155 
156     private static final String RADIO_SUBCOMMAND = "radio";
157     private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
158     private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
159 
160     // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
161     private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
162 
163     private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
164     private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
165 
166     private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
167     private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
168     private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
169 
170     private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
171             "get-allowed-network-types-for-users";
172     private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
173             "set-allowed-network-types-for-users";
174     // Check if telephony new data stack is enabled.
175     private static final String GET_DATA_MODE = "get-data-mode";
176     private static final String GET_IMEI = "get-imei";
177     private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
178     // Take advantage of existing methods that already contain permissions checks when possible.
179     private final ITelephony mInterface;
180 
181     private SubscriptionManager mSubscriptionManager;
182     private CarrierConfigManager mCarrierConfigManager;
183     private TelephonyRegistryManager mTelephonyRegistryManager;
184     private Context mContext;
185 
186     private enum CcType {
187         BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
188                 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
189     }
190 
191     private class CcOptionParseResult {
192         public int mSubId;
193         public boolean mPersistent;
194     }
195 
196     // Maps carrier config keys to type. It is possible to infer the type for most carrier config
197     // keys by looking at the end of the string which usually tells the type.
198     // For instance: "xxxx_string", "xxxx_string_array", etc.
199     // The carrier config keys in this map does not follow this convention. It is therefore not
200     // possible to infer the type for these keys by looking at the string.
201     private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
202             put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
203             put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
204             put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
205             put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
206             put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
207             put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
208             put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
209             put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
210             put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
211             put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
212             put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
213                     CcType.STRING);
214             put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
215                     CcType.STRING_ARRAY);
216             put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
217                     CcType.STRING_ARRAY);
218             put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
219             put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
220             put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
221             put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
222             put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
223             put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
224             put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
225             put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
226         }
227     };
228 
229     /**
230      * Map from a shorthand string to the feature tags required in registration required in order
231      * for the RCS feature to be considered "capable".
232      */
233     private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
234     static {
235         ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
236         map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
237         map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
238         map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
239         map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
240         map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
241         map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
242                 FeatureTags.FEATURE_TAG_VIDEO)));
243         map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
244         map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
245         map.put("call_comp",
246                 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
247         map.put("call_comp_mmtel",
248                 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
249         map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
250         map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
251         map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
252         // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
253         // version
254         map.put("chatbot", new ArraySet<>(Arrays.asList(
255                 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
256                 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
257         map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
258                 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
259                 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
260         map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
261                 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
262                 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
263         map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
264                 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
265                 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
266         map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
267         TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
268     }
269 
270 
TelephonyShellCommand(ITelephony binder, Context context)271     public TelephonyShellCommand(ITelephony binder, Context context) {
272         mInterface = binder;
273         mCarrierConfigManager =
274                 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
275         mSubscriptionManager = (SubscriptionManager)
276                 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
277         mTelephonyRegistryManager = (TelephonyRegistryManager)
278                 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
279         mContext = context;
280     }
281 
282     @Override
onCommand(String cmd)283     public int onCommand(String cmd) {
284         if (cmd == null) {
285             return handleDefaultCommands(null);
286         }
287 
288         switch (cmd) {
289             case IMS_SUBCOMMAND: {
290                 return handleImsCommand();
291             }
292             case RCS_UCE_COMMAND:
293                 return handleRcsUceCommand();
294             case NUMBER_VERIFICATION_SUBCOMMAND:
295                 return handleNumberVerificationCommand();
296             case EMERGENCY_CALLBACK_MODE:
297                 return handleEmergencyCallbackModeCommand();
298             case EMERGENCY_NUMBER_TEST_MODE:
299                 return handleEmergencyNumberTestModeCommand();
300             case CARRIER_CONFIG_SUBCOMMAND: {
301                 return handleCcCommand();
302             }
303             case DATA_TEST_MODE:
304                 return handleDataTestModeCommand();
305             case END_BLOCK_SUPPRESSION:
306                 return handleEndBlockSuppressionCommand();
307             case GBA_SUBCOMMAND:
308                 return handleGbaCommand();
309             case D2D_SUBCOMMAND:
310                 return handleD2dCommand();
311             case BARRING_SUBCOMMAND:
312                 return handleBarringCommand();
313             case SINGLE_REGISTATION_CONFIG:
314                 return handleSingleRegistrationConfigCommand();
315             case RESTART_MODEM:
316                 return handleRestartModemCommand();
317             case CALL_COMPOSER_SUBCOMMAND:
318                 return handleCallComposerCommand();
319             case UNATTENDED_REBOOT:
320                 return handleUnattendedReboot();
321             case HAS_CARRIER_PRIVILEGES_COMMAND:
322                 return handleHasCarrierPrivilegesCommand();
323             case THERMAL_MITIGATION_COMMAND:
324                 return handleThermalMitigationCommand();
325             case DISABLE_PHYSICAL_SUBSCRIPTION:
326                 return handleEnablePhysicalSubscription(false);
327             case ENABLE_PHYSICAL_SUBSCRIPTION:
328                 return handleEnablePhysicalSubscription(true);
329             case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
330             case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
331                 return handleAllowedNetworkTypesCommand(cmd);
332             case GET_DATA_MODE:
333                 return handleGetDataMode();
334             case GET_IMEI:
335                 return handleGetImei();
336             case GET_SIM_SLOTS_MAPPING:
337                 return handleGetSimSlotsMapping();
338             case RADIO_SUBCOMMAND:
339                 return handleRadioCommand();
340             default: {
341                 return handleDefaultCommands(cmd);
342             }
343         }
344     }
345 
346     @Override
onHelp()347     public void onHelp() {
348         PrintWriter pw = getOutPrintWriter();
349         pw.println("Telephony Commands:");
350         pw.println("  help");
351         pw.println("    Print this help text.");
352         pw.println("  ims");
353         pw.println("    IMS Commands.");
354         pw.println("  uce");
355         pw.println("    RCS User Capability Exchange Commands.");
356         pw.println("  emergency-number-test-mode");
357         pw.println("    Emergency Number Test Mode Commands.");
358         pw.println("  end-block-suppression");
359         pw.println("    End Block Suppression command.");
360         pw.println("  data");
361         pw.println("    Data Test Mode Commands.");
362         pw.println("  cc");
363         pw.println("    Carrier Config Commands.");
364         pw.println("  gba");
365         pw.println("    GBA Commands.");
366         pw.println("  src");
367         pw.println("    RCS VoLTE Single Registration Config Commands.");
368         pw.println("  restart-modem");
369         pw.println("    Restart modem command.");
370         pw.println("  unattended-reboot");
371         pw.println("    Prepare for unattended reboot.");
372         pw.println("  has-carrier-privileges [package]");
373         pw.println("    Query carrier privilege status for a package. Prints true or false.");
374         pw.println("  get-allowed-network-types-for-users");
375         pw.println("    Get the Allowed Network Types.");
376         pw.println("  set-allowed-network-types-for-users");
377         pw.println("    Set the Allowed Network Types.");
378         pw.println("  radio");
379         pw.println("    Radio Commands.");
380         onHelpIms();
381         onHelpUce();
382         onHelpEmergencyNumber();
383         onHelpEndBlockSupperssion();
384         onHelpDataTestMode();
385         onHelpCc();
386         onHelpGba();
387         onHelpSrc();
388         onHelpD2D();
389         onHelpDisableOrEnablePhysicalSubscription();
390         onHelpAllowedNetworkTypes();
391         onHelpRadio();
392         onHelpImei();
393     }
394 
onHelpD2D()395     private void onHelpD2D() {
396         PrintWriter pw = getOutPrintWriter();
397         pw.println("D2D Comms Commands:");
398         pw.println("  d2d send TYPE VALUE");
399         pw.println("    Sends a D2D message of specified type and value.");
400         pw.println("    Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
401                 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
402         pw.println("    Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
403                 MESSAGE_CALL_AUDIO_CODEC));
404         pw.println("    Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
405                         + Communicator.messageToString(
406                         MESSAGE_DEVICE_BATTERY_STATE));
407         pw.println("    Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
408                 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
409         pw.println("  d2d transport TYPE");
410         pw.println("    Forces the specified D2D transport TYPE to be active.  Use the");
411         pw.println("    short class name of the transport; i.e. DtmfTransport or RtpTransport.");
412         pw.println("  d2d set-device-support true/default");
413         pw.println("    true - forces device support to be enabled for D2D.");
414         pw.println("    default - clear any previously set force-enable of D2D, reverting to ");
415         pw.println("    the current device's configuration.");
416     }
417 
onHelpBarring()418     private void onHelpBarring() {
419         PrintWriter pw = getOutPrintWriter();
420         pw.println("Barring Commands:");
421         pw.println("  barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
422                 + " -t CONDITIONAL_BARRING_TIME_SECS");
423         pw.println("    Notifies of a barring info change for the specified slot id.");
424         pw.println("    BARRING_TYPE: 0 for BARRING_TYPE_NONE");
425         pw.println("    BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
426         pw.println("    BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
427         pw.println("    BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
428     }
429 
onHelpIms()430     private void onHelpIms() {
431         PrintWriter pw = getOutPrintWriter();
432         pw.println("IMS Commands:");
433         pw.println("  ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
434         pw.println("    Sets the ImsService defined in PACKAGE_NAME to to be the bound");
435         pw.println("    ImsService. Options are:");
436         pw.println("      -s: the slot ID that the ImsService should be bound for. If no option");
437         pw.println("          is specified, it will choose the default voice SIM slot.");
438         pw.println("      -c: Override the ImsService defined in the carrier configuration.");
439         pw.println("      -d: Override the ImsService defined in the device overlay.");
440         pw.println("      -f: Set the feature that this override if for, if no option is");
441         pw.println("          specified, the new package name will be used for all features.");
442         pw.println("  ims get-ims-service [-s SLOT_ID] [-c | -d]");
443         pw.println("    Gets the package name of the currently defined ImsService.");
444         pw.println("    Options are:");
445         pw.println("      -s: The SIM slot ID for the registered ImsService. If no option");
446         pw.println("          is specified, it will choose the default voice SIM slot.");
447         pw.println("      -c: The ImsService defined as the carrier configured ImsService.");
448         pw.println("      -d: The ImsService defined as the device default ImsService.");
449         pw.println("      -f: The feature type that the query will be requested for. If none is");
450         pw.println("          specified, the returned package name will correspond to MMTEL.");
451         pw.println("  ims clear-ims-service-override [-s SLOT_ID]");
452         pw.println("    Clear all carrier ImsService overrides. This does not work for device ");
453         pw.println("    configuration overrides. Options are:");
454         pw.println("      -s: The SIM slot ID for the registered ImsService. If no option");
455         pw.println("          is specified, it will choose the default voice SIM slot.");
456         pw.println("  ims enable [-s SLOT_ID]");
457         pw.println("    enables IMS for the SIM slot specified, or for the default voice SIM slot");
458         pw.println("    if none is specified.");
459         pw.println("  ims disable [-s SLOT_ID]");
460         pw.println("    disables IMS for the SIM slot specified, or for the default voice SIM");
461         pw.println("    slot if none is specified.");
462         pw.println("  ims conference-event-package [enable/disable]");
463         pw.println("    enables or disables handling or network conference event package data.");
464     }
465 
onHelpUce()466     private void onHelpUce() {
467         PrintWriter pw = getOutPrintWriter();
468         pw.println("User Capability Exchange Commands:");
469         pw.println("  uce get-eab-contact [PHONE_NUMBER]");
470         pw.println("    Get the EAB contacts from the EAB database.");
471         pw.println("    Options are:");
472         pw.println("      PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
473         pw.println("    Expected output format :");
474         pw.println("      [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
475         pw.println("  uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
476         pw.println("    Remove the EAB contacts from the EAB database.");
477         pw.println("    Options are:");
478         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
479         pw.println("          is specified, it will choose the default voice SIM slot.");
480         pw.println("      PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
481         pw.println("  uce get-device-enabled");
482         pw.println("    Get the config to check whether the device supports RCS UCE or not.");
483         pw.println("  uce set-device-enabled true|false");
484         pw.println("    Set the device config for RCS User Capability Exchange to the value.");
485         pw.println("    The value could be true, false.");
486         pw.println("  uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
487         pw.println("    Override the existing SIP PUBLISH with different capabilities.");
488         pw.println("    Options are:");
489         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
490         pw.println("          is specified, it will choose the default voice SIM slot.");
491         pw.println("      add [CAPABILITY]: add a new capability");
492         pw.println("      remove [CAPABILITY]: remove a capability");
493         pw.println("      clear: clear all capability overrides");
494         pw.println("      CAPABILITY: \":\" separated list of capabilities.");
495         pw.println("          Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
496         pw.println("          geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
497         pw.println("          chatbot_sa, chatbot_role] as well as full length");
498         pw.println("          featureTag=\"featureValue\" feature tags that are not defined here.");
499         pw.println("  uce get-last-publish-pidf [-s SLOT_ID]");
500         pw.println("    Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
501         pw.println("    PUBLISH is active");
502         pw.println("  uce remove-request-disallowed-status [-s SLOT_ID]");
503         pw.println("    Remove the UCE is disallowed to execute UCE requests status");
504         pw.println("  uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
505         pw.println("    Set the timeout for contact capabilities request.");
506     }
507 
onHelpNumberVerification()508     private void onHelpNumberVerification() {
509         PrintWriter pw = getOutPrintWriter();
510         pw.println("Number verification commands");
511         pw.println("  numverify override-package PACKAGE_NAME;");
512         pw.println("    Set the authorized package for number verification.");
513         pw.println("    Leave the package name blank to reset.");
514         pw.println("  numverify fake-call NUMBER;");
515         pw.println("    Fake an incoming call from NUMBER. This is for testing. Output will be");
516         pw.println("    1 if the call would have been intercepted, 0 otherwise.");
517     }
518 
onHelpThermalMitigation()519     private void onHelpThermalMitigation() {
520         PrintWriter pw = getOutPrintWriter();
521         pw.println("Thermal mitigation commands");
522         pw.println("  thermal-mitigation allow-package PACKAGE_NAME");
523         pw.println("    Set the package as one of authorized packages for thermal mitigation.");
524         pw.println("  thermal-mitigation disallow-package PACKAGE_NAME");
525         pw.println("    Remove the package from one of the authorized packages for thermal "
526                 + "mitigation.");
527     }
528 
onHelpDisableOrEnablePhysicalSubscription()529     private void onHelpDisableOrEnablePhysicalSubscription() {
530         PrintWriter pw = getOutPrintWriter();
531         pw.println("Disable or enable a physical subscription");
532         pw.println("  disable-physical-subscription SUB_ID");
533         pw.println("    Disable the physical subscription with the provided subId, if allowed.");
534         pw.println("  enable-physical-subscription SUB_ID");
535         pw.println("    Enable the physical subscription with the provided subId, if allowed.");
536     }
537 
onHelpDataTestMode()538     private void onHelpDataTestMode() {
539         PrintWriter pw = getOutPrintWriter();
540         pw.println("Mobile Data Test Mode Commands:");
541         pw.println("  data enable: enable mobile data connectivity");
542         pw.println("  data disable: disable mobile data connectivity");
543     }
544 
onHelpEmergencyNumber()545     private void onHelpEmergencyNumber() {
546         PrintWriter pw = getOutPrintWriter();
547         pw.println("Emergency Number Test Mode Commands:");
548         pw.println("  emergency-number-test-mode ");
549         pw.println("    Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
550                 + " the test mode");
551         pw.println("      -a <emergency number address>: add an emergency number address for the"
552                 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
553         pw.println("      -c: clear the emergency number list in the test mode.");
554         pw.println("      -r <emergency number address>: remove an existing emergency number"
555                 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
556         pw.println("      -p: get the full emergency number list in the test mode.");
557     }
558 
onHelpEndBlockSupperssion()559     private void onHelpEndBlockSupperssion() {
560         PrintWriter pw = getOutPrintWriter();
561         pw.println("End Block Suppression command:");
562         pw.println("  end-block-suppression: disable suppressing blocking by contact");
563         pw.println("                         with emergency services.");
564     }
565 
onHelpCc()566     private void onHelpCc() {
567         PrintWriter pw = getOutPrintWriter();
568         pw.println("Carrier Config Commands:");
569         pw.println("  cc get-value [-s SLOT_ID] [KEY]");
570         pw.println("    Print carrier config values.");
571         pw.println("    Options are:");
572         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
573         pw.println("          is specified, it will choose the default voice SIM slot.");
574         pw.println("    KEY: The key to the carrier config value to print. All values are printed");
575         pw.println("         if KEY is not specified.");
576         pw.println("  cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
577         pw.println("    Set carrier config KEY to NEW_VALUE.");
578         pw.println("    Options are:");
579         pw.println("      -s: The SIM slot ID to set carrier config value for. If no option");
580         pw.println("          is specified, it will choose the default voice SIM slot.");
581         pw.println("      -p: Value will be stored persistent");
582         pw.println("    NEW_VALUE specifies the new value for carrier config KEY. Null will be");
583         pw.println("      used if NEW_VALUE is not set. Strings should be encapsulated with");
584         pw.println("      quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
585         pw.println("      Separate items in arrays with space . Example: \"item1\" \"item2\"");
586         pw.println("  cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
587         pw.println("    Set carrier config based on the contents of the XML_FILE. File must be");
588         pw.println("    provided through standard input and follow CarrierConfig XML format.");
589         pw.println("    Example: packages/apps/CarrierConfig/assets/*.xml");
590         pw.println("    Options are:");
591         pw.println("      -s: The SIM slot ID to set carrier config value for. If no option");
592         pw.println("          is specified, it will choose the default voice SIM slot.");
593         pw.println("      -p: Value will be stored persistent");
594         pw.println("  cc clear-values [-s SLOT_ID]");
595         pw.println("    Clear all carrier override values that has previously been set");
596         pw.println("    with set-value or set-values-from-xml");
597         pw.println("    Options are:");
598         pw.println("      -s: The SIM slot ID to clear carrier config values for. If no option");
599         pw.println("          is specified, it will choose the default voice SIM slot.");
600     }
601 
onHelpGba()602     private void onHelpGba() {
603         PrintWriter pw = getOutPrintWriter();
604         pw.println("Gba Commands:");
605         pw.println("  gba set-service [-s SLOT_ID] PACKAGE_NAME");
606         pw.println("    Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
607         pw.println("    Options are:");
608         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
609         pw.println("          is specified, it will choose the default voice SIM slot.");
610         pw.println("  gba get-service [-s SLOT_ID]");
611         pw.println("    Gets the package name of the currently defined GbaService.");
612         pw.println("    Options are:");
613         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
614         pw.println("          is specified, it will choose the default voice SIM slot.");
615         pw.println("  gba set-release [-s SLOT_ID] n");
616         pw.println("    Sets the time to release/unbind GbaService in n milli-second.");
617         pw.println("    Do not release/unbind if n is -1.");
618         pw.println("    Options are:");
619         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
620         pw.println("          is specified, it will choose the default voice SIM slot.");
621         pw.println("  gba get-release [-s SLOT_ID]");
622         pw.println("    Gets the time to release/unbind GbaService in n milli-sencond.");
623         pw.println("    Options are:");
624         pw.println("      -s: The SIM slot ID to read carrier config value for. If no option");
625         pw.println("          is specified, it will choose the default voice SIM slot.");
626     }
627 
onHelpSrc()628     private void onHelpSrc() {
629         PrintWriter pw = getOutPrintWriter();
630         pw.println("RCS VoLTE Single Registration Config Commands:");
631         pw.println("  src set-test-enabled true|false");
632         pw.println("    Sets the test mode enabled for RCS VoLTE single registration.");
633         pw.println("    The value could be true, false, or null(undefined).");
634         pw.println("  src get-test-enabled");
635         pw.println("    Gets the test mode for RCS VoLTE single registration.");
636         pw.println("  src set-device-enabled true|false|null");
637         pw.println("    Sets the device config for RCS VoLTE single registration to the value.");
638         pw.println("    The value could be true, false, or null(undefined).");
639         pw.println("  src get-device-enabled");
640         pw.println("    Gets the device config for RCS VoLTE single registration.");
641         pw.println("  src set-carrier-enabled [-s SLOT_ID] true|false|null");
642         pw.println("    Sets the carrier config for RCS VoLTE single registration to the value.");
643         pw.println("    The value could be true, false, or null(undefined).");
644         pw.println("    Options are:");
645         pw.println("      -s: The SIM slot ID to set the config value for. If no option");
646         pw.println("          is specified, it will choose the default voice SIM slot.");
647         pw.println("  src get-carrier-enabled [-s SLOT_ID]");
648         pw.println("    Gets the carrier config for RCS VoLTE single registration.");
649         pw.println("    Options are:");
650         pw.println("      -s: The SIM slot ID to read the config value for. If no option");
651         pw.println("          is specified, it will choose the default voice SIM slot.");
652         pw.println("  src set-feature-validation [-s SLOT_ID] true|false|null");
653         pw.println("    Sets ims feature validation result.");
654         pw.println("    The value could be true, false, or null(undefined).");
655         pw.println("    Options are:");
656         pw.println("      -s: The SIM slot ID to set the config value for. If no option");
657         pw.println("          is specified, it will choose the default voice SIM slot.");
658         pw.println("  src get-feature-validation [-s SLOT_ID]");
659         pw.println("    Gets ims feature validation override value.");
660         pw.println("    Options are:");
661         pw.println("      -s: The SIM slot ID to read the config value for. If no option");
662         pw.println("          is specified, it will choose the default voice SIM slot.");
663     }
664 
onHelpAllowedNetworkTypes()665     private void onHelpAllowedNetworkTypes() {
666         PrintWriter pw = getOutPrintWriter();
667         pw.println("Allowed Network Types Commands:");
668         pw.println("  get-allowed-network-types-for-users [-s SLOT_ID]");
669         pw.println("    Print allowed network types value.");
670         pw.println("    Options are:");
671         pw.println("      -s: The SIM slot ID to read allowed network types value for. If no");
672         pw.println("          option is specified, it will choose the default voice SIM slot.");
673         pw.println("  set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
674         pw.println("    Sets allowed network types to NETWORK_TYPES_BITMASK.");
675         pw.println("    Options are:");
676         pw.println("      -s: The SIM slot ID to set allowed network types value for. If no");
677         pw.println("          option is specified, it will choose the default voice SIM slot.");
678         pw.println("    NETWORK_TYPES_BITMASK specifies the new network types value and this type");
679         pw.println("      is bitmask in binary format. Reference the NetworkTypeBitMask");
680         pw.println("      at TelephonyManager.java");
681         pw.println("      For example:");
682         pw.println("        NR only                    : 10000000000000000000");
683         pw.println("        NR|LTE                     : 11000001000000000000");
684         pw.println("        NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
685         pw.println("        LTE|CDMA|EVDO|GSM|WCDMA    : 01001111101111111111");
686         pw.println("        LTE only                   : 01000001000000000000");
687     }
688 
onHelpRadio()689     private void onHelpRadio() {
690         PrintWriter pw = getOutPrintWriter();
691         pw.println("Radio Commands:");
692         pw.println("  radio set-modem-service [-s SERVICE_NAME]");
693         pw.println("    Sets the class name of modem service defined in SERVICE_NAME");
694         pw.println("    to be the bound. Options are:");
695         pw.println("      -s: the service name that the modem service should be bound for.");
696         pw.println("          If no option is specified, it will bind to the default.");
697         pw.println("  radio get-modem-service");
698         pw.println("    Gets the service name of the currently defined modem service.");
699         pw.println("    If it is binding to default, 'default' returns.");
700         pw.println("    If it doesn't bind to any modem service for some reasons,");
701         pw.println("    the result would be 'unknown'.");
702     }
703 
onHelpImei()704     private void onHelpImei() {
705         PrintWriter pw = getOutPrintWriter();
706         pw.println("IMEI Commands:");
707         pw.println("  get-imei [-s SLOT_ID]");
708         pw.println("    Gets the device IMEI. Options are:");
709         pw.println("      -s: the slot ID to get the IMEI. If no option");
710         pw.println("          is specified, it will choose the default voice SIM slot.");
711     }
712 
handleImsCommand()713     private int handleImsCommand() {
714         String arg = getNextArg();
715         if (arg == null) {
716             onHelpIms();
717             return 0;
718         }
719 
720         switch (arg) {
721             case IMS_SET_IMS_SERVICE: {
722                 return handleImsSetServiceCommand();
723             }
724             case IMS_GET_IMS_SERVICE: {
725                 return handleImsGetServiceCommand();
726             }
727             case IMS_CLEAR_SERVICE_OVERRIDE: {
728                 return handleImsClearCarrierServiceCommand();
729             }
730             case ENABLE: {
731                 return handleEnableIms();
732             }
733             case DISABLE: {
734                 return handleDisableIms();
735             }
736             case IMS_CEP: {
737                 return handleCepChange();
738             }
739         }
740 
741         return -1;
742     }
743 
handleDataTestModeCommand()744     private int handleDataTestModeCommand() {
745         PrintWriter errPw = getErrPrintWriter();
746         String arg = getNextArgRequired();
747         if (arg == null) {
748             onHelpDataTestMode();
749             return 0;
750         }
751         switch (arg) {
752             case ENABLE: {
753                 try {
754                     mInterface.enableDataConnectivity(mContext.getOpPackageName());
755                 } catch (RemoteException ex) {
756                     Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
757                     errPw.println("Exception: " + ex.getMessage());
758                     return -1;
759                 }
760                 break;
761             }
762             case DISABLE: {
763                 try {
764                     mInterface.disableDataConnectivity(mContext.getOpPackageName());
765                 } catch (RemoteException ex) {
766                     Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
767                     errPw.println("Exception: " + ex.getMessage());
768                     return -1;
769                 }
770                 break;
771             }
772             default:
773                 onHelpDataTestMode();
774                 break;
775         }
776         return 0;
777     }
778 
handleEmergencyCallbackModeCommand()779     private int handleEmergencyCallbackModeCommand() {
780         PrintWriter errPw = getErrPrintWriter();
781         try {
782             mInterface.startEmergencyCallbackMode();
783             Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
784         } catch (RemoteException ex) {
785             Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
786             errPw.println("Exception: " + ex.getMessage());
787             return -1;
788         }
789         return 0;
790     }
791 
handleEmergencyNumberTestModeCommand()792     private int handleEmergencyNumberTestModeCommand() {
793         PrintWriter errPw = getErrPrintWriter();
794         String opt = getNextOption();
795         if (opt == null) {
796             onHelpEmergencyNumber();
797             return 0;
798         }
799 
800         switch (opt) {
801             case "-a": {
802                 String emergencyNumberCmd = getNextArgRequired();
803                 if (emergencyNumberCmd == null
804                         || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
805                     errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
806                             + " to be specified after -a in the command ");
807                     return -1;
808                 }
809                 try {
810                     mInterface.updateEmergencyNumberListTestMode(
811                             EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
812                             new EmergencyNumber(emergencyNumberCmd, "", "",
813                                     EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
814                                     new ArrayList<String>(),
815                                     EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
816                                     EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
817                 } catch (RemoteException ex) {
818                     Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
819                             + ", error " + ex.getMessage());
820                     errPw.println("Exception: " + ex.getMessage());
821                     return -1;
822                 }
823                 break;
824             }
825             case "-c": {
826                 try {
827                     mInterface.updateEmergencyNumberListTestMode(
828                             EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
829                 } catch (RemoteException ex) {
830                     Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
831                     errPw.println("Exception: " + ex.getMessage());
832                     return -1;
833                 }
834                 break;
835             }
836             case "-r": {
837                 String emergencyNumberCmd = getNextArgRequired();
838                 if (emergencyNumberCmd == null
839                         || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
840                     errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
841                             + " to be specified after -r in the command ");
842                     return -1;
843                 }
844                 try {
845                     mInterface.updateEmergencyNumberListTestMode(
846                             EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
847                             new EmergencyNumber(emergencyNumberCmd, "", "",
848                                     EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
849                                     new ArrayList<String>(),
850                                     EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
851                                     EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
852                 } catch (RemoteException ex) {
853                     Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
854                             + ", error " + ex.getMessage());
855                     errPw.println("Exception: " + ex.getMessage());
856                     return -1;
857                 }
858                 break;
859             }
860             case "-p": {
861                 try {
862                     getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
863                 } catch (RemoteException ex) {
864                     Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
865                     errPw.println("Exception: " + ex.getMessage());
866                     return -1;
867                 }
868                 break;
869             }
870             default:
871                 onHelpEmergencyNumber();
872                 break;
873         }
874         return 0;
875     }
876 
handleNumberVerificationCommand()877     private int handleNumberVerificationCommand() {
878         String arg = getNextArg();
879         if (arg == null) {
880             onHelpNumberVerification();
881             return 0;
882         }
883 
884         if (!checkShellUid()) {
885             return -1;
886         }
887 
888         switch (arg) {
889             case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
890                 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
891                 return 0;
892             }
893             case NUMBER_VERIFICATION_FAKE_CALL: {
894                 boolean val = NumberVerificationManager.getInstance()
895                         .checkIncomingCall(getNextArg());
896                 getOutPrintWriter().println(val ? "1" : "0");
897                 return 0;
898             }
899         }
900 
901         return -1;
902     }
903 
subIsEsim(int subId)904     private boolean subIsEsim(int subId) {
905         SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
906         if (info != null) {
907             return info.isEmbedded();
908         }
909         return false;
910     }
911 
handleEnablePhysicalSubscription(boolean enable)912     private int handleEnablePhysicalSubscription(boolean enable) {
913         PrintWriter errPw = getErrPrintWriter();
914         int subId = 0;
915         try {
916             subId = Integer.parseInt(getNextArgRequired());
917         } catch (NumberFormatException e) {
918             errPw.println((enable ? "enable" : "disable")
919                     + "-physical-subscription requires an integer as a subId.");
920             return -1;
921         }
922         // Verify that the user is allowed to run the command. Only allowed in rooted device in a
923         // non user build.
924         if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
925             errPw.println("cc: Permission denied.");
926             return -1;
927         }
928         // Verify that the subId represents a physical sub
929         if (subIsEsim(subId)) {
930             errPw.println("SubId " + subId + " is not for a physical subscription");
931             return -1;
932         }
933         Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
934                 + " physical subscription with subId=" + subId);
935         mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
936         return 0;
937     }
938 
handleThermalMitigationCommand()939     private int handleThermalMitigationCommand() {
940         String arg = getNextArg();
941         String packageName = getNextArg();
942         if (arg == null || packageName == null) {
943             onHelpThermalMitigation();
944             return 0;
945         }
946 
947         if (!checkShellUid()) {
948             return -1;
949         }
950 
951         switch (arg) {
952             case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
953                 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
954                 return 0;
955             }
956             case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
957                 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
958                         mContext);
959                 return 0;
960             }
961             default:
962                 onHelpThermalMitigation();
963         }
964 
965         return -1;
966 
967     }
968 
handleD2dCommand()969     private int handleD2dCommand() {
970         String arg = getNextArg();
971         if (arg == null) {
972             onHelpD2D();
973             return 0;
974         }
975 
976         switch (arg) {
977             case D2D_SEND: {
978                 return handleD2dSendCommand();
979             }
980             case D2D_TRANSPORT: {
981                 return handleD2dTransportCommand();
982             }
983             case D2D_SET_DEVICE_SUPPORT: {
984                 return handleD2dDeviceSupportedCommand();
985             }
986         }
987 
988         return -1;
989     }
990 
handleD2dSendCommand()991     private int handleD2dSendCommand() {
992         PrintWriter errPw = getErrPrintWriter();
993         int messageType = -1;
994         int messageValue = -1;
995 
996         String arg = getNextArg();
997         if (arg == null) {
998             onHelpD2D();
999             return 0;
1000         }
1001         try {
1002             messageType = Integer.parseInt(arg);
1003         } catch (NumberFormatException e) {
1004             errPw.println("message type must be a valid integer");
1005             return -1;
1006         }
1007 
1008         arg = getNextArg();
1009         if (arg == null) {
1010             onHelpD2D();
1011             return 0;
1012         }
1013         try {
1014             messageValue = Integer.parseInt(arg);
1015         } catch (NumberFormatException e) {
1016             errPw.println("message value must be a valid integer");
1017             return -1;
1018         }
1019 
1020         try {
1021             mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1022         } catch (RemoteException e) {
1023             Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1024             errPw.println("Exception: " + e.getMessage());
1025             return -1;
1026         }
1027 
1028         return 0;
1029     }
1030 
handleD2dTransportCommand()1031     private int handleD2dTransportCommand() {
1032         PrintWriter errPw = getErrPrintWriter();
1033 
1034         String arg = getNextArg();
1035         if (arg == null) {
1036             onHelpD2D();
1037             return 0;
1038         }
1039 
1040         try {
1041             mInterface.setActiveDeviceToDeviceTransport(arg);
1042         } catch (RemoteException e) {
1043             Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1044             errPw.println("Exception: " + e.getMessage());
1045             return -1;
1046         }
1047         return 0;
1048     }
handleBarringCommand()1049     private int handleBarringCommand() {
1050         String arg = getNextArg();
1051         if (arg == null) {
1052             onHelpBarring();
1053             return 0;
1054         }
1055 
1056         switch (arg) {
1057             case BARRING_SEND_INFO: {
1058                 return handleBarringSendCommand();
1059             }
1060         }
1061         return -1;
1062     }
1063 
handleBarringSendCommand()1064     private int handleBarringSendCommand() {
1065         PrintWriter errPw = getErrPrintWriter();
1066         int slotId = getDefaultSlot();
1067         int subId = SubscriptionManager.getSubId(slotId)[0];
1068         @BarringInfo.BarringServiceInfo.BarringType int barringType =
1069                 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1070         boolean isConditionallyBarred = false;
1071         int conditionalBarringTimeSeconds = 0;
1072 
1073         String opt;
1074         while ((opt = getNextOption()) != null) {
1075             switch (opt) {
1076                 case "-s": {
1077                     try {
1078                         slotId = Integer.parseInt(getNextArgRequired());
1079                         subId = SubscriptionManager.getSubId(slotId)[0];
1080                     } catch (NumberFormatException e) {
1081                         errPw.println("barring send requires an integer as a SLOT_ID.");
1082                         return -1;
1083                     }
1084                     break;
1085                 }
1086                 case "-b": {
1087                     try {
1088                         barringType = Integer.parseInt(getNextArgRequired());
1089                         if (barringType < -1 || barringType > 2) {
1090                             throw new NumberFormatException();
1091                         }
1092 
1093                     } catch (NumberFormatException e) {
1094                         errPw.println("barring send requires an integer in range [-1,2] as "
1095                                 + "a BARRING_TYPE.");
1096                         return -1;
1097                     }
1098                     break;
1099                 }
1100                 case "-c": {
1101                     try {
1102                         isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1103                     } catch (Exception e) {
1104                         errPw.println("barring send requires a boolean after -c indicating"
1105                                 + " conditional barring");
1106                         return -1;
1107                     }
1108                     break;
1109                 }
1110                 case "-t": {
1111                     try {
1112                         conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1113                     } catch (NumberFormatException e) {
1114                         errPw.println("barring send requires an integer for time of barring"
1115                                 + " in seconds after -t for conditional barring");
1116                         return -1;
1117                     }
1118                     break;
1119                 }
1120             }
1121         }
1122         SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1123         BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1124                 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1125         barringServiceInfos.append(0, bsi);
1126         BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1127         try {
1128             mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1129         } catch (Exception e) {
1130             Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1131             errPw.println("Exception: " + e.getMessage());
1132             return -1;
1133         }
1134         return 0;
1135     }
1136 
handleD2dDeviceSupportedCommand()1137     private int handleD2dDeviceSupportedCommand() {
1138         PrintWriter errPw = getErrPrintWriter();
1139 
1140         String arg = getNextArg();
1141         if (arg == null) {
1142             onHelpD2D();
1143             return 0;
1144         }
1145 
1146         boolean isEnabled = "true".equals(arg.toLowerCase());
1147         try {
1148             mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1149         } catch (RemoteException e) {
1150             Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1151             errPw.println("Exception: " + e.getMessage());
1152             return -1;
1153         }
1154         return 0;
1155     }
1156 
1157     // ims set-ims-service
handleImsSetServiceCommand()1158     private int handleImsSetServiceCommand() {
1159         PrintWriter errPw = getErrPrintWriter();
1160         int slotId = getDefaultSlot();
1161         Boolean isCarrierService = null;
1162         List<Integer> featuresList = new ArrayList<>();
1163 
1164         String opt;
1165         while ((opt = getNextOption()) != null) {
1166             switch (opt) {
1167                 case "-s": {
1168                     try {
1169                         slotId = Integer.parseInt(getNextArgRequired());
1170                     } catch (NumberFormatException e) {
1171                         errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1172                         return -1;
1173                     }
1174                     break;
1175                 }
1176                 case "-c": {
1177                     isCarrierService = true;
1178                     break;
1179                 }
1180                 case "-d": {
1181                     isCarrierService = false;
1182                     break;
1183                 }
1184                 case "-f": {
1185                     String featureString = getNextArgRequired();
1186                     String[] features = featureString.split(",");
1187                     for (int i = 0; i < features.length; i++) {
1188                         try {
1189                             Integer result = Integer.parseInt(features[i]);
1190                             if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1191                                     || result >= ImsFeature.FEATURE_MAX) {
1192                                 errPw.println("ims set-ims-service -f " + result
1193                                         + " is an invalid feature.");
1194                                 return -1;
1195                             }
1196                             featuresList.add(result);
1197                         } catch (NumberFormatException e) {
1198                             errPw.println("ims set-ims-service -f tried to parse " + features[i]
1199                                             + " as an integer.");
1200                             return -1;
1201                         }
1202                     }
1203                 }
1204             }
1205         }
1206         // Mandatory param, either -c or -d
1207         if (isCarrierService == null) {
1208             errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1209             return -1;
1210         }
1211 
1212         String packageName = getNextArg();
1213 
1214         try {
1215             if (packageName == null) {
1216                 packageName = "";
1217             }
1218             int[] featureArray = new int[featuresList.size()];
1219             for (int i = 0; i < featuresList.size(); i++) {
1220                 featureArray[i] = featuresList.get(i);
1221             }
1222             boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1223                     featureArray, packageName);
1224             if (VDBG) {
1225                 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
1226                         + (isCarrierService ? "-c " : "-d ")
1227                         + "-f " + featuresList + " "
1228                         + packageName + ", result=" + result);
1229             }
1230             getOutPrintWriter().println(result);
1231         } catch (RemoteException e) {
1232             Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
1233                     + (isCarrierService ? "-c " : "-d ")
1234                     + "-f " + featuresList + " "
1235                     + packageName + ", error" + e.getMessage());
1236             errPw.println("Exception: " + e.getMessage());
1237             return -1;
1238         }
1239         return 0;
1240     }
1241 
1242     // ims clear-ims-service-override
handleImsClearCarrierServiceCommand()1243     private int handleImsClearCarrierServiceCommand() {
1244         PrintWriter errPw = getErrPrintWriter();
1245         int slotId = getDefaultSlot();
1246 
1247         String opt;
1248         while ((opt = getNextOption()) != null) {
1249             switch (opt) {
1250                 case "-s": {
1251                     try {
1252                         slotId = Integer.parseInt(getNextArgRequired());
1253                     } catch (NumberFormatException e) {
1254                         errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1255                         return -1;
1256                     }
1257                     break;
1258                 }
1259             }
1260         }
1261 
1262         try {
1263             boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1264             if (VDBG) {
1265                 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1266                         + ", result=" + result);
1267             }
1268             getOutPrintWriter().println(result);
1269         } catch (RemoteException e) {
1270             Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1271                     + ", error" + e.getMessage());
1272             errPw.println("Exception: " + e.getMessage());
1273             return -1;
1274         }
1275         return 0;
1276     }
1277 
1278     // ims get-ims-service
handleImsGetServiceCommand()1279     private int handleImsGetServiceCommand() {
1280         PrintWriter errPw = getErrPrintWriter();
1281         int slotId = getDefaultSlot();
1282         Boolean isCarrierService = null;
1283         Integer featureType = ImsFeature.FEATURE_MMTEL;
1284 
1285         String opt;
1286         while ((opt = getNextOption()) != null) {
1287             switch (opt) {
1288                 case "-s": {
1289                     try {
1290                         slotId = Integer.parseInt(getNextArgRequired());
1291                     } catch (NumberFormatException e) {
1292                         errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1293                         return -1;
1294                     }
1295                     break;
1296                 }
1297                 case "-c": {
1298                     isCarrierService = true;
1299                     break;
1300                 }
1301                 case "-d": {
1302                     isCarrierService = false;
1303                     break;
1304                 }
1305                 case "-f": {
1306                     try {
1307                         featureType = Integer.parseInt(getNextArg());
1308                     } catch (NumberFormatException e) {
1309                         errPw.println("ims get-ims-service -f requires valid integer as feature.");
1310                         return -1;
1311                     }
1312                     if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1313                             || featureType >= ImsFeature.FEATURE_MAX) {
1314                         errPw.println("ims get-ims-service -f invalid feature.");
1315                         return -1;
1316                     }
1317                 }
1318             }
1319         }
1320         // Mandatory param, either -c or -d
1321         if (isCarrierService == null) {
1322             errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
1323             return -1;
1324         }
1325 
1326         String result;
1327         try {
1328             result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
1329         } catch (RemoteException e) {
1330             return -1;
1331         }
1332         if (VDBG) {
1333             Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
1334                     + (isCarrierService ? "-c " : "-d ")
1335                     + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1336                     + result);
1337         }
1338         getOutPrintWriter().println(result);
1339         return 0;
1340     }
1341 
handleEnableIms()1342     private int handleEnableIms() {
1343         int slotId = getDefaultSlot();
1344         String opt;
1345         while ((opt = getNextOption()) != null) {
1346             switch (opt) {
1347                 case "-s": {
1348                     try {
1349                         slotId = Integer.parseInt(getNextArgRequired());
1350                     } catch (NumberFormatException e) {
1351                         getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1352                         return -1;
1353                     }
1354                     break;
1355                 }
1356             }
1357         }
1358         try {
1359             mInterface.enableIms(slotId);
1360         } catch (RemoteException e) {
1361             return -1;
1362         }
1363         if (VDBG) {
1364             Log.v(LOG_TAG, "ims enable -s " + slotId);
1365         }
1366         return 0;
1367     }
1368 
handleDisableIms()1369     private int handleDisableIms() {
1370         int slotId = getDefaultSlot();
1371         String opt;
1372         while ((opt = getNextOption()) != null) {
1373             switch (opt) {
1374                 case "-s": {
1375                     try {
1376                         slotId = Integer.parseInt(getNextArgRequired());
1377                     } catch (NumberFormatException e) {
1378                         getErrPrintWriter().println(
1379                                 "ims disable requires an integer as a SLOT_ID.");
1380                         return -1;
1381                     }
1382                     break;
1383                 }
1384             }
1385         }
1386         try {
1387             mInterface.disableIms(slotId);
1388         } catch (RemoteException e) {
1389             return -1;
1390         }
1391         if (VDBG) {
1392             Log.v(LOG_TAG, "ims disable -s " + slotId);
1393         }
1394         return 0;
1395     }
1396 
handleCepChange()1397     private int handleCepChange() {
1398         Log.i(LOG_TAG, "handleCepChange");
1399         String opt = getNextArg();
1400         if (opt == null) {
1401             return -1;
1402         }
1403         boolean isCepEnabled = opt.equals("enable");
1404 
1405         try {
1406             mInterface.setCepEnabled(isCepEnabled);
1407         } catch (RemoteException e) {
1408             return -1;
1409         }
1410         return 0;
1411     }
1412 
getDefaultSlot()1413     private int getDefaultSlot() {
1414         int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1415         if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1416                 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1417             // If there is no default, default to slot 0.
1418             slotId = DEFAULT_PHONE_ID;
1419         }
1420         return slotId;
1421     }
1422 
1423     // Parse options related to Carrier Config Commands.
parseCcOptions(String tag, boolean allowOptionPersistent)1424     private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
1425         PrintWriter errPw = getErrPrintWriter();
1426         CcOptionParseResult result = new CcOptionParseResult();
1427         result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1428         result.mPersistent = false;
1429 
1430         String opt;
1431         while ((opt = getNextOption()) != null) {
1432             switch (opt) {
1433                 case "-s": {
1434                     try {
1435                         result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1436                         if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1437                             errPw.println(tag + "No valid subscription found.");
1438                             return null;
1439                         }
1440 
1441                     } catch (IllegalArgumentException e) {
1442                         // Missing slot id
1443                         errPw.println(tag + "SLOT_ID expected after -s.");
1444                         return null;
1445                     }
1446                     break;
1447                 }
1448                 case "-p": {
1449                     if (allowOptionPersistent) {
1450                         result.mPersistent = true;
1451                     } else {
1452                         errPw.println(tag + "Unexpected option " + opt);
1453                         return null;
1454                     }
1455                     break;
1456                 }
1457                 default: {
1458                     errPw.println(tag + "Unknown option " + opt);
1459                     return null;
1460                 }
1461             }
1462         }
1463         return result;
1464     }
1465 
slotStringToSubId(String tag, String slotString)1466     private int slotStringToSubId(String tag, String slotString) {
1467         int slotId = -1;
1468         try {
1469             slotId = Integer.parseInt(slotString);
1470         } catch (NumberFormatException e) {
1471             getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1472             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1473         }
1474 
1475         if (!SubscriptionManager.isValidPhoneId(slotId)) {
1476             getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1477             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1478         }
1479 
1480         Phone phone = PhoneFactory.getPhone(slotId);
1481         if (phone == null) {
1482             getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1483             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1484         }
1485         return phone.getSubId();
1486     }
1487 
checkShellUid()1488     private boolean checkShellUid() {
1489         // adb can run as root or as shell, depending on whether the device is rooted.
1490         return Binder.getCallingUid() == Process.SHELL_UID
1491                 || Binder.getCallingUid() == Process.ROOT_UID;
1492     }
1493 
handleCcCommand()1494     private int handleCcCommand() {
1495         // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1496         // non user build.
1497         if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1498             getErrPrintWriter().println("cc: Permission denied.");
1499             return -1;
1500         }
1501 
1502         String arg = getNextArg();
1503         if (arg == null) {
1504             onHelpCc();
1505             return 0;
1506         }
1507 
1508         switch (arg) {
1509             case CC_GET_VALUE: {
1510                 return handleCcGetValue();
1511             }
1512             case CC_SET_VALUE: {
1513                 return handleCcSetValue();
1514             }
1515             case CC_SET_VALUES_FROM_XML: {
1516                 return handleCcSetValuesFromXml();
1517             }
1518             case CC_CLEAR_VALUES: {
1519                 return handleCcClearValues();
1520             }
1521             default: {
1522                 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1523             }
1524         }
1525         return -1;
1526     }
1527 
1528     // cc get-value
handleCcGetValue()1529     private int handleCcGetValue() {
1530         PrintWriter errPw = getErrPrintWriter();
1531         String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1532         String key = null;
1533 
1534         // Parse all options
1535         CcOptionParseResult options = parseCcOptions(tag, false);
1536         if (options == null) {
1537             return -1;
1538         }
1539 
1540         // Get bundle containing all carrier configuration values.
1541         PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1542         if (bundle == null) {
1543             errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1544             return -1;
1545         }
1546 
1547         // Get the key.
1548         key = getNextArg();
1549         if (key != null) {
1550             // A key was provided. Verify if it is a valid key
1551             if (!bundle.containsKey(key)) {
1552                 errPw.println(tag + key + " is not a valid key.");
1553                 return -1;
1554             }
1555 
1556             // Print the carrier config value for key.
1557             getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1558         } else {
1559             // No key provided. Show all values.
1560             // Iterate over a sorted list of all carrier config keys and print them.
1561             TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1562             for (String k : sortedSet) {
1563                 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1564             }
1565         }
1566         return 0;
1567     }
1568 
1569     // cc set-value
handleCcSetValue()1570     private int handleCcSetValue() {
1571         PrintWriter errPw = getErrPrintWriter();
1572         String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1573 
1574         // Parse all options
1575         CcOptionParseResult options = parseCcOptions(tag, true);
1576         if (options == null) {
1577             return -1;
1578         }
1579 
1580         // Get bundle containing all current carrier configuration values.
1581         PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1582         if (originalValues == null) {
1583             errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1584             return -1;
1585         }
1586 
1587         // Get the key.
1588         String key = getNextArg();
1589         if (key == null || key.equals("")) {
1590             errPw.println(tag + "KEY is missing");
1591             return -1;
1592         }
1593 
1594         // Verify if the key is valid
1595         if (!originalValues.containsKey(key)) {
1596             errPw.println(tag + key + " is not a valid key.");
1597             return -1;
1598         }
1599 
1600         // Remaining arguments is a list of new values. Add them all into an ArrayList.
1601         ArrayList<String> valueList = new ArrayList<String>();
1602         while (peekNextArg() != null) {
1603             valueList.add(getNextArg());
1604         }
1605 
1606         // Find the type of the carrier config value
1607         CcType type = getType(tag, key, originalValues);
1608         if (type == CcType.UNKNOWN) {
1609             errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1610             return -1;
1611         }
1612         if (type == CcType.PERSISTABLE_BUNDLE) {
1613             errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1614                     + "Use set-values-from-xml instead.");
1615             return -1;
1616         }
1617 
1618         // Create an override bundle containing the key and value that should be overriden.
1619         PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1620         if (overrideBundle == null) {
1621             return -1;
1622         }
1623 
1624         // Override the value
1625         mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1626 
1627         // Find bundle containing all new carrier configuration values after the override.
1628         PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1629         if (newValues == null) {
1630             errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1631             return -1;
1632         }
1633 
1634         // Print the original and new value.
1635         String originalValueString = ccValueToString(key, type, originalValues);
1636         String newValueString = ccValueToString(key, type, newValues);
1637         getOutPrintWriter().println("Previous value: \n" + originalValueString);
1638         getOutPrintWriter().println("New value: \n" + newValueString);
1639 
1640         return 0;
1641     }
1642 
1643     // cc set-values-from-xml
handleCcSetValuesFromXml()1644     private int handleCcSetValuesFromXml() {
1645         PrintWriter errPw = getErrPrintWriter();
1646         String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1647 
1648         // Parse all options
1649         CcOptionParseResult options = parseCcOptions(tag, true);
1650         if (options == null) {
1651             return -1;
1652         }
1653 
1654         // Get bundle containing all current carrier configuration values.
1655         PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1656         if (originalValues == null) {
1657             errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1658             return -1;
1659         }
1660 
1661         PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1662         if (overrideBundle == null) {
1663             return -1;
1664         }
1665 
1666         // Verify all values are valid types
1667         for (String key : overrideBundle.keySet()) {
1668             CcType type = getType(tag, key, originalValues);
1669             if (type == CcType.UNKNOWN) {
1670                 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1671                 return -1;
1672             }
1673         }
1674 
1675         // Override the value
1676         mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1677 
1678         // Find bundle containing all new carrier configuration values after the override.
1679         PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1680         if (newValues == null) {
1681             errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1682             return -1;
1683         }
1684 
1685         // Print the original and new values
1686         overrideBundle.keySet().forEach(key -> {
1687             CcType type = getType(tag, key, originalValues);
1688             String originalValueString = ccValueToString(key, type, originalValues);
1689             String newValueString = ccValueToString(key, type, newValues);
1690             getOutPrintWriter().println("Previous value: \n" + originalValueString);
1691             getOutPrintWriter().println("New value: \n" + newValueString);
1692         });
1693 
1694         return 0;
1695     }
1696 
readPersistableBundleFromXml(String tag)1697     private PersistableBundle readPersistableBundleFromXml(String tag) {
1698         PersistableBundle subIdBundles;
1699         try {
1700             subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1701         } catch (IOException | RuntimeException e) {
1702             PrintWriter errPw = getErrPrintWriter();
1703             errPw.println(tag + e);
1704             return null;
1705         }
1706 
1707         return subIdBundles;
1708     }
1709 
1710     // cc clear-values
handleCcClearValues()1711     private int handleCcClearValues() {
1712         String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1713 
1714         // Parse all options
1715         CcOptionParseResult options = parseCcOptions(tag, false);
1716         if (options == null) {
1717             return -1;
1718         }
1719 
1720         // Clear all values that has previously been set.
1721         mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
1722         getOutPrintWriter()
1723                 .println("All previously set carrier config override values has been cleared");
1724         return 0;
1725     }
1726 
getType(String tag, String key, PersistableBundle bundle)1727     private CcType getType(String tag, String key, PersistableBundle bundle) {
1728         // Find the type by checking the type of the current value stored in the bundle.
1729         Object value = bundle.get(key);
1730 
1731         if (CC_TYPE_MAP.containsKey(key)) {
1732             return CC_TYPE_MAP.get(key);
1733         } else if (value != null) {
1734             if (value instanceof Boolean) {
1735                 return CcType.BOOLEAN;
1736             }
1737             if (value instanceof Double) {
1738                 return CcType.DOUBLE;
1739             }
1740             if (value instanceof double[]) {
1741                 return CcType.DOUBLE_ARRAY;
1742             }
1743             if (value instanceof Integer) {
1744                 return CcType.INT;
1745             }
1746             if (value instanceof int[]) {
1747                 return CcType.INT_ARRAY;
1748             }
1749             if (value instanceof Long) {
1750                 return CcType.LONG;
1751             }
1752             if (value instanceof long[]) {
1753                 return CcType.LONG_ARRAY;
1754             }
1755             if (value instanceof String) {
1756                 return CcType.STRING;
1757             }
1758             if (value instanceof String[]) {
1759                 return CcType.STRING_ARRAY;
1760             }
1761             if (value instanceof PersistableBundle) {
1762                 return CcType.PERSISTABLE_BUNDLE;
1763             }
1764         } else {
1765             // Current value was null and can therefore not be used in order to find the type.
1766             // Check the name of the key to infer the type. This check is not needed for primitive
1767             // data types (boolean, double, int and long), since they can not be null.
1768             if (key.endsWith("double_array")) {
1769                 return CcType.DOUBLE_ARRAY;
1770             }
1771             if (key.endsWith("int_array")) {
1772                 return CcType.INT_ARRAY;
1773             }
1774             if (key.endsWith("long_array")) {
1775                 return CcType.LONG_ARRAY;
1776             }
1777             if (key.endsWith("string")) {
1778                 return CcType.STRING;
1779             }
1780             if (key.endsWith("string_array") || key.endsWith("strings")) {
1781                 return CcType.STRING_ARRAY;
1782             }
1783             if (key.endsWith("bundle")) {
1784                 return CcType.PERSISTABLE_BUNDLE;
1785             }
1786         }
1787 
1788         // Not possible to infer the type by looking at the current value or the key.
1789         PrintWriter errPw = getErrPrintWriter();
1790         errPw.println(tag + "ERROR: " + key + " has unknown type.");
1791         return CcType.UNKNOWN;
1792     }
1793 
ccValueToString(String key, CcType type, PersistableBundle bundle)1794     private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1795         String result;
1796         StringBuilder valueString = new StringBuilder();
1797         String typeString = type.toString();
1798         Object value = bundle.get(key);
1799 
1800         if (value == null) {
1801             valueString.append("null");
1802         } else {
1803             switch (type) {
1804                 case DOUBLE_ARRAY: {
1805                     // Format the string representation of the int array as value1 value2......
1806                     double[] valueArray = (double[]) value;
1807                     for (int i = 0; i < valueArray.length; i++) {
1808                         if (i != 0) {
1809                             valueString.append(" ");
1810                         }
1811                         valueString.append(valueArray[i]);
1812                     }
1813                     break;
1814                 }
1815                 case INT_ARRAY: {
1816                     // Format the string representation of the int array as value1 value2......
1817                     int[] valueArray = (int[]) value;
1818                     for (int i = 0; i < valueArray.length; i++) {
1819                         if (i != 0) {
1820                             valueString.append(" ");
1821                         }
1822                         valueString.append(valueArray[i]);
1823                     }
1824                     break;
1825                 }
1826                 case LONG_ARRAY: {
1827                     // Format the string representation of the int array as value1 value2......
1828                     long[] valueArray = (long[]) value;
1829                     for (int i = 0; i < valueArray.length; i++) {
1830                         if (i != 0) {
1831                             valueString.append(" ");
1832                         }
1833                         valueString.append(valueArray[i]);
1834                     }
1835                     break;
1836                 }
1837                 case STRING: {
1838                     valueString.append("\"" + value.toString() + "\"");
1839                     break;
1840                 }
1841                 case STRING_ARRAY: {
1842                     // Format the string representation of the string array as "value1" "value2"....
1843                     String[] valueArray = (String[]) value;
1844                     for (int i = 0; i < valueArray.length; i++) {
1845                         if (i != 0) {
1846                             valueString.append(" ");
1847                         }
1848                         if (valueArray[i] != null) {
1849                             valueString.append("\"" + valueArray[i] + "\"");
1850                         } else {
1851                             valueString.append("null");
1852                         }
1853                     }
1854                     break;
1855                 }
1856                 default: {
1857                     valueString.append(value.toString());
1858                 }
1859             }
1860         }
1861         return String.format("%-70s %-15s %s", key, typeString, valueString);
1862     }
1863 
getOverrideBundle(String tag, CcType type, String key, ArrayList<String> valueList)1864     private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1865             ArrayList<String> valueList) {
1866         PrintWriter errPw = getErrPrintWriter();
1867         PersistableBundle bundle = new PersistableBundle();
1868 
1869         // First verify that a valid number of values has been provided for the type.
1870         switch (type) {
1871             case BOOLEAN:
1872             case DOUBLE:
1873             case INT:
1874             case LONG: {
1875                 if (valueList.size() != 1) {
1876                     errPw.println(tag + "Expected 1 value for type " + type
1877                             + ". Found: " + valueList.size());
1878                     return null;
1879                 }
1880                 break;
1881             }
1882             case STRING: {
1883                 if (valueList.size() > 1) {
1884                     errPw.println(tag + "Expected 0 or 1 values for type " + type
1885                             + ". Found: " + valueList.size());
1886                     return null;
1887                 }
1888                 break;
1889             }
1890         }
1891 
1892         // Parse the value according to type and add it to the Bundle.
1893         switch (type) {
1894             case BOOLEAN: {
1895                 if ("true".equalsIgnoreCase(valueList.get(0))) {
1896                     bundle.putBoolean(key, true);
1897                 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1898                     bundle.putBoolean(key, false);
1899                 } else {
1900                     errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1901                     return null;
1902                 }
1903                 break;
1904             }
1905             case DOUBLE: {
1906                 try {
1907                     bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1908                 } catch (NumberFormatException nfe) {
1909                     // Not a valid double
1910                     errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1911                     return null;
1912                 }
1913                 break;
1914             }
1915             case DOUBLE_ARRAY: {
1916                 double[] valueDoubleArray = null;
1917                 if (valueList.size() > 0) {
1918                     valueDoubleArray = new double[valueList.size()];
1919                     for (int i = 0; i < valueList.size(); i++) {
1920                         try {
1921                             valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1922                         } catch (NumberFormatException nfe) {
1923                             // Not a valid double
1924                             errPw.println(
1925                                     tag + "Unable to parse " + valueList.get(i) + " as a double.");
1926                             return null;
1927                         }
1928                     }
1929                 }
1930                 bundle.putDoubleArray(key, valueDoubleArray);
1931                 break;
1932             }
1933             case INT: {
1934                 try {
1935                     bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1936                 } catch (NumberFormatException nfe) {
1937                     // Not a valid integer
1938                     errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1939                     return null;
1940                 }
1941                 break;
1942             }
1943             case INT_ARRAY: {
1944                 int[] valueIntArray = null;
1945                 if (valueList.size() > 0) {
1946                     valueIntArray = new int[valueList.size()];
1947                     for (int i = 0; i < valueList.size(); i++) {
1948                         try {
1949                             valueIntArray[i] = Integer.parseInt(valueList.get(i));
1950                         } catch (NumberFormatException nfe) {
1951                             // Not a valid integer
1952                             errPw.println(tag
1953                                     + "Unable to parse " + valueList.get(i) + " as an integer.");
1954                             return null;
1955                         }
1956                     }
1957                 }
1958                 bundle.putIntArray(key, valueIntArray);
1959                 break;
1960             }
1961             case LONG: {
1962                 try {
1963                     bundle.putLong(key, Long.parseLong(valueList.get(0)));
1964                 } catch (NumberFormatException nfe) {
1965                     // Not a valid long
1966                     errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1967                     return null;
1968                 }
1969                 break;
1970             }
1971             case LONG_ARRAY: {
1972                 long[] valueLongArray = null;
1973                 if (valueList.size() > 0) {
1974                     valueLongArray = new long[valueList.size()];
1975                     for (int i = 0; i < valueList.size(); i++) {
1976                         try {
1977                             valueLongArray[i] = Long.parseLong(valueList.get(i));
1978                         } catch (NumberFormatException nfe) {
1979                             // Not a valid long
1980                             errPw.println(
1981                                     tag + "Unable to parse " + valueList.get(i) + " as a long");
1982                             return null;
1983                         }
1984                     }
1985                 }
1986                 bundle.putLongArray(key, valueLongArray);
1987                 break;
1988             }
1989             case STRING: {
1990                 String value = null;
1991                 if (valueList.size() > 0) {
1992                     value = valueList.get(0);
1993                 }
1994                 bundle.putString(key, value);
1995                 break;
1996             }
1997             case STRING_ARRAY: {
1998                 String[] valueStringArray = null;
1999                 if (valueList.size() > 0) {
2000                     valueStringArray = new String[valueList.size()];
2001                     valueList.toArray(valueStringArray);
2002                 }
2003                 bundle.putStringArray(key, valueStringArray);
2004                 break;
2005             }
2006         }
2007         return bundle;
2008     }
2009 
handleEndBlockSuppressionCommand()2010     private int handleEndBlockSuppressionCommand() {
2011         if (!checkShellUid()) {
2012             return -1;
2013         }
2014 
2015         if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2016             BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2017         }
2018         return 0;
2019     }
2020 
handleRestartModemCommand()2021     private int handleRestartModemCommand() {
2022         // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2023         // non user build.
2024         if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2025             getErrPrintWriter().println("RestartModem: Permission denied.");
2026             return -1;
2027         }
2028 
2029         boolean result = TelephonyManager.getDefault().rebootRadio();
2030         getOutPrintWriter().println(result);
2031 
2032         return result ? 0 : -1;
2033     }
2034 
handleGetImei()2035     private int handleGetImei() {
2036         // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2037         // non user build.
2038         if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2039             getErrPrintWriter().println("Device IMEI: Permission denied.");
2040             return -1;
2041         }
2042 
2043         final long identity = Binder.clearCallingIdentity();
2044 
2045         String imei = null;
2046         String arg = getNextArg();
2047         if (arg != null) {
2048             try {
2049                 int specifiedSlotIndex = Integer.parseInt(arg);
2050                 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2051             } catch (NumberFormatException exception) {
2052                 PrintWriter errPw = getErrPrintWriter();
2053                 errPw.println("-s requires an integer as slot index.");
2054                 return -1;
2055             }
2056 
2057         } else {
2058             imei = TelephonyManager.from(mContext).getImei();
2059         }
2060         getOutPrintWriter().println("Device IMEI: " + imei);
2061 
2062         Binder.restoreCallingIdentity(identity);
2063         return 0;
2064     }
2065 
handleUnattendedReboot()2066     private int handleUnattendedReboot() {
2067         // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2068         // non user build.
2069         if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2070             getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2071             return -1;
2072         }
2073 
2074         int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2075         getOutPrintWriter().println("result: " + result);
2076 
2077         return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2078     }
2079 
handleGetSimSlotsMapping()2080     private int handleGetSimSlotsMapping() {
2081         // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2082         // non user build.
2083         if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2084             getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2085             return -1;
2086         }
2087         TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2088         String result = telephonyManager.getSimSlotMapping().toString();
2089         getOutPrintWriter().println("simSlotsMapping: " + result);
2090 
2091         return 0;
2092     }
2093 
handleGbaCommand()2094     private int handleGbaCommand() {
2095         String arg = getNextArg();
2096         if (arg == null) {
2097             onHelpGba();
2098             return 0;
2099         }
2100 
2101         switch (arg) {
2102             case GBA_SET_SERVICE: {
2103                 return handleGbaSetServiceCommand();
2104             }
2105             case GBA_GET_SERVICE: {
2106                 return handleGbaGetServiceCommand();
2107             }
2108             case GBA_SET_RELEASE_TIME: {
2109                 return handleGbaSetReleaseCommand();
2110             }
2111             case GBA_GET_RELEASE_TIME: {
2112                 return handleGbaGetReleaseCommand();
2113             }
2114         }
2115 
2116         return -1;
2117     }
2118 
getSubId(String cmd)2119     private int getSubId(String cmd) {
2120         int slotId = getDefaultSlot();
2121         String opt = getNextOption();
2122         if (opt != null && opt.equals("-s")) {
2123             try {
2124                 slotId = Integer.parseInt(getNextArgRequired());
2125             } catch (NumberFormatException e) {
2126                 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2127                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2128             }
2129         }
2130         int[] subIds = SubscriptionManager.getSubId(slotId);
2131         return subIds[0];
2132     }
2133 
handleGbaSetServiceCommand()2134     private int handleGbaSetServiceCommand() {
2135         int subId = getSubId("gba set-service");
2136         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2137             return -1;
2138         }
2139 
2140         String packageName = getNextArg();
2141         try {
2142             if (packageName == null) {
2143                 packageName = "";
2144             }
2145             boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2146             if (VDBG) {
2147                 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2148                         + packageName + ", result=" + result);
2149             }
2150             getOutPrintWriter().println(result);
2151         } catch (RemoteException e) {
2152             Log.w(LOG_TAG, "gba set-service " + subId + " "
2153                     + packageName + ", error" + e.getMessage());
2154             getErrPrintWriter().println("Exception: " + e.getMessage());
2155             return -1;
2156         }
2157         return 0;
2158     }
2159 
handleGbaGetServiceCommand()2160     private int handleGbaGetServiceCommand() {
2161         String result;
2162 
2163         int subId = getSubId("gba get-service");
2164         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2165             return -1;
2166         }
2167 
2168         try {
2169             result = mInterface.getBoundGbaService(subId);
2170         } catch (RemoteException e) {
2171             return -1;
2172         }
2173         if (VDBG) {
2174             Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2175         }
2176         getOutPrintWriter().println(result);
2177         return 0;
2178     }
2179 
handleGbaSetReleaseCommand()2180     private int handleGbaSetReleaseCommand() {
2181         //the release time value could be -1
2182         int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2183                 : SubscriptionManager.getDefaultSubscriptionId();
2184         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2185             return -1;
2186         }
2187 
2188         String intervalStr = getNextArg();
2189         if (intervalStr == null) {
2190             return -1;
2191         }
2192 
2193         try {
2194             int interval = Integer.parseInt(intervalStr);
2195             boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2196             if (VDBG) {
2197                 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2198                         + intervalStr + ", result=" + result);
2199             }
2200             getOutPrintWriter().println(result);
2201         } catch (NumberFormatException | RemoteException e) {
2202             Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2203                     + intervalStr + ", error" + e.getMessage());
2204             getErrPrintWriter().println("Exception: " + e.getMessage());
2205             return -1;
2206         }
2207         return 0;
2208     }
2209 
handleGbaGetReleaseCommand()2210     private int handleGbaGetReleaseCommand() {
2211         int subId = getSubId("gba get-release");
2212         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2213             return -1;
2214         }
2215 
2216         int result = 0;
2217         try {
2218             result = mInterface.getGbaReleaseTime(subId);
2219         } catch (RemoteException e) {
2220             return -1;
2221         }
2222         if (VDBG) {
2223             Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2224         }
2225         getOutPrintWriter().println(result);
2226         return 0;
2227     }
2228 
handleSingleRegistrationConfigCommand()2229     private int handleSingleRegistrationConfigCommand() {
2230         String arg = getNextArg();
2231         if (arg == null) {
2232             onHelpSrc();
2233             return 0;
2234         }
2235 
2236         switch (arg) {
2237             case SRC_SET_TEST_ENABLED: {
2238                 return handleSrcSetTestEnabledCommand();
2239             }
2240             case SRC_GET_TEST_ENABLED: {
2241                 return handleSrcGetTestEnabledCommand();
2242             }
2243             case SRC_SET_DEVICE_ENABLED: {
2244                 return handleSrcSetDeviceEnabledCommand();
2245             }
2246             case SRC_GET_DEVICE_ENABLED: {
2247                 return handleSrcGetDeviceEnabledCommand();
2248             }
2249             case SRC_SET_CARRIER_ENABLED: {
2250                 return handleSrcSetCarrierEnabledCommand();
2251             }
2252             case SRC_GET_CARRIER_ENABLED: {
2253                 return handleSrcGetCarrierEnabledCommand();
2254             }
2255             case SRC_SET_FEATURE_ENABLED: {
2256                 return handleSrcSetFeatureValidationCommand();
2257             }
2258             case SRC_GET_FEATURE_ENABLED: {
2259                 return handleSrcGetFeatureValidationCommand();
2260             }
2261         }
2262 
2263         return -1;
2264     }
2265 
handleRcsUceCommand()2266     private int handleRcsUceCommand() {
2267         String arg = getNextArg();
2268         if (arg == null) {
2269             onHelpUce();
2270             return 0;
2271         }
2272 
2273         switch (arg) {
2274             case UCE_REMOVE_EAB_CONTACT:
2275                 return handleRemovingEabContactCommand();
2276             case UCE_GET_EAB_CONTACT:
2277                 return handleGettingEabContactCommand();
2278             case UCE_GET_EAB_CAPABILITY:
2279                 return handleGettingEabCapabilityCommand();
2280             case UCE_GET_DEVICE_ENABLED:
2281                 return handleUceGetDeviceEnabledCommand();
2282             case UCE_SET_DEVICE_ENABLED:
2283                 return handleUceSetDeviceEnabledCommand();
2284             case UCE_OVERRIDE_PUBLISH_CAPS:
2285                 return handleUceOverridePublishCaps();
2286             case UCE_GET_LAST_PIDF_XML:
2287                 return handleUceGetPidfXml();
2288             case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2289                 return handleUceRemoveRequestDisallowedStatus();
2290             case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2291                 return handleUceSetCapRequestTimeout();
2292         }
2293         return -1;
2294     }
2295 
handleRemovingEabContactCommand()2296     private int handleRemovingEabContactCommand() {
2297         int subId = getSubId("uce remove-eab-contact");
2298         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2299             return -1;
2300         }
2301 
2302         String phoneNumber = getNextArgRequired();
2303         if (TextUtils.isEmpty(phoneNumber)) {
2304             return -1;
2305         }
2306         int result = 0;
2307         try {
2308             result = mInterface.removeContactFromEab(subId, phoneNumber);
2309         } catch (RemoteException e) {
2310             Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2311             getErrPrintWriter().println("Exception: " + e.getMessage());
2312             return -1;
2313         }
2314 
2315         if (VDBG) {
2316             Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2317         }
2318         return 0;
2319     }
2320 
handleGettingEabContactCommand()2321     private int handleGettingEabContactCommand() {
2322         String phoneNumber = getNextArgRequired();
2323         if (TextUtils.isEmpty(phoneNumber)) {
2324             return -1;
2325         }
2326         String result = "";
2327         try {
2328             result = mInterface.getContactFromEab(phoneNumber);
2329         } catch (RemoteException e) {
2330             Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2331             getErrPrintWriter().println("Exception: " + e.getMessage());
2332             return -1;
2333         }
2334 
2335         if (VDBG) {
2336             Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2337         }
2338         getOutPrintWriter().println(result);
2339         return 0;
2340     }
2341 
handleGettingEabCapabilityCommand()2342     private int handleGettingEabCapabilityCommand() {
2343         String phoneNumber = getNextArgRequired();
2344         if (TextUtils.isEmpty(phoneNumber)) {
2345             return -1;
2346         }
2347         String result = "";
2348         try {
2349             result = mInterface.getCapabilityFromEab(phoneNumber);
2350         } catch (RemoteException e) {
2351             Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2352             getErrPrintWriter().println("Exception: " + e.getMessage());
2353             return -1;
2354         }
2355 
2356         if (VDBG) {
2357             Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2358         }
2359         getOutPrintWriter().println(result);
2360         return 0;
2361     }
2362 
handleUceGetDeviceEnabledCommand()2363     private int handleUceGetDeviceEnabledCommand() {
2364         boolean result = false;
2365         try {
2366             result = mInterface.getDeviceUceEnabled();
2367         } catch (RemoteException e) {
2368             Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2369             return -1;
2370         }
2371         if (VDBG) {
2372             Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2373         }
2374         getOutPrintWriter().println(result);
2375         return 0;
2376     }
2377 
handleUceSetDeviceEnabledCommand()2378     private int handleUceSetDeviceEnabledCommand() {
2379         String enabledStr = getNextArg();
2380         if (TextUtils.isEmpty(enabledStr)) {
2381             return -1;
2382         }
2383 
2384         try {
2385             boolean isEnabled = Boolean.parseBoolean(enabledStr);
2386             mInterface.setDeviceUceEnabled(isEnabled);
2387             if (VDBG) {
2388                 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2389             }
2390         } catch (NumberFormatException | RemoteException e) {
2391             Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2392             getErrPrintWriter().println("Exception: " + e.getMessage());
2393             return -1;
2394         }
2395         return 0;
2396     }
2397 
handleUceRemoveRequestDisallowedStatus()2398     private int handleUceRemoveRequestDisallowedStatus() {
2399         int subId = getSubId("uce remove-request-disallowed-status");
2400         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2401             Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2402             return -1;
2403         }
2404         boolean result;
2405         try {
2406             result = mInterface.removeUceRequestDisallowedStatus(subId);
2407         } catch (RemoteException e) {
2408             Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2409             return -1;
2410         }
2411         if (VDBG) {
2412             Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2413         }
2414         getOutPrintWriter().println(result);
2415         return 0;
2416     }
2417 
handleUceSetCapRequestTimeout()2418     private int handleUceSetCapRequestTimeout() {
2419         int subId = getSubId("uce set-capabilities-request-timeout");
2420         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2421             Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2422             return -1;
2423         }
2424         long timeoutAfterMs = Long.valueOf(getNextArg());
2425         boolean result;
2426         try {
2427             result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2428         } catch (RemoteException e) {
2429             Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2430             return -1;
2431         }
2432         if (VDBG) {
2433             Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2434         }
2435         getOutPrintWriter().println(result);
2436         return 0;
2437     }
2438 
handleSrcSetTestEnabledCommand()2439     private int handleSrcSetTestEnabledCommand() {
2440         String enabledStr = getNextArg();
2441         if (enabledStr == null) {
2442             return -1;
2443         }
2444 
2445         try {
2446             mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2447             if (VDBG) {
2448                 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2449             }
2450             getOutPrintWriter().println("Done");
2451         } catch (NumberFormatException | RemoteException e) {
2452             Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2453             getErrPrintWriter().println("Exception: " + e.getMessage());
2454             return -1;
2455         }
2456         return 0;
2457     }
2458 
handleSrcGetTestEnabledCommand()2459     private int handleSrcGetTestEnabledCommand() {
2460         boolean result = false;
2461         try {
2462             result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2463         } catch (RemoteException e) {
2464             return -1;
2465         }
2466         if (VDBG) {
2467             Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2468         }
2469         getOutPrintWriter().println(result);
2470         return 0;
2471     }
2472 
handleUceOverridePublishCaps()2473     private int handleUceOverridePublishCaps() {
2474         int subId = getSubId("uce override-published-caps");
2475         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2476             return -1;
2477         }
2478         //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2479         String operation = getNextArgRequired();
2480         String caps = getNextArg();
2481         if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2482                 && !"list".equals(operation)) {
2483             getErrPrintWriter().println("Invalid operation: " + operation);
2484             return -1;
2485         }
2486 
2487         // add/remove requires capabilities to be specified.
2488         if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2489             getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2490                     + "specified");
2491             return -1;
2492         }
2493 
2494         ArraySet<String> capSet = new ArraySet<>();
2495         if (!TextUtils.isEmpty(caps)) {
2496             String[] capArray = caps.split(":");
2497             for (String cap : capArray) {
2498                 // Allow unknown tags to be passed in as well.
2499                 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2500             }
2501         }
2502 
2503         RcsContactUceCapability result = null;
2504         try {
2505             switch (operation) {
2506                 case "add":
2507                     result = mInterface.addUceRegistrationOverrideShell(subId,
2508                             new ArrayList<>(capSet));
2509                     break;
2510                 case "remove":
2511                     result = mInterface.removeUceRegistrationOverrideShell(subId,
2512                             new ArrayList<>(capSet));
2513                     break;
2514                 case "clear":
2515                     result = mInterface.clearUceRegistrationOverrideShell(subId);
2516                     break;
2517                 case "list":
2518                     result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2519                     break;
2520             }
2521         } catch (RemoteException e) {
2522             Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2523             getErrPrintWriter().println("Exception: " + e.getMessage());
2524             return -1;
2525         } catch (ServiceSpecificException sse) {
2526             // Reconstruct ImsException
2527             ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2528             Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2529             getErrPrintWriter().println("Exception: " + imsException);
2530             return -1;
2531         }
2532         if (result == null) {
2533             getErrPrintWriter().println("Service not available");
2534             return -1;
2535         }
2536         getOutPrintWriter().println(result);
2537         return 0;
2538     }
2539 
handleUceGetPidfXml()2540     private int handleUceGetPidfXml() {
2541         int subId = getSubId("uce get-last-publish-pidf");
2542         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2543             return -1;
2544         }
2545 
2546         String result;
2547         try {
2548             result = mInterface.getLastUcePidfXmlShell(subId);
2549         } catch (RemoteException e) {
2550             Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2551             getErrPrintWriter().println("Exception: " + e.getMessage());
2552             return -1;
2553         } catch (ServiceSpecificException sse) {
2554             // Reconstruct ImsException
2555             ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2556             Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2557             getErrPrintWriter().println("Exception: " + imsException);
2558             return -1;
2559         }
2560         if (result == null) {
2561             getErrPrintWriter().println("Service not available");
2562             return -1;
2563         }
2564         getOutPrintWriter().println(result);
2565         return 0;
2566     }
2567 
handleSrcSetDeviceEnabledCommand()2568     private int handleSrcSetDeviceEnabledCommand() {
2569         String enabledStr = getNextArg();
2570         if (enabledStr == null) {
2571             return -1;
2572         }
2573 
2574         try {
2575             mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2576             if (VDBG) {
2577                 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2578             }
2579             getOutPrintWriter().println("Done");
2580         } catch (NumberFormatException | RemoteException e) {
2581             Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2582             getErrPrintWriter().println("Exception: " + e.getMessage());
2583             return -1;
2584         }
2585         return 0;
2586     }
2587 
handleSrcGetDeviceEnabledCommand()2588     private int handleSrcGetDeviceEnabledCommand() {
2589         boolean result = false;
2590         try {
2591             result = mInterface.getDeviceSingleRegistrationEnabled();
2592         } catch (RemoteException e) {
2593             return -1;
2594         }
2595         if (VDBG) {
2596             Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2597         }
2598         getOutPrintWriter().println(result);
2599         return 0;
2600     }
2601 
handleSrcSetCarrierEnabledCommand()2602     private int handleSrcSetCarrierEnabledCommand() {
2603         //the release time value could be -1
2604         int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2605                 : SubscriptionManager.getDefaultSubscriptionId();
2606         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2607             return -1;
2608         }
2609 
2610         String enabledStr = getNextArg();
2611         if (enabledStr == null) {
2612             return -1;
2613         }
2614 
2615         try {
2616             boolean result =
2617                     mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2618             if (VDBG) {
2619                 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2620                         + enabledStr + ", result=" + result);
2621             }
2622             getOutPrintWriter().println(result);
2623         } catch (NumberFormatException | RemoteException e) {
2624             Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2625                     + enabledStr + ", error" + e.getMessage());
2626             getErrPrintWriter().println("Exception: " + e.getMessage());
2627             return -1;
2628         }
2629         return 0;
2630     }
2631 
handleSrcGetCarrierEnabledCommand()2632     private int handleSrcGetCarrierEnabledCommand() {
2633         int subId = getSubId("src get-carrier-enabled");
2634         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2635             return -1;
2636         }
2637 
2638         boolean result = false;
2639         try {
2640             result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2641         } catch (RemoteException e) {
2642             return -1;
2643         }
2644         if (VDBG) {
2645             Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2646         }
2647         getOutPrintWriter().println(result);
2648         return 0;
2649     }
2650 
handleSrcSetFeatureValidationCommand()2651     private int handleSrcSetFeatureValidationCommand() {
2652         //the release time value could be -1
2653         int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2654                 : SubscriptionManager.getDefaultSubscriptionId();
2655         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2656             return -1;
2657         }
2658 
2659         String enabledStr = getNextArg();
2660         if (enabledStr == null) {
2661             return -1;
2662         }
2663 
2664         try {
2665             boolean result =
2666                     mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2667             if (VDBG) {
2668                 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2669                         + enabledStr + ", result=" + result);
2670             }
2671             getOutPrintWriter().println(result);
2672         } catch (NumberFormatException | RemoteException e) {
2673             Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2674                     + enabledStr + ", error" + e.getMessage());
2675             getErrPrintWriter().println("Exception: " + e.getMessage());
2676             return -1;
2677         }
2678         return 0;
2679     }
2680 
handleSrcGetFeatureValidationCommand()2681     private int handleSrcGetFeatureValidationCommand() {
2682         int subId = getSubId("src get-feature-validation");
2683         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2684             return -1;
2685         }
2686 
2687         Boolean result = false;
2688         try {
2689             result = mInterface.getImsFeatureValidationOverride(subId);
2690         } catch (RemoteException e) {
2691             return -1;
2692         }
2693         if (VDBG) {
2694             Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2695         }
2696         getOutPrintWriter().println(result);
2697         return 0;
2698     }
2699 
2700 
onHelpCallComposer()2701     private void onHelpCallComposer() {
2702         PrintWriter pw = getOutPrintWriter();
2703         pw.println("Call composer commands");
2704         pw.println("  callcomposer test-mode enable|disable|query");
2705         pw.println("    Enables or disables test mode for call composer. In test mode, picture");
2706         pw.println("    upload/download from carrier servers is disabled, and operations are");
2707         pw.println("    performed using emulated local files instead.");
2708         pw.println("  callcomposer simulate-outgoing-call [subId] [UUID]");
2709         pw.println("    Simulates an outgoing call being placed with the picture ID as");
2710         pw.println("    the provided UUID. This triggers storage to the call log.");
2711         pw.println("  callcomposer user-setting [subId] enable|disable|query");
2712         pw.println("    Enables or disables the user setting for call composer, as set by");
2713         pw.println("    TelephonyManager#setCallComposerStatus.");
2714     }
2715 
handleCallComposerCommand()2716     private int handleCallComposerCommand() {
2717         String arg = getNextArg();
2718         if (arg == null) {
2719             onHelpCallComposer();
2720             return 0;
2721         }
2722 
2723         mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2724                 "MODIFY_PHONE_STATE required for call composer shell cmds");
2725         switch (arg) {
2726             case CALL_COMPOSER_TEST_MODE: {
2727                 String enabledStr = getNextArg();
2728                 if (ENABLE.equals(enabledStr)) {
2729                     CallComposerPictureManager.sTestMode = true;
2730                 } else if (DISABLE.equals(enabledStr)) {
2731                     CallComposerPictureManager.sTestMode = false;
2732                 } else if (QUERY.equals(enabledStr)) {
2733                     getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2734                 } else {
2735                     onHelpCallComposer();
2736                     return 1;
2737                 }
2738                 break;
2739             }
2740             case CALL_COMPOSER_SIMULATE_CALL: {
2741                 int subscriptionId = Integer.valueOf(getNextArg());
2742                 String uuidString = getNextArg();
2743                 UUID uuid = UUID.fromString(uuidString);
2744                 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2745                 Binder.withCleanCallingIdentity(() -> {
2746                     CallComposerPictureManager.getInstance(mContext, subscriptionId)
2747                             .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2748                 });
2749                 try {
2750                     Uri uri = storageUriFuture.get();
2751                     getOutPrintWriter().println(String.valueOf(uri));
2752                 } catch (Exception e) {
2753                     throw new RuntimeException(e);
2754                 }
2755                 break;
2756             }
2757             case CALL_COMPOSER_USER_SETTING: {
2758                 try {
2759                     int subscriptionId = Integer.valueOf(getNextArg());
2760                     String enabledStr = getNextArg();
2761                     if (ENABLE.equals(enabledStr)) {
2762                         mInterface.setCallComposerStatus(subscriptionId,
2763                                 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2764                     } else if (DISABLE.equals(enabledStr)) {
2765                         mInterface.setCallComposerStatus(subscriptionId,
2766                                 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2767                     } else if (QUERY.equals(enabledStr)) {
2768                         getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2769                                 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2770                     } else {
2771                         onHelpCallComposer();
2772                         return 1;
2773                     }
2774                 } catch (RemoteException e) {
2775                     e.printStackTrace(getOutPrintWriter());
2776                     return 1;
2777                 }
2778                 break;
2779             }
2780         }
2781         return 0;
2782     }
2783 
handleHasCarrierPrivilegesCommand()2784     private int handleHasCarrierPrivilegesCommand() {
2785         String packageName = getNextArgRequired();
2786 
2787         boolean hasCarrierPrivileges;
2788         final long token = Binder.clearCallingIdentity();
2789         try {
2790             hasCarrierPrivileges =
2791                     mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2792                             == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2793         } catch (RemoteException e) {
2794             Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2795             getErrPrintWriter().println("Exception: " + e.getMessage());
2796             return -1;
2797         } finally {
2798             Binder.restoreCallingIdentity(token);
2799         }
2800 
2801         getOutPrintWriter().println(hasCarrierPrivileges);
2802         return 0;
2803     }
2804 
handleAllowedNetworkTypesCommand(String command)2805     private int handleAllowedNetworkTypesCommand(String command) {
2806         if (!checkShellUid()) {
2807             return -1;
2808         }
2809 
2810         PrintWriter errPw = getErrPrintWriter();
2811         String tag = command + ": ";
2812         String opt;
2813         int subId = -1;
2814         Log.v(LOG_TAG, command + " start");
2815 
2816         while ((opt = getNextOption()) != null) {
2817             if (opt.equals("-s")) {
2818                 try {
2819                     subId = slotStringToSubId(tag, getNextArgRequired());
2820                     if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2821                         errPw.println(tag + "No valid subscription found.");
2822                         return -1;
2823                     }
2824                 } catch (IllegalArgumentException e) {
2825                     // Missing slot id
2826                     errPw.println(tag + "SLOT_ID expected after -s.");
2827                     return -1;
2828                 }
2829             } else {
2830                 errPw.println(tag + "Unknown option " + opt);
2831                 return -1;
2832             }
2833         }
2834 
2835         if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2836             return handleGetAllowedNetworkTypesCommand(subId);
2837         }
2838         if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2839             return handleSetAllowedNetworkTypesCommand(subId);
2840         }
2841         return -1;
2842     }
2843 
handleGetAllowedNetworkTypesCommand(int subId)2844     private int handleGetAllowedNetworkTypesCommand(int subId) {
2845         PrintWriter errPw = getErrPrintWriter();
2846 
2847         long result = -1;
2848         try {
2849             if (mInterface != null) {
2850                 result = mInterface.getAllowedNetworkTypesForReason(subId,
2851                         TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2852             } else {
2853                 throw new IllegalStateException("telephony service is null.");
2854             }
2855         } catch (RemoteException e) {
2856             Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2857             errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2858             return -1;
2859         }
2860 
2861         getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2862         return 0;
2863     }
2864 
handleSetAllowedNetworkTypesCommand(int subId)2865     private int handleSetAllowedNetworkTypesCommand(int subId) {
2866         PrintWriter errPw = getErrPrintWriter();
2867 
2868         String bitmaskString = getNextArg();
2869         if (TextUtils.isEmpty(bitmaskString)) {
2870             errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2871             return -1;
2872         }
2873         long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2874         if (allowedNetworkTypes < 0) {
2875             errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2876             return -1;
2877         }
2878         boolean result = false;
2879         try {
2880             if (mInterface != null) {
2881                 result = mInterface.setAllowedNetworkTypesForReason(subId,
2882                         TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2883             } else {
2884                 throw new IllegalStateException("telephony service is null.");
2885             }
2886         } catch (RemoteException e) {
2887             Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2888             errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2889             return -1;
2890         }
2891 
2892         String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2893         if (result) {
2894             resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2895         }
2896         getOutPrintWriter().println(resultMessage);
2897         return 0;
2898     }
2899 
convertNetworkTypeBitmaskFromStringToLong(String bitmaskString)2900     private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2901         if (TextUtils.isEmpty(bitmaskString)) {
2902             return -1;
2903         }
2904         if (VDBG) {
2905             Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2906                             + ", length: " + bitmaskString.length());
2907         }
2908         try {
2909             return Long.parseLong(bitmaskString, 2);
2910         } catch (NumberFormatException e) {
2911             Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2912             return -1;
2913         }
2914     }
2915 
handleGetDataMode()2916     private int handleGetDataMode() {
2917         if (!checkShellUid()) {
2918             return -1;
2919         }
2920 
2921         boolean newDataStackEnabled = false;
2922         try {
2923             newDataStackEnabled = mInterface.isUsingNewDataStack();
2924         } catch (RemoteException e) {
2925             getOutPrintWriter().println("Something went wrong. " + e);
2926             return -1;
2927         }
2928 
2929         getOutPrintWriter().println("Telephony is running with the "
2930                 + (newDataStackEnabled ? "new" : "old") + " data stack.");
2931         return 0;
2932     }
2933 
handleRadioSetModemServiceCommand()2934     private int handleRadioSetModemServiceCommand() {
2935         PrintWriter errPw = getErrPrintWriter();
2936         String serviceName = null;
2937 
2938         String opt;
2939         while ((opt = getNextOption()) != null) {
2940             switch (opt) {
2941                 case "-s": {
2942                     serviceName = getNextArgRequired();
2943                     break;
2944                 }
2945             }
2946         }
2947 
2948         try {
2949             boolean result = mInterface.setModemService(serviceName);
2950             if (VDBG) {
2951                 Log.v(LOG_TAG,
2952                         "RadioSetModemService " + serviceName + ", result = " + result);
2953             }
2954             getOutPrintWriter().println(result);
2955         } catch (RemoteException e) {
2956             Log.w(LOG_TAG,
2957                     "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2958             errPw.println("Exception: " + e.getMessage());
2959             return -1;
2960         }
2961         return 0;
2962     }
2963 
handleRadioGetModemServiceCommand()2964     private int handleRadioGetModemServiceCommand() {
2965         PrintWriter errPw = getErrPrintWriter();
2966         String result;
2967 
2968         try {
2969             result = mInterface.getModemService();
2970             getOutPrintWriter().println(result);
2971         } catch (RemoteException e) {
2972             errPw.println("Exception: " + e.getMessage());
2973             return -1;
2974         }
2975         if (VDBG) {
2976             Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2977         }
2978         return 0;
2979     }
2980 
handleRadioCommand()2981     private int handleRadioCommand() {
2982         String arg = getNextArg();
2983         if (arg == null) {
2984             onHelpRadio();
2985             return 0;
2986         }
2987 
2988         switch (arg) {
2989             case RADIO_SET_MODEM_SERVICE:
2990                 return handleRadioSetModemServiceCommand();
2991 
2992             case RADIO_GET_MODEM_SERVICE:
2993                 return handleRadioGetModemServiceCommand();
2994         }
2995 
2996         return -1;
2997     }
2998 }
2999