blob: dbeb7ce1d39a642d2ecf361742f71e7b24bab641 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000031import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070032import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070033import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010034import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070035import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000037import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070038import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080039import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000040import android.telephony.ims.ImsException;
41import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080042import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080043import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000044import android.util.ArrayMap;
45import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070046import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070047import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
Brad Ebinger14d467f2021-02-12 06:18:28 +000049import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080051import com.android.internal.telephony.Phone;
52import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080053import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080054import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080055import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080056import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080057import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070058
59import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080060import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000061import java.util.Arrays;
62import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010063import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080064import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010065import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010067import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080068import java.util.UUID;
69import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070
71/**
72 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
73 * permission checks have been done before onCommand was called. Make sure any commands processed
74 * here also contain the appropriate permissions checks.
75 */
76
Hall Liua1548bd2019-12-24 14:14:12 -080077public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070078
79 private static final String LOG_TAG = "TelephonyShellCommand";
80 // Don't commit with this true.
81 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070082 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
Hall Liuaa4211e2021-01-20 15:43:39 -080084 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080086 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080087 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080088 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070089 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000090 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000091 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010092 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080093 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080094 private static final String ENABLE = "enable";
95 private static final String DISABLE = "disable";
96 private static final String QUERY = "query";
97
Hall Liu7135e502021-02-04 16:58:17 -080098 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800100 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800101
Brad Ebinger999d3302020-11-25 14:31:39 -0800102 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
103 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
104 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700105 // Used to disable or enable processing of conference event package data from the network.
106 // This is handy for testing scenarios where CEP data does not exist on a network which does
107 // support CEP data.
108 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700109
Hall Liud892bec2018-11-30 14:51:45 -0800110 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800111 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100113 private static final String CC_GET_VALUE = "get-value";
114 private static final String CC_SET_VALUE = "set-value";
115 private static final String CC_CLEAR_VALUES = "clear-values";
116
Hui Wang641e81c2020-10-12 12:14:23 -0700117 private static final String GBA_SUBCOMMAND = "gba";
118 private static final String GBA_SET_SERVICE = "set-service";
119 private static final String GBA_GET_SERVICE = "get-service";
120 private static final String GBA_SET_RELEASE_TIME = "set-release";
121 private static final String GBA_GET_RELEASE_TIME = "get-release";
122
Hui Wang761a6682020-10-31 05:12:53 +0000123 private static final String SINGLE_REGISTATION_CONFIG = "src";
124 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
125 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
126 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
127 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800128 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
129 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800130 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
131 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000132
Tyler Gunn92479152021-01-20 16:30:10 -0800133 private static final String D2D_SUBCOMMAND = "d2d";
134 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800135 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700136 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800137
Nazanin014f41e2021-05-06 17:26:31 -0700138 private static final String BARRING_SUBCOMMAND = "barring";
139 private static final String BARRING_SEND_INFO = "send";
140
James.cf Linbcdf8b32021-01-14 16:44:13 +0800141 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800142 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800143 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800144 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800145 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
146 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000147 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
148 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800149 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
150 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800151 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
152 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800153
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800154 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
155 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
156
Jordan Liu0ccee222021-04-27 11:55:13 -0700157 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
158 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
159
Jack Nudelman644b91a2021-03-12 14:09:48 -0800160 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
161 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
162 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
163
SongFerngWang98dd5992021-05-13 17:50:00 +0800164 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
165 "get-allowed-network-types-for-users";
166 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
167 "set-allowed-network-types-for-users";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700168 // Take advantage of existing methods that already contain permissions checks when possible.
169 private final ITelephony mInterface;
170
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100171 private SubscriptionManager mSubscriptionManager;
172 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700173 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700174 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100175
176 private enum CcType {
177 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
178 STRING_ARRAY, UNKNOWN
179 }
180
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100181 private class CcOptionParseResult {
182 public int mSubId;
183 public boolean mPersistent;
184 }
185
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100186 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
187 // keys by looking at the end of the string which usually tells the type.
188 // For instance: "xxxx_string", "xxxx_string_array", etc.
189 // The carrier config keys in this map does not follow this convention. It is therefore not
190 // possible to infer the type for these keys by looking at the string.
191 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
192 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
193 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
194 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
195 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
196 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
197 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
198 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
199 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
200 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
203 CcType.STRING);
204 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
205 CcType.STRING_ARRAY);
206 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
207 CcType.STRING_ARRAY);
208 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
209 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
210 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
211 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
212 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
213 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
214 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
215 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
216 }
217 };
218
Brad Ebinger14d467f2021-02-12 06:18:28 +0000219 /**
220 * Map from a shorthand string to the feature tags required in registration required in order
221 * for the RCS feature to be considered "capable".
222 */
223 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
224 static {
225 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
226 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
227 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
228 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
229 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
230 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
231 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
232 FeatureTags.FEATURE_TAG_VIDEO)));
233 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
234 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
235 map.put("call_comp",
236 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
237 map.put("call_comp_mmtel",
238 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
239 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
240 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
241 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
242 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
243 // version
244 map.put("chatbot", new ArraySet<>(Arrays.asList(
245 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
246 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
247 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
248 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
249 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
250 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
251 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
252 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
253 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
254 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
255 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
256 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
257 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
258 }
259
260
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100261 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700262 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100263 mCarrierConfigManager =
264 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
265 mSubscriptionManager = (SubscriptionManager)
266 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700267 mTelephonyRegistryManager = (TelephonyRegistryManager)
268 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700269 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700270 }
271
272 @Override
273 public int onCommand(String cmd) {
274 if (cmd == null) {
275 return handleDefaultCommands(null);
276 }
277
278 switch (cmd) {
279 case IMS_SUBCOMMAND: {
280 return handleImsCommand();
281 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800282 case RCS_UCE_COMMAND:
283 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800284 case NUMBER_VERIFICATION_SUBCOMMAND:
285 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800286 case EMERGENCY_CALLBACK_MODE:
287 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800288 case EMERGENCY_NUMBER_TEST_MODE:
289 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100290 case CARRIER_CONFIG_SUBCOMMAND: {
291 return handleCcCommand();
292 }
Shuo Qianf5125122019-12-16 17:03:07 -0800293 case DATA_TEST_MODE:
294 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700295 case END_BLOCK_SUPPRESSION:
296 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700297 case GBA_SUBCOMMAND:
298 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800299 case D2D_SUBCOMMAND:
300 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700301 case BARRING_SUBCOMMAND:
302 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000303 case SINGLE_REGISTATION_CONFIG:
304 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000305 case RESTART_MODEM:
306 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800307 case CALL_COMPOSER_SUBCOMMAND:
308 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000309 case UNATTENDED_REBOOT:
310 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800311 case HAS_CARRIER_PRIVILEGES_COMMAND:
312 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800313 case THERMAL_MITIGATION_COMMAND:
314 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700315 case DISABLE_PHYSICAL_SUBSCRIPTION:
316 return handleEnablePhysicalSubscription(false);
317 case ENABLE_PHYSICAL_SUBSCRIPTION:
318 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800319 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
320 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
321 return handleAllowedNetworkTypesCommand(cmd);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700322 default: {
323 return handleDefaultCommands(cmd);
324 }
325 }
326 }
327
328 @Override
329 public void onHelp() {
330 PrintWriter pw = getOutPrintWriter();
331 pw.println("Telephony Commands:");
332 pw.println(" help");
333 pw.println(" Print this help text.");
334 pw.println(" ims");
335 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800336 pw.println(" uce");
337 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800338 pw.println(" emergency-number-test-mode");
339 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700340 pw.println(" end-block-suppression");
341 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800342 pw.println(" data");
343 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100344 pw.println(" cc");
345 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700346 pw.println(" gba");
347 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000348 pw.println(" src");
349 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000350 pw.println(" restart-modem");
351 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000352 pw.println(" unattended-reboot");
353 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800354 pw.println(" has-carrier-privileges [package]");
355 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800356 pw.println(" get-allowed-network-types-for-users");
357 pw.println(" Get the Allowed Network Types.");
358 pw.println(" set-allowed-network-types-for-users");
359 pw.println(" Set the Allowed Network Types.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700360 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800361 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800362 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700363 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800364 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100365 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700366 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000367 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800368 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700369 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800370 onHelpAllowedNetworkTypes();
Tyler Gunn92479152021-01-20 16:30:10 -0800371 }
372
373 private void onHelpD2D() {
374 PrintWriter pw = getOutPrintWriter();
375 pw.println("D2D Comms Commands:");
376 pw.println(" d2d send TYPE VALUE");
377 pw.println(" Sends a D2D message of specified type and value.");
378 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
379 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
380 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
381 MESSAGE_CALL_AUDIO_CODEC));
382 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
383 + Communicator.messageToString(
384 MESSAGE_DEVICE_BATTERY_STATE));
385 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
386 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800387 pw.println(" d2d transport TYPE");
388 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
389 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700390 pw.println(" d2d set-device-support true/default");
391 pw.println(" true - forces device support to be enabled for D2D.");
392 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
393 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700394 }
395
Nazanin014f41e2021-05-06 17:26:31 -0700396 private void onHelpBarring() {
397 PrintWriter pw = getOutPrintWriter();
398 pw.println("Barring Commands:");
399 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
400 + " -t CONDITIONAL_BARRING_TIME_SECS");
401 pw.println(" Notifies of a barring info change for the specified slot id.");
402 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
403 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
404 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
405 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
406 }
407
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700408 private void onHelpIms() {
409 PrintWriter pw = getOutPrintWriter();
410 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800411 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700412 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
413 pw.println(" ImsService. Options are:");
414 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
415 pw.println(" is specified, it will choose the default voice SIM slot.");
416 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
417 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800418 pw.println(" -f: Set the feature that this override if for, if no option is");
419 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700420 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
421 pw.println(" Gets the package name of the currently defined ImsService.");
422 pw.println(" Options are:");
423 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
424 pw.println(" is specified, it will choose the default voice SIM slot.");
425 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000426 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800427 pw.println(" -f: The feature type that the query will be requested for. If none is");
428 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800429 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
430 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
431 pw.println(" configuration overrides. Options are:");
432 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
433 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700434 pw.println(" ims enable [-s SLOT_ID]");
435 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
436 pw.println(" if none is specified.");
437 pw.println(" ims disable [-s SLOT_ID]");
438 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
439 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700440 pw.println(" ims conference-event-package [enable/disable]");
441 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700442 }
443
James.cf Linbcdf8b32021-01-14 16:44:13 +0800444 private void onHelpUce() {
445 PrintWriter pw = getOutPrintWriter();
446 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800447 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
448 pw.println(" Get the EAB contacts from the EAB database.");
449 pw.println(" Options are:");
450 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
451 pw.println(" Expected output format :");
452 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800453 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
454 pw.println(" Remove the EAB contacts from the EAB database.");
455 pw.println(" Options are:");
456 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
457 pw.println(" is specified, it will choose the default voice SIM slot.");
458 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800459 pw.println(" uce get-device-enabled");
460 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
461 pw.println(" uce set-device-enabled true|false");
462 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
463 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000464 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
465 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
466 pw.println(" Options are:");
467 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
468 pw.println(" is specified, it will choose the default voice SIM slot.");
469 pw.println(" add [CAPABILITY]: add a new capability");
470 pw.println(" remove [CAPABILITY]: remove a capability");
471 pw.println(" clear: clear all capability overrides");
472 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
473 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
474 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
475 pw.println(" chatbot_sa, chatbot_role] as well as full length");
476 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
477 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
478 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
479 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800480 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
481 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800482 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
483 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800484 }
485
Hall Liud892bec2018-11-30 14:51:45 -0800486 private void onHelpNumberVerification() {
487 PrintWriter pw = getOutPrintWriter();
488 pw.println("Number verification commands");
489 pw.println(" numverify override-package PACKAGE_NAME;");
490 pw.println(" Set the authorized package for number verification.");
491 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800492 pw.println(" numverify fake-call NUMBER;");
493 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
494 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800495 }
496
Jack Nudelman644b91a2021-03-12 14:09:48 -0800497 private void onHelpThermalMitigation() {
498 PrintWriter pw = getOutPrintWriter();
499 pw.println("Thermal mitigation commands");
500 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
501 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
502 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
503 pw.println(" Remove the package from one of the authorized packages for thermal "
504 + "mitigation.");
505 }
506
Jordan Liu0ccee222021-04-27 11:55:13 -0700507 private void onHelpDisableOrEnablePhysicalSubscription() {
508 PrintWriter pw = getOutPrintWriter();
509 pw.println("Disable or enable a physical subscription");
510 pw.println(" disable-physical-subscription SUB_ID");
511 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
512 pw.println(" enable-physical-subscription SUB_ID");
513 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
514 }
515
Shuo Qianf5125122019-12-16 17:03:07 -0800516 private void onHelpDataTestMode() {
517 PrintWriter pw = getOutPrintWriter();
518 pw.println("Mobile Data Test Mode Commands:");
519 pw.println(" data enable: enable mobile data connectivity");
520 pw.println(" data disable: disable mobile data connectivity");
521 }
522
sqian9d4df8b2019-01-15 18:32:07 -0800523 private void onHelpEmergencyNumber() {
524 PrintWriter pw = getOutPrintWriter();
525 pw.println("Emergency Number Test Mode Commands:");
526 pw.println(" emergency-number-test-mode ");
527 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
528 + " the test mode");
529 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700530 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800531 pw.println(" -c: clear the emergency number list in the test mode.");
532 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700533 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800534 pw.println(" -p: get the full emergency number list in the test mode.");
535 }
536
Shuo Qian489d9282020-07-09 11:30:03 -0700537 private void onHelpEndBlockSupperssion() {
538 PrintWriter pw = getOutPrintWriter();
539 pw.println("End Block Suppression command:");
540 pw.println(" end-block-suppression: disable suppressing blocking by contact");
541 pw.println(" with emergency services.");
542 }
543
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100544 private void onHelpCc() {
545 PrintWriter pw = getOutPrintWriter();
546 pw.println("Carrier Config Commands:");
547 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
548 pw.println(" Print carrier config values.");
549 pw.println(" Options are:");
550 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
551 pw.println(" is specified, it will choose the default voice SIM slot.");
552 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
553 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100554 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100555 pw.println(" Set carrier config KEY to NEW_VALUE.");
556 pw.println(" Options are:");
557 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
558 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100559 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100560 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
561 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
562 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
563 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
564 pw.println(" cc clear-values [-s SLOT_ID]");
565 pw.println(" Clear all carrier override values that has previously been set");
566 pw.println(" with set-value");
567 pw.println(" Options are:");
568 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
569 pw.println(" is specified, it will choose the default voice SIM slot.");
570 }
571
Hui Wang641e81c2020-10-12 12:14:23 -0700572 private void onHelpGba() {
573 PrintWriter pw = getOutPrintWriter();
574 pw.println("Gba Commands:");
575 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
576 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
577 pw.println(" Options are:");
578 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
579 pw.println(" is specified, it will choose the default voice SIM slot.");
580 pw.println(" gba get-service [-s SLOT_ID]");
581 pw.println(" Gets the package name of the currently defined GbaService.");
582 pw.println(" Options are:");
583 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
584 pw.println(" is specified, it will choose the default voice SIM slot.");
585 pw.println(" gba set-release [-s SLOT_ID] n");
586 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
587 pw.println(" Do not release/unbind if n is -1.");
588 pw.println(" Options are:");
589 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
590 pw.println(" is specified, it will choose the default voice SIM slot.");
591 pw.println(" gba get-release [-s SLOT_ID]");
592 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
593 pw.println(" Options are:");
594 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
595 pw.println(" is specified, it will choose the default voice SIM slot.");
596 }
597
Hui Wang761a6682020-10-31 05:12:53 +0000598 private void onHelpSrc() {
599 PrintWriter pw = getOutPrintWriter();
600 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800601 pw.println(" src set-test-enabled true|false");
602 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
603 pw.println(" The value could be true, false, or null(undefined).");
604 pw.println(" src get-test-enabled");
605 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000606 pw.println(" src set-device-enabled true|false|null");
607 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
608 pw.println(" The value could be true, false, or null(undefined).");
609 pw.println(" src get-device-enabled");
610 pw.println(" Gets the device config for RCS VoLTE single registration.");
611 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
612 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
613 pw.println(" The value could be true, false, or null(undefined).");
614 pw.println(" Options are:");
615 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
616 pw.println(" is specified, it will choose the default voice SIM slot.");
617 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
618 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
619 pw.println(" Options are:");
620 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
621 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800622 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
623 pw.println(" Sets ims feature validation result.");
624 pw.println(" The value could be true, false, or null(undefined).");
625 pw.println(" Options are:");
626 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
627 pw.println(" is specified, it will choose the default voice SIM slot.");
628 pw.println(" src get-feature-validation [-s SLOT_ID]");
629 pw.println(" Gets ims feature validation override value.");
630 pw.println(" Options are:");
631 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
632 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000633 }
634
SongFerngWang98dd5992021-05-13 17:50:00 +0800635 private void onHelpAllowedNetworkTypes() {
636 PrintWriter pw = getOutPrintWriter();
637 pw.println("Allowed Network Types Commands:");
638 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
639 pw.println(" Print allowed network types value.");
640 pw.println(" Options are:");
641 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
642 pw.println(" option is specified, it will choose the default voice SIM slot.");
643 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
644 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
645 pw.println(" Options are:");
646 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
647 pw.println(" option is specified, it will choose the default voice SIM slot.");
648 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
649 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
650 pw.println(" at TelephonyManager.java");
651 pw.println(" For example:");
652 pw.println(" NR only : 10000000000000000000");
653 pw.println(" NR|LTE : 11000001000000000000");
654 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
655 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
656 pw.println(" LTE only : 01000001000000000000");
657 }
658
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700659 private int handleImsCommand() {
660 String arg = getNextArg();
661 if (arg == null) {
662 onHelpIms();
663 return 0;
664 }
665
666 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800667 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700668 return handleImsSetServiceCommand();
669 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800670 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700671 return handleImsGetServiceCommand();
672 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800673 case IMS_CLEAR_SERVICE_OVERRIDE: {
674 return handleImsClearCarrierServiceCommand();
675 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800676 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700677 return handleEnableIms();
678 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800679 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700680 return handleDisableIms();
681 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700682 case IMS_CEP: {
683 return handleCepChange();
684 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700685 }
686
687 return -1;
688 }
689
Shuo Qianf5125122019-12-16 17:03:07 -0800690 private int handleDataTestModeCommand() {
691 PrintWriter errPw = getErrPrintWriter();
692 String arg = getNextArgRequired();
693 if (arg == null) {
694 onHelpDataTestMode();
695 return 0;
696 }
697 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800698 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800699 try {
700 mInterface.enableDataConnectivity();
701 } catch (RemoteException ex) {
702 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
703 errPw.println("Exception: " + ex.getMessage());
704 return -1;
705 }
706 break;
707 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800708 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800709 try {
710 mInterface.disableDataConnectivity();
711 } catch (RemoteException ex) {
712 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
713 errPw.println("Exception: " + ex.getMessage());
714 return -1;
715 }
716 break;
717 }
718 default:
719 onHelpDataTestMode();
720 break;
721 }
722 return 0;
723 }
724
Shuo Qianccbaf742021-02-22 18:32:21 -0800725 private int handleEmergencyCallbackModeCommand() {
726 PrintWriter errPw = getErrPrintWriter();
727 try {
728 mInterface.startEmergencyCallbackMode();
729 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
730 } catch (RemoteException ex) {
731 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
732 errPw.println("Exception: " + ex.getMessage());
733 return -1;
734 }
735 return 0;
736 }
737
sqian9d4df8b2019-01-15 18:32:07 -0800738 private int handleEmergencyNumberTestModeCommand() {
739 PrintWriter errPw = getErrPrintWriter();
740 String opt = getNextOption();
741 if (opt == null) {
742 onHelpEmergencyNumber();
743 return 0;
744 }
745
746 switch (opt) {
747 case "-a": {
748 String emergencyNumberCmd = getNextArgRequired();
749 if (emergencyNumberCmd == null
750 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700751 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800752 + " to be specified after -a in the command ");
753 return -1;
754 }
755 try {
756 mInterface.updateEmergencyNumberListTestMode(
757 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
758 new EmergencyNumber(emergencyNumberCmd, "", "",
759 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
760 new ArrayList<String>(),
761 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
762 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
763 } catch (RemoteException ex) {
764 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
765 + ", error " + ex.getMessage());
766 errPw.println("Exception: " + ex.getMessage());
767 return -1;
768 }
769 break;
770 }
771 case "-c": {
772 try {
773 mInterface.updateEmergencyNumberListTestMode(
774 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
775 } catch (RemoteException ex) {
776 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
777 errPw.println("Exception: " + ex.getMessage());
778 return -1;
779 }
780 break;
781 }
782 case "-r": {
783 String emergencyNumberCmd = getNextArgRequired();
784 if (emergencyNumberCmd == null
785 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700786 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800787 + " to be specified after -r in the command ");
788 return -1;
789 }
790 try {
791 mInterface.updateEmergencyNumberListTestMode(
792 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
793 new EmergencyNumber(emergencyNumberCmd, "", "",
794 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
795 new ArrayList<String>(),
796 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
797 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
798 } catch (RemoteException ex) {
799 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
800 + ", error " + ex.getMessage());
801 errPw.println("Exception: " + ex.getMessage());
802 return -1;
803 }
804 break;
805 }
806 case "-p": {
807 try {
808 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
809 } catch (RemoteException ex) {
810 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
811 errPw.println("Exception: " + ex.getMessage());
812 return -1;
813 }
814 break;
815 }
816 default:
817 onHelpEmergencyNumber();
818 break;
819 }
820 return 0;
821 }
822
Hall Liud892bec2018-11-30 14:51:45 -0800823 private int handleNumberVerificationCommand() {
824 String arg = getNextArg();
825 if (arg == null) {
826 onHelpNumberVerification();
827 return 0;
828 }
829
Hall Liuca5af3a2018-12-04 16:58:23 -0800830 if (!checkShellUid()) {
831 return -1;
832 }
833
Hall Liud892bec2018-11-30 14:51:45 -0800834 switch (arg) {
835 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800836 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
837 return 0;
838 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800839 case NUMBER_VERIFICATION_FAKE_CALL: {
840 boolean val = NumberVerificationManager.getInstance()
841 .checkIncomingCall(getNextArg());
842 getOutPrintWriter().println(val ? "1" : "0");
843 return 0;
844 }
Hall Liud892bec2018-11-30 14:51:45 -0800845 }
846
847 return -1;
848 }
849
Jordan Liu0ccee222021-04-27 11:55:13 -0700850 private boolean subIsEsim(int subId) {
851 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
852 if (info != null) {
853 return info.isEmbedded();
854 }
855 return false;
856 }
857
858 private int handleEnablePhysicalSubscription(boolean enable) {
859 PrintWriter errPw = getErrPrintWriter();
860 int subId = 0;
861 try {
862 subId = Integer.parseInt(getNextArgRequired());
863 } catch (NumberFormatException e) {
864 errPw.println((enable ? "enable" : "disable")
865 + "-physical-subscription requires an integer as a subId.");
866 return -1;
867 }
868 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
869 // non user build.
870 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
871 errPw.println("cc: Permission denied.");
872 return -1;
873 }
874 // Verify that the subId represents a physical sub
875 if (subIsEsim(subId)) {
876 errPw.println("SubId " + subId + " is not for a physical subscription");
877 return -1;
878 }
879 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
880 + " physical subscription with subId=" + subId);
881 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
882 return 0;
883 }
884
Jack Nudelman644b91a2021-03-12 14:09:48 -0800885 private int handleThermalMitigationCommand() {
886 String arg = getNextArg();
887 String packageName = getNextArg();
888 if (arg == null || packageName == null) {
889 onHelpThermalMitigation();
890 return 0;
891 }
892
893 if (!checkShellUid()) {
894 return -1;
895 }
896
897 switch (arg) {
898 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
899 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
900 return 0;
901 }
902 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
903 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
904 mContext);
905 return 0;
906 }
907 default:
908 onHelpThermalMitigation();
909 }
910
911 return -1;
912
913 }
914
Tyler Gunn92479152021-01-20 16:30:10 -0800915 private int handleD2dCommand() {
916 String arg = getNextArg();
917 if (arg == null) {
918 onHelpD2D();
919 return 0;
920 }
921
922 switch (arg) {
923 case D2D_SEND: {
924 return handleD2dSendCommand();
925 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800926 case D2D_TRANSPORT: {
927 return handleD2dTransportCommand();
928 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700929 case D2D_SET_DEVICE_SUPPORT: {
930 return handleD2dDeviceSupportedCommand();
931 }
Tyler Gunn92479152021-01-20 16:30:10 -0800932 }
933
934 return -1;
935 }
936
937 private int handleD2dSendCommand() {
938 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800939 int messageType = -1;
940 int messageValue = -1;
941
Tyler Gunn92479152021-01-20 16:30:10 -0800942 String arg = getNextArg();
943 if (arg == null) {
944 onHelpD2D();
945 return 0;
946 }
947 try {
948 messageType = Integer.parseInt(arg);
949 } catch (NumberFormatException e) {
950 errPw.println("message type must be a valid integer");
951 return -1;
952 }
953
954 arg = getNextArg();
955 if (arg == null) {
956 onHelpD2D();
957 return 0;
958 }
959 try {
960 messageValue = Integer.parseInt(arg);
961 } catch (NumberFormatException e) {
962 errPw.println("message value must be a valid integer");
963 return -1;
964 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800965
Tyler Gunn92479152021-01-20 16:30:10 -0800966 try {
967 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
968 } catch (RemoteException e) {
969 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
970 errPw.println("Exception: " + e.getMessage());
971 return -1;
972 }
973
974 return 0;
975 }
976
Tyler Gunnbabbda02021-02-10 11:05:02 -0800977 private int handleD2dTransportCommand() {
978 PrintWriter errPw = getErrPrintWriter();
979
980 String arg = getNextArg();
981 if (arg == null) {
982 onHelpD2D();
983 return 0;
984 }
985
986 try {
987 mInterface.setActiveDeviceToDeviceTransport(arg);
988 } catch (RemoteException e) {
989 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
990 errPw.println("Exception: " + e.getMessage());
991 return -1;
992 }
993 return 0;
994 }
Nazanin014f41e2021-05-06 17:26:31 -0700995 private int handleBarringCommand() {
996 String arg = getNextArg();
997 if (arg == null) {
998 onHelpBarring();
999 return 0;
1000 }
1001
1002 switch (arg) {
1003 case BARRING_SEND_INFO: {
1004 return handleBarringSendCommand();
1005 }
1006 }
1007 return -1;
1008 }
1009
1010 private int handleBarringSendCommand() {
1011 PrintWriter errPw = getErrPrintWriter();
1012 int slotId = getDefaultSlot();
1013 int subId = SubscriptionManager.getSubId(slotId)[0];
1014 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1015 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1016 boolean isConditionallyBarred = false;
1017 int conditionalBarringTimeSeconds = 0;
1018
1019 String opt;
1020 while ((opt = getNextOption()) != null) {
1021 switch (opt) {
1022 case "-s": {
1023 try {
1024 slotId = Integer.parseInt(getNextArgRequired());
1025 subId = SubscriptionManager.getSubId(slotId)[0];
1026 } catch (NumberFormatException e) {
1027 errPw.println("barring send requires an integer as a SLOT_ID.");
1028 return -1;
1029 }
1030 break;
1031 }
1032 case "-b": {
1033 try {
1034 barringType = Integer.parseInt(getNextArgRequired());
1035 if (barringType < -1 || barringType > 2) {
1036 throw new NumberFormatException();
1037 }
1038
1039 } catch (NumberFormatException e) {
1040 errPw.println("barring send requires an integer in range [-1,2] as "
1041 + "a BARRING_TYPE.");
1042 return -1;
1043 }
1044 break;
1045 }
1046 case "-c": {
1047 try {
1048 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1049 } catch (Exception e) {
1050 errPw.println("barring send requires a boolean after -c indicating"
1051 + " conditional barring");
1052 return -1;
1053 }
1054 break;
1055 }
1056 case "-t": {
1057 try {
1058 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1059 } catch (NumberFormatException e) {
1060 errPw.println("barring send requires an integer for time of barring"
1061 + " in seconds after -t for conditional barring");
1062 return -1;
1063 }
1064 break;
1065 }
1066 }
1067 }
1068 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1069 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1070 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1071 barringServiceInfos.append(0, bsi);
1072 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1073 try {
1074 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1075 } catch (Exception e) {
1076 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1077 errPw.println("Exception: " + e.getMessage());
1078 return -1;
1079 }
1080 return 0;
1081 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001082
Tyler Gunnd4575212021-05-03 14:46:49 -07001083 private int handleD2dDeviceSupportedCommand() {
1084 PrintWriter errPw = getErrPrintWriter();
1085
1086 String arg = getNextArg();
1087 if (arg == null) {
1088 onHelpD2D();
1089 return 0;
1090 }
1091
1092 boolean isEnabled = "true".equals(arg.toLowerCase());
1093 try {
1094 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1095 } catch (RemoteException e) {
1096 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1097 errPw.println("Exception: " + e.getMessage());
1098 return -1;
1099 }
1100 return 0;
1101 }
1102
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001103 // ims set-ims-service
1104 private int handleImsSetServiceCommand() {
1105 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001106 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001107 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001108 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001109
1110 String opt;
1111 while ((opt = getNextOption()) != null) {
1112 switch (opt) {
1113 case "-s": {
1114 try {
1115 slotId = Integer.parseInt(getNextArgRequired());
1116 } catch (NumberFormatException e) {
1117 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1118 return -1;
1119 }
1120 break;
1121 }
1122 case "-c": {
1123 isCarrierService = true;
1124 break;
1125 }
1126 case "-d": {
1127 isCarrierService = false;
1128 break;
1129 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001130 case "-f": {
1131 String featureString = getNextArgRequired();
1132 String[] features = featureString.split(",");
1133 for (int i = 0; i < features.length; i++) {
1134 try {
1135 Integer result = Integer.parseInt(features[i]);
1136 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1137 || result >= ImsFeature.FEATURE_MAX) {
1138 errPw.println("ims set-ims-service -f " + result
1139 + " is an invalid feature.");
1140 return -1;
1141 }
1142 featuresList.add(result);
1143 } catch (NumberFormatException e) {
1144 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1145 + " as an integer.");
1146 return -1;
1147 }
1148 }
1149 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001150 }
1151 }
1152 // Mandatory param, either -c or -d
1153 if (isCarrierService == null) {
1154 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1155 return -1;
1156 }
1157
1158 String packageName = getNextArg();
1159
1160 try {
1161 if (packageName == null) {
1162 packageName = "";
1163 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001164 int[] featureArray = new int[featuresList.size()];
1165 for (int i = 0; i < featuresList.size(); i++) {
1166 featureArray[i] = featuresList.get(i);
1167 }
1168 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1169 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001170 if (VDBG) {
1171 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001172 + (isCarrierService ? "-c " : "-d ")
1173 + "-f " + featuresList + " "
1174 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001175 }
1176 getOutPrintWriter().println(result);
1177 } catch (RemoteException e) {
1178 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001179 + (isCarrierService ? "-c " : "-d ")
1180 + "-f " + featuresList + " "
1181 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001182 errPw.println("Exception: " + e.getMessage());
1183 return -1;
1184 }
1185 return 0;
1186 }
1187
Brad Ebinger999d3302020-11-25 14:31:39 -08001188 // ims clear-ims-service-override
1189 private int handleImsClearCarrierServiceCommand() {
1190 PrintWriter errPw = getErrPrintWriter();
1191 int slotId = getDefaultSlot();
1192
1193 String opt;
1194 while ((opt = getNextOption()) != null) {
1195 switch (opt) {
1196 case "-s": {
1197 try {
1198 slotId = Integer.parseInt(getNextArgRequired());
1199 } catch (NumberFormatException e) {
1200 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1201 return -1;
1202 }
1203 break;
1204 }
1205 }
1206 }
1207
1208 try {
1209 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1210 if (VDBG) {
1211 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1212 + ", result=" + result);
1213 }
1214 getOutPrintWriter().println(result);
1215 } catch (RemoteException e) {
1216 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1217 + ", error" + e.getMessage());
1218 errPw.println("Exception: " + e.getMessage());
1219 return -1;
1220 }
1221 return 0;
1222 }
1223
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001224 // ims get-ims-service
1225 private int handleImsGetServiceCommand() {
1226 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001227 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001228 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001229 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001230
1231 String opt;
1232 while ((opt = getNextOption()) != null) {
1233 switch (opt) {
1234 case "-s": {
1235 try {
1236 slotId = Integer.parseInt(getNextArgRequired());
1237 } catch (NumberFormatException e) {
1238 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1239 return -1;
1240 }
1241 break;
1242 }
1243 case "-c": {
1244 isCarrierService = true;
1245 break;
1246 }
1247 case "-d": {
1248 isCarrierService = false;
1249 break;
1250 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001251 case "-f": {
1252 try {
1253 featureType = Integer.parseInt(getNextArg());
1254 } catch (NumberFormatException e) {
1255 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1256 return -1;
1257 }
1258 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1259 || featureType >= ImsFeature.FEATURE_MAX) {
1260 errPw.println("ims get-ims-service -f invalid feature.");
1261 return -1;
1262 }
1263 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001264 }
1265 }
1266 // Mandatory param, either -c or -d
1267 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001268 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001269 return -1;
1270 }
1271
1272 String result;
1273 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001274 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001275 } catch (RemoteException e) {
1276 return -1;
1277 }
1278 if (VDBG) {
1279 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001280 + (isCarrierService ? "-c " : "-d ")
1281 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1282 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001283 }
1284 getOutPrintWriter().println(result);
1285 return 0;
1286 }
1287
1288 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001289 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001290 String opt;
1291 while ((opt = getNextOption()) != null) {
1292 switch (opt) {
1293 case "-s": {
1294 try {
1295 slotId = Integer.parseInt(getNextArgRequired());
1296 } catch (NumberFormatException e) {
1297 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1298 return -1;
1299 }
1300 break;
1301 }
1302 }
1303 }
1304 try {
1305 mInterface.enableIms(slotId);
1306 } catch (RemoteException e) {
1307 return -1;
1308 }
1309 if (VDBG) {
1310 Log.v(LOG_TAG, "ims enable -s " + slotId);
1311 }
1312 return 0;
1313 }
1314
1315 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001316 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001317 String opt;
1318 while ((opt = getNextOption()) != null) {
1319 switch (opt) {
1320 case "-s": {
1321 try {
1322 slotId = Integer.parseInt(getNextArgRequired());
1323 } catch (NumberFormatException e) {
1324 getErrPrintWriter().println(
1325 "ims disable requires an integer as a SLOT_ID.");
1326 return -1;
1327 }
1328 break;
1329 }
1330 }
1331 }
1332 try {
1333 mInterface.disableIms(slotId);
1334 } catch (RemoteException e) {
1335 return -1;
1336 }
1337 if (VDBG) {
1338 Log.v(LOG_TAG, "ims disable -s " + slotId);
1339 }
1340 return 0;
1341 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001342
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001343 private int handleCepChange() {
1344 Log.i(LOG_TAG, "handleCepChange");
1345 String opt = getNextArg();
1346 if (opt == null) {
1347 return -1;
1348 }
1349 boolean isCepEnabled = opt.equals("enable");
1350
1351 try {
1352 mInterface.setCepEnabled(isCepEnabled);
1353 } catch (RemoteException e) {
1354 return -1;
1355 }
1356 return 0;
1357 }
1358
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001359 private int getDefaultSlot() {
1360 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1361 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1362 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1363 // If there is no default, default to slot 0.
1364 slotId = DEFAULT_PHONE_ID;
1365 }
1366 return slotId;
1367 }
sqian2fff4a32018-11-05 14:18:37 -08001368
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001369 // Parse options related to Carrier Config Commands.
1370 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001371 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001372 CcOptionParseResult result = new CcOptionParseResult();
1373 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1374 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001375
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001376 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001377 while ((opt = getNextOption()) != null) {
1378 switch (opt) {
1379 case "-s": {
1380 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001381 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1382 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1383 errPw.println(tag + "No valid subscription found.");
1384 return null;
1385 }
1386
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001387 } catch (IllegalArgumentException e) {
1388 // Missing slot id
1389 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001390 return null;
1391 }
1392 break;
1393 }
1394 case "-p": {
1395 if (allowOptionPersistent) {
1396 result.mPersistent = true;
1397 } else {
1398 errPw.println(tag + "Unexpected option " + opt);
1399 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001400 }
1401 break;
1402 }
1403 default: {
1404 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001405 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001406 }
1407 }
1408 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001409 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001410 }
1411
1412 private int slotStringToSubId(String tag, String slotString) {
1413 int slotId = -1;
1414 try {
1415 slotId = Integer.parseInt(slotString);
1416 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001417 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1418 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1419 }
1420
1421 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001422 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1423 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1424 }
1425
Qiong Liuf25799b2020-09-10 10:13:46 +08001426 Phone phone = PhoneFactory.getPhone(slotId);
1427 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001428 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1429 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1430 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001431 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001432 }
1433
Hall Liud892bec2018-11-30 14:51:45 -08001434 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001435 // adb can run as root or as shell, depending on whether the device is rooted.
1436 return Binder.getCallingUid() == Process.SHELL_UID
1437 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001438 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001439
1440 private int handleCcCommand() {
1441 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1442 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001443 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001444 getErrPrintWriter().println("cc: Permission denied.");
1445 return -1;
1446 }
1447
1448 String arg = getNextArg();
1449 if (arg == null) {
1450 onHelpCc();
1451 return 0;
1452 }
1453
1454 switch (arg) {
1455 case CC_GET_VALUE: {
1456 return handleCcGetValue();
1457 }
1458 case CC_SET_VALUE: {
1459 return handleCcSetValue();
1460 }
1461 case CC_CLEAR_VALUES: {
1462 return handleCcClearValues();
1463 }
1464 default: {
1465 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1466 }
1467 }
1468 return -1;
1469 }
1470
1471 // cc get-value
1472 private int handleCcGetValue() {
1473 PrintWriter errPw = getErrPrintWriter();
1474 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1475 String key = null;
1476
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001477 // Parse all options
1478 CcOptionParseResult options = parseCcOptions(tag, false);
1479 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001480 return -1;
1481 }
1482
1483 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001484 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001485 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001486 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001487 return -1;
1488 }
1489
1490 // Get the key.
1491 key = getNextArg();
1492 if (key != null) {
1493 // A key was provided. Verify if it is a valid key
1494 if (!bundle.containsKey(key)) {
1495 errPw.println(tag + key + " is not a valid key.");
1496 return -1;
1497 }
1498
1499 // Print the carrier config value for key.
1500 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1501 } else {
1502 // No key provided. Show all values.
1503 // Iterate over a sorted list of all carrier config keys and print them.
1504 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1505 for (String k : sortedSet) {
1506 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1507 }
1508 }
1509 return 0;
1510 }
1511
1512 // cc set-value
1513 private int handleCcSetValue() {
1514 PrintWriter errPw = getErrPrintWriter();
1515 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1516
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001517 // Parse all options
1518 CcOptionParseResult options = parseCcOptions(tag, true);
1519 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001520 return -1;
1521 }
1522
1523 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001524 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001525 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001526 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001527 return -1;
1528 }
1529
1530 // Get the key.
1531 String key = getNextArg();
1532 if (key == null || key.equals("")) {
1533 errPw.println(tag + "KEY is missing");
1534 return -1;
1535 }
1536
1537 // Verify if the key is valid
1538 if (!originalValues.containsKey(key)) {
1539 errPw.println(tag + key + " is not a valid key.");
1540 return -1;
1541 }
1542
1543 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1544 ArrayList<String> valueList = new ArrayList<String>();
1545 while (peekNextArg() != null) {
1546 valueList.add(getNextArg());
1547 }
1548
1549 // Find the type of the carrier config value
1550 CcType type = getType(tag, key, originalValues);
1551 if (type == CcType.UNKNOWN) {
1552 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1553 return -1;
1554 }
1555
1556 // Create an override bundle containing the key and value that should be overriden.
1557 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1558 if (overrideBundle == null) {
1559 return -1;
1560 }
1561
1562 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001563 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001564
1565 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001566 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001567 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001568 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001569 return -1;
1570 }
1571
1572 // Print the original and new value.
1573 String originalValueString = ccValueToString(key, type, originalValues);
1574 String newValueString = ccValueToString(key, type, newValues);
1575 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1576 getOutPrintWriter().println("New value: \n" + newValueString);
1577
1578 return 0;
1579 }
1580
1581 // cc clear-values
1582 private int handleCcClearValues() {
1583 PrintWriter errPw = getErrPrintWriter();
1584 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1585
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001586 // Parse all options
1587 CcOptionParseResult options = parseCcOptions(tag, false);
1588 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001589 return -1;
1590 }
1591
1592 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001593 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001594 getOutPrintWriter()
1595 .println("All previously set carrier config override values has been cleared");
1596 return 0;
1597 }
1598
1599 private CcType getType(String tag, String key, PersistableBundle bundle) {
1600 // Find the type by checking the type of the current value stored in the bundle.
1601 Object value = bundle.get(key);
1602
1603 if (CC_TYPE_MAP.containsKey(key)) {
1604 return CC_TYPE_MAP.get(key);
1605 } else if (value != null) {
1606 if (value instanceof Boolean) {
1607 return CcType.BOOLEAN;
1608 } else if (value instanceof Double) {
1609 return CcType.DOUBLE;
1610 } else if (value instanceof double[]) {
1611 return CcType.DOUBLE_ARRAY;
1612 } else if (value instanceof Integer) {
1613 return CcType.INT;
1614 } else if (value instanceof int[]) {
1615 return CcType.INT_ARRAY;
1616 } else if (value instanceof Long) {
1617 return CcType.LONG;
1618 } else if (value instanceof long[]) {
1619 return CcType.LONG_ARRAY;
1620 } else if (value instanceof String) {
1621 return CcType.STRING;
1622 } else if (value instanceof String[]) {
1623 return CcType.STRING_ARRAY;
1624 }
1625 } else {
1626 // Current value was null and can therefore not be used in order to find the type.
1627 // Check the name of the key to infer the type. This check is not needed for primitive
1628 // data types (boolean, double, int and long), since they can not be null.
1629 if (key.endsWith("double_array")) {
1630 return CcType.DOUBLE_ARRAY;
1631 }
1632 if (key.endsWith("int_array")) {
1633 return CcType.INT_ARRAY;
1634 }
1635 if (key.endsWith("long_array")) {
1636 return CcType.LONG_ARRAY;
1637 }
1638 if (key.endsWith("string")) {
1639 return CcType.STRING;
1640 }
1641 if (key.endsWith("string_array") || key.endsWith("strings")) {
1642 return CcType.STRING_ARRAY;
1643 }
1644 }
1645
1646 // Not possible to infer the type by looking at the current value or the key.
1647 PrintWriter errPw = getErrPrintWriter();
1648 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1649 return CcType.UNKNOWN;
1650 }
1651
1652 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1653 String result;
1654 StringBuilder valueString = new StringBuilder();
1655 String typeString = type.toString();
1656 Object value = bundle.get(key);
1657
1658 if (value == null) {
1659 valueString.append("null");
1660 } else {
1661 switch (type) {
1662 case DOUBLE_ARRAY: {
1663 // Format the string representation of the int array as value1 value2......
1664 double[] valueArray = (double[]) value;
1665 for (int i = 0; i < valueArray.length; i++) {
1666 if (i != 0) {
1667 valueString.append(" ");
1668 }
1669 valueString.append(valueArray[i]);
1670 }
1671 break;
1672 }
1673 case INT_ARRAY: {
1674 // Format the string representation of the int array as value1 value2......
1675 int[] valueArray = (int[]) value;
1676 for (int i = 0; i < valueArray.length; i++) {
1677 if (i != 0) {
1678 valueString.append(" ");
1679 }
1680 valueString.append(valueArray[i]);
1681 }
1682 break;
1683 }
1684 case LONG_ARRAY: {
1685 // Format the string representation of the int array as value1 value2......
1686 long[] valueArray = (long[]) value;
1687 for (int i = 0; i < valueArray.length; i++) {
1688 if (i != 0) {
1689 valueString.append(" ");
1690 }
1691 valueString.append(valueArray[i]);
1692 }
1693 break;
1694 }
1695 case STRING: {
1696 valueString.append("\"" + value.toString() + "\"");
1697 break;
1698 }
1699 case STRING_ARRAY: {
1700 // Format the string representation of the string array as "value1" "value2"....
1701 String[] valueArray = (String[]) value;
1702 for (int i = 0; i < valueArray.length; i++) {
1703 if (i != 0) {
1704 valueString.append(" ");
1705 }
1706 if (valueArray[i] != null) {
1707 valueString.append("\"" + valueArray[i] + "\"");
1708 } else {
1709 valueString.append("null");
1710 }
1711 }
1712 break;
1713 }
1714 default: {
1715 valueString.append(value.toString());
1716 }
1717 }
1718 }
1719 return String.format("%-70s %-15s %s", key, typeString, valueString);
1720 }
1721
1722 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1723 ArrayList<String> valueList) {
1724 PrintWriter errPw = getErrPrintWriter();
1725 PersistableBundle bundle = new PersistableBundle();
1726
1727 // First verify that a valid number of values has been provided for the type.
1728 switch (type) {
1729 case BOOLEAN:
1730 case DOUBLE:
1731 case INT:
1732 case LONG: {
1733 if (valueList.size() != 1) {
1734 errPw.println(tag + "Expected 1 value for type " + type
1735 + ". Found: " + valueList.size());
1736 return null;
1737 }
1738 break;
1739 }
1740 case STRING: {
1741 if (valueList.size() > 1) {
1742 errPw.println(tag + "Expected 0 or 1 values for type " + type
1743 + ". Found: " + valueList.size());
1744 return null;
1745 }
1746 break;
1747 }
1748 }
1749
1750 // Parse the value according to type and add it to the Bundle.
1751 switch (type) {
1752 case BOOLEAN: {
1753 if ("true".equalsIgnoreCase(valueList.get(0))) {
1754 bundle.putBoolean(key, true);
1755 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1756 bundle.putBoolean(key, false);
1757 } else {
1758 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1759 return null;
1760 }
1761 break;
1762 }
1763 case DOUBLE: {
1764 try {
1765 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1766 } catch (NumberFormatException nfe) {
1767 // Not a valid double
1768 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1769 return null;
1770 }
1771 break;
1772 }
1773 case DOUBLE_ARRAY: {
1774 double[] valueDoubleArray = null;
1775 if (valueList.size() > 0) {
1776 valueDoubleArray = new double[valueList.size()];
1777 for (int i = 0; i < valueList.size(); i++) {
1778 try {
1779 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1780 } catch (NumberFormatException nfe) {
1781 // Not a valid double
1782 errPw.println(
1783 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1784 return null;
1785 }
1786 }
1787 }
1788 bundle.putDoubleArray(key, valueDoubleArray);
1789 break;
1790 }
1791 case INT: {
1792 try {
1793 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1794 } catch (NumberFormatException nfe) {
1795 // Not a valid integer
1796 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1797 return null;
1798 }
1799 break;
1800 }
1801 case INT_ARRAY: {
1802 int[] valueIntArray = null;
1803 if (valueList.size() > 0) {
1804 valueIntArray = new int[valueList.size()];
1805 for (int i = 0; i < valueList.size(); i++) {
1806 try {
1807 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1808 } catch (NumberFormatException nfe) {
1809 // Not a valid integer
1810 errPw.println(tag
1811 + "Unable to parse " + valueList.get(i) + " as an integer.");
1812 return null;
1813 }
1814 }
1815 }
1816 bundle.putIntArray(key, valueIntArray);
1817 break;
1818 }
1819 case LONG: {
1820 try {
1821 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1822 } catch (NumberFormatException nfe) {
1823 // Not a valid long
1824 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1825 return null;
1826 }
1827 break;
1828 }
1829 case LONG_ARRAY: {
1830 long[] valueLongArray = null;
1831 if (valueList.size() > 0) {
1832 valueLongArray = new long[valueList.size()];
1833 for (int i = 0; i < valueList.size(); i++) {
1834 try {
1835 valueLongArray[i] = Long.parseLong(valueList.get(i));
1836 } catch (NumberFormatException nfe) {
1837 // Not a valid long
1838 errPw.println(
1839 tag + "Unable to parse " + valueList.get(i) + " as a long");
1840 return null;
1841 }
1842 }
1843 }
1844 bundle.putLongArray(key, valueLongArray);
1845 break;
1846 }
1847 case STRING: {
1848 String value = null;
1849 if (valueList.size() > 0) {
1850 value = valueList.get(0);
1851 }
1852 bundle.putString(key, value);
1853 break;
1854 }
1855 case STRING_ARRAY: {
1856 String[] valueStringArray = null;
1857 if (valueList.size() > 0) {
1858 valueStringArray = new String[valueList.size()];
1859 valueList.toArray(valueStringArray);
1860 }
1861 bundle.putStringArray(key, valueStringArray);
1862 break;
1863 }
1864 }
1865 return bundle;
1866 }
Shuo Qian489d9282020-07-09 11:30:03 -07001867
1868 private int handleEndBlockSuppressionCommand() {
1869 if (!checkShellUid()) {
1870 return -1;
1871 }
1872
1873 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1874 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1875 }
1876 return 0;
1877 }
Hui Wang641e81c2020-10-12 12:14:23 -07001878
Michele Berionne54af4632020-12-28 20:23:16 +00001879 private int handleRestartModemCommand() {
1880 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1881 // non user build.
1882 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1883 getErrPrintWriter().println("RestartModem: Permission denied.");
1884 return -1;
1885 }
1886
1887 boolean result = TelephonyManager.getDefault().rebootRadio();
1888 getOutPrintWriter().println(result);
1889
1890 return result ? 0 : -1;
1891 }
1892
Michele Berionne5e411512020-11-13 02:36:59 +00001893 private int handleUnattendedReboot() {
1894 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1895 // non user build.
1896 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1897 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1898 return -1;
1899 }
1900
1901 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1902 getOutPrintWriter().println("result: " + result);
1903
1904 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1905 }
1906
Hui Wang641e81c2020-10-12 12:14:23 -07001907 private int handleGbaCommand() {
1908 String arg = getNextArg();
1909 if (arg == null) {
1910 onHelpGba();
1911 return 0;
1912 }
1913
1914 switch (arg) {
1915 case GBA_SET_SERVICE: {
1916 return handleGbaSetServiceCommand();
1917 }
1918 case GBA_GET_SERVICE: {
1919 return handleGbaGetServiceCommand();
1920 }
1921 case GBA_SET_RELEASE_TIME: {
1922 return handleGbaSetReleaseCommand();
1923 }
1924 case GBA_GET_RELEASE_TIME: {
1925 return handleGbaGetReleaseCommand();
1926 }
1927 }
1928
1929 return -1;
1930 }
1931
1932 private int getSubId(String cmd) {
1933 int slotId = getDefaultSlot();
1934 String opt = getNextOption();
1935 if (opt != null && opt.equals("-s")) {
1936 try {
1937 slotId = Integer.parseInt(getNextArgRequired());
1938 } catch (NumberFormatException e) {
1939 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1940 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1941 }
1942 }
1943 int[] subIds = SubscriptionManager.getSubId(slotId);
1944 return subIds[0];
1945 }
1946
1947 private int handleGbaSetServiceCommand() {
1948 int subId = getSubId("gba set-service");
1949 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1950 return -1;
1951 }
1952
1953 String packageName = getNextArg();
1954 try {
1955 if (packageName == null) {
1956 packageName = "";
1957 }
1958 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1959 if (VDBG) {
1960 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1961 + packageName + ", result=" + result);
1962 }
1963 getOutPrintWriter().println(result);
1964 } catch (RemoteException e) {
1965 Log.w(LOG_TAG, "gba set-service " + subId + " "
1966 + packageName + ", error" + e.getMessage());
1967 getErrPrintWriter().println("Exception: " + e.getMessage());
1968 return -1;
1969 }
1970 return 0;
1971 }
1972
1973 private int handleGbaGetServiceCommand() {
1974 String result;
1975
1976 int subId = getSubId("gba get-service");
1977 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1978 return -1;
1979 }
1980
1981 try {
1982 result = mInterface.getBoundGbaService(subId);
1983 } catch (RemoteException e) {
1984 return -1;
1985 }
1986 if (VDBG) {
1987 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1988 }
1989 getOutPrintWriter().println(result);
1990 return 0;
1991 }
1992
1993 private int handleGbaSetReleaseCommand() {
1994 //the release time value could be -1
1995 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1996 : SubscriptionManager.getDefaultSubscriptionId();
1997 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1998 return -1;
1999 }
2000
2001 String intervalStr = getNextArg();
2002 if (intervalStr == null) {
2003 return -1;
2004 }
2005
2006 try {
2007 int interval = Integer.parseInt(intervalStr);
2008 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2009 if (VDBG) {
2010 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2011 + intervalStr + ", result=" + result);
2012 }
2013 getOutPrintWriter().println(result);
2014 } catch (NumberFormatException | RemoteException e) {
2015 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2016 + intervalStr + ", error" + e.getMessage());
2017 getErrPrintWriter().println("Exception: " + e.getMessage());
2018 return -1;
2019 }
2020 return 0;
2021 }
2022
2023 private int handleGbaGetReleaseCommand() {
2024 int subId = getSubId("gba get-release");
2025 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2026 return -1;
2027 }
2028
2029 int result = 0;
2030 try {
2031 result = mInterface.getGbaReleaseTime(subId);
2032 } catch (RemoteException e) {
2033 return -1;
2034 }
2035 if (VDBG) {
2036 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2037 }
2038 getOutPrintWriter().println(result);
2039 return 0;
2040 }
Hui Wang761a6682020-10-31 05:12:53 +00002041
2042 private int handleSingleRegistrationConfigCommand() {
2043 String arg = getNextArg();
2044 if (arg == null) {
2045 onHelpSrc();
2046 return 0;
2047 }
2048
2049 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002050 case SRC_SET_TEST_ENABLED: {
2051 return handleSrcSetTestEnabledCommand();
2052 }
2053 case SRC_GET_TEST_ENABLED: {
2054 return handleSrcGetTestEnabledCommand();
2055 }
Hui Wang761a6682020-10-31 05:12:53 +00002056 case SRC_SET_DEVICE_ENABLED: {
2057 return handleSrcSetDeviceEnabledCommand();
2058 }
2059 case SRC_GET_DEVICE_ENABLED: {
2060 return handleSrcGetDeviceEnabledCommand();
2061 }
2062 case SRC_SET_CARRIER_ENABLED: {
2063 return handleSrcSetCarrierEnabledCommand();
2064 }
2065 case SRC_GET_CARRIER_ENABLED: {
2066 return handleSrcGetCarrierEnabledCommand();
2067 }
Hui Wangb647abe2021-02-26 09:33:38 -08002068 case SRC_SET_FEATURE_ENABLED: {
2069 return handleSrcSetFeatureValidationCommand();
2070 }
2071 case SRC_GET_FEATURE_ENABLED: {
2072 return handleSrcGetFeatureValidationCommand();
2073 }
Hui Wang761a6682020-10-31 05:12:53 +00002074 }
2075
2076 return -1;
2077 }
2078
James.cf Linbcdf8b32021-01-14 16:44:13 +08002079 private int handleRcsUceCommand() {
2080 String arg = getNextArg();
2081 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002082 onHelpUce();
2083 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002084 }
2085
2086 switch (arg) {
2087 case UCE_REMOVE_EAB_CONTACT:
2088 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002089 case UCE_GET_EAB_CONTACT:
2090 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002091 case UCE_GET_EAB_CAPABILITY:
2092 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002093 case UCE_GET_DEVICE_ENABLED:
2094 return handleUceGetDeviceEnabledCommand();
2095 case UCE_SET_DEVICE_ENABLED:
2096 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002097 case UCE_OVERRIDE_PUBLISH_CAPS:
2098 return handleUceOverridePublishCaps();
2099 case UCE_GET_LAST_PIDF_XML:
2100 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002101 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2102 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002103 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2104 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002105 }
2106 return -1;
2107 }
2108
2109 private int handleRemovingEabContactCommand() {
2110 int subId = getSubId("uce remove-eab-contact");
2111 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2112 return -1;
2113 }
2114
2115 String phoneNumber = getNextArgRequired();
2116 if (TextUtils.isEmpty(phoneNumber)) {
2117 return -1;
2118 }
2119 int result = 0;
2120 try {
2121 result = mInterface.removeContactFromEab(subId, phoneNumber);
2122 } catch (RemoteException e) {
2123 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2124 getErrPrintWriter().println("Exception: " + e.getMessage());
2125 return -1;
2126 }
2127
2128 if (VDBG) {
2129 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2130 }
calvinpan293ea1b2021-02-04 17:52:13 +08002131 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002132 }
2133
calvinpane4a8a1d2021-01-25 13:51:18 +08002134 private int handleGettingEabContactCommand() {
2135 String phoneNumber = getNextArgRequired();
2136 if (TextUtils.isEmpty(phoneNumber)) {
2137 return -1;
2138 }
2139 String result = "";
2140 try {
2141 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002142 } catch (RemoteException e) {
2143 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2144 getErrPrintWriter().println("Exception: " + e.getMessage());
2145 return -1;
2146 }
2147
2148 if (VDBG) {
2149 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2150 }
calvinpan293ea1b2021-02-04 17:52:13 +08002151 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002152 return 0;
2153 }
2154
Calvin Pana1434322021-07-01 19:27:01 +08002155 private int handleGettingEabCapabilityCommand() {
2156 String phoneNumber = getNextArgRequired();
2157 if (TextUtils.isEmpty(phoneNumber)) {
2158 return -1;
2159 }
2160 String result = "";
2161 try {
2162 result = mInterface.getCapabilityFromEab(phoneNumber);
2163 } catch (RemoteException e) {
2164 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2165 getErrPrintWriter().println("Exception: " + e.getMessage());
2166 return -1;
2167 }
2168
2169 if (VDBG) {
2170 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2171 }
2172 getOutPrintWriter().println(result);
2173 return 0;
2174 }
2175
James.cf Lin4b784aa2021-01-31 03:25:15 +08002176 private int handleUceGetDeviceEnabledCommand() {
2177 boolean result = false;
2178 try {
2179 result = mInterface.getDeviceUceEnabled();
2180 } catch (RemoteException e) {
2181 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2182 return -1;
2183 }
2184 if (VDBG) {
2185 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2186 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002187 getOutPrintWriter().println(result);
2188 return 0;
2189 }
2190
James.cf Lin4b784aa2021-01-31 03:25:15 +08002191 private int handleUceSetDeviceEnabledCommand() {
2192 String enabledStr = getNextArg();
2193 if (TextUtils.isEmpty(enabledStr)) {
2194 return -1;
2195 }
2196
2197 try {
2198 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2199 mInterface.setDeviceUceEnabled(isEnabled);
2200 if (VDBG) {
2201 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2202 }
2203 } catch (NumberFormatException | RemoteException e) {
2204 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2205 getErrPrintWriter().println("Exception: " + e.getMessage());
2206 return -1;
2207 }
2208 return 0;
2209 }
2210
James.cf Line8713a42021-04-29 16:04:26 +08002211 private int handleUceRemoveRequestDisallowedStatus() {
2212 int subId = getSubId("uce remove-request-disallowed-status");
2213 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2214 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2215 return -1;
2216 }
2217 boolean result;
2218 try {
2219 result = mInterface.removeUceRequestDisallowedStatus(subId);
2220 } catch (RemoteException e) {
2221 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2222 return -1;
2223 }
2224 if (VDBG) {
2225 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2226 }
2227 getOutPrintWriter().println(result);
2228 return 0;
2229 }
2230
James.cf Lin0fc71b02021-05-25 01:37:38 +08002231 private int handleUceSetCapRequestTimeout() {
2232 int subId = getSubId("uce set-capabilities-request-timeout");
2233 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2234 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2235 return -1;
2236 }
2237 long timeoutAfterMs = Long.valueOf(getNextArg());
2238 boolean result;
2239 try {
2240 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2241 } catch (RemoteException e) {
2242 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2243 return -1;
2244 }
2245 if (VDBG) {
2246 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2247 }
2248 getOutPrintWriter().println(result);
2249 return 0;
2250 }
2251
Hui Wangbaaee6a2021-02-19 20:45:36 -08002252 private int handleSrcSetTestEnabledCommand() {
2253 String enabledStr = getNextArg();
2254 if (enabledStr == null) {
2255 return -1;
2256 }
2257
2258 try {
2259 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2260 if (VDBG) {
2261 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2262 }
2263 getOutPrintWriter().println("Done");
2264 } catch (NumberFormatException | RemoteException e) {
2265 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2266 getErrPrintWriter().println("Exception: " + e.getMessage());
2267 return -1;
2268 }
2269 return 0;
2270 }
2271
2272 private int handleSrcGetTestEnabledCommand() {
2273 boolean result = false;
2274 try {
2275 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2276 } catch (RemoteException e) {
2277 return -1;
2278 }
2279 if (VDBG) {
2280 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2281 }
2282 getOutPrintWriter().println(result);
2283 return 0;
2284 }
2285
Brad Ebinger14d467f2021-02-12 06:18:28 +00002286 private int handleUceOverridePublishCaps() {
2287 int subId = getSubId("uce override-published-caps");
2288 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2289 return -1;
2290 }
2291 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2292 String operation = getNextArgRequired();
2293 String caps = getNextArg();
2294 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2295 && !"list".equals(operation)) {
2296 getErrPrintWriter().println("Invalid operation: " + operation);
2297 return -1;
2298 }
2299
2300 // add/remove requires capabilities to be specified.
2301 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2302 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2303 + "specified");
2304 return -1;
2305 }
2306
2307 ArraySet<String> capSet = new ArraySet<>();
2308 if (!TextUtils.isEmpty(caps)) {
2309 String[] capArray = caps.split(":");
2310 for (String cap : capArray) {
2311 // Allow unknown tags to be passed in as well.
2312 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2313 }
2314 }
2315
2316 RcsContactUceCapability result = null;
2317 try {
2318 switch (operation) {
2319 case "add":
2320 result = mInterface.addUceRegistrationOverrideShell(subId,
2321 new ArrayList<>(capSet));
2322 break;
2323 case "remove":
2324 result = mInterface.removeUceRegistrationOverrideShell(subId,
2325 new ArrayList<>(capSet));
2326 break;
2327 case "clear":
2328 result = mInterface.clearUceRegistrationOverrideShell(subId);
2329 break;
2330 case "list":
2331 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2332 break;
2333 }
2334 } catch (RemoteException e) {
2335 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2336 getErrPrintWriter().println("Exception: " + e.getMessage());
2337 return -1;
2338 } catch (ServiceSpecificException sse) {
2339 // Reconstruct ImsException
2340 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2341 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2342 getErrPrintWriter().println("Exception: " + imsException);
2343 return -1;
2344 }
2345 if (result == null) {
2346 getErrPrintWriter().println("Service not available");
2347 return -1;
2348 }
2349 getOutPrintWriter().println(result);
2350 return 0;
2351 }
2352
2353 private int handleUceGetPidfXml() {
2354 int subId = getSubId("uce get-last-publish-pidf");
2355 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2356 return -1;
2357 }
2358
2359 String result;
2360 try {
2361 result = mInterface.getLastUcePidfXmlShell(subId);
2362 } catch (RemoteException e) {
2363 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2364 getErrPrintWriter().println("Exception: " + e.getMessage());
2365 return -1;
2366 } catch (ServiceSpecificException sse) {
2367 // Reconstruct ImsException
2368 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2369 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2370 getErrPrintWriter().println("Exception: " + imsException);
2371 return -1;
2372 }
2373 if (result == null) {
2374 getErrPrintWriter().println("Service not available");
2375 return -1;
2376 }
2377 getOutPrintWriter().println(result);
2378 return 0;
2379 }
2380
Hui Wang761a6682020-10-31 05:12:53 +00002381 private int handleSrcSetDeviceEnabledCommand() {
2382 String enabledStr = getNextArg();
2383 if (enabledStr == null) {
2384 return -1;
2385 }
2386
2387 try {
2388 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2389 if (VDBG) {
2390 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2391 }
2392 getOutPrintWriter().println("Done");
2393 } catch (NumberFormatException | RemoteException e) {
2394 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2395 getErrPrintWriter().println("Exception: " + e.getMessage());
2396 return -1;
2397 }
2398 return 0;
2399 }
2400
2401 private int handleSrcGetDeviceEnabledCommand() {
2402 boolean result = false;
2403 try {
2404 result = mInterface.getDeviceSingleRegistrationEnabled();
2405 } catch (RemoteException e) {
2406 return -1;
2407 }
2408 if (VDBG) {
2409 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2410 }
2411 getOutPrintWriter().println(result);
2412 return 0;
2413 }
2414
2415 private int handleSrcSetCarrierEnabledCommand() {
2416 //the release time value could be -1
2417 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2418 : SubscriptionManager.getDefaultSubscriptionId();
2419 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2420 return -1;
2421 }
2422
2423 String enabledStr = getNextArg();
2424 if (enabledStr == null) {
2425 return -1;
2426 }
2427
2428 try {
2429 boolean result =
2430 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2431 if (VDBG) {
2432 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2433 + enabledStr + ", result=" + result);
2434 }
2435 getOutPrintWriter().println(result);
2436 } catch (NumberFormatException | RemoteException e) {
2437 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2438 + enabledStr + ", error" + e.getMessage());
2439 getErrPrintWriter().println("Exception: " + e.getMessage());
2440 return -1;
2441 }
2442 return 0;
2443 }
2444
2445 private int handleSrcGetCarrierEnabledCommand() {
2446 int subId = getSubId("src get-carrier-enabled");
2447 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2448 return -1;
2449 }
2450
2451 boolean result = false;
2452 try {
2453 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2454 } catch (RemoteException e) {
2455 return -1;
2456 }
2457 if (VDBG) {
2458 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2459 }
2460 getOutPrintWriter().println(result);
2461 return 0;
2462 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002463
Hui Wangb647abe2021-02-26 09:33:38 -08002464 private int handleSrcSetFeatureValidationCommand() {
2465 //the release time value could be -1
2466 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2467 : SubscriptionManager.getDefaultSubscriptionId();
2468 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2469 return -1;
2470 }
2471
2472 String enabledStr = getNextArg();
2473 if (enabledStr == null) {
2474 return -1;
2475 }
2476
2477 try {
2478 boolean result =
2479 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2480 if (VDBG) {
2481 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2482 + enabledStr + ", result=" + result);
2483 }
2484 getOutPrintWriter().println(result);
2485 } catch (NumberFormatException | RemoteException e) {
2486 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2487 + enabledStr + ", error" + e.getMessage());
2488 getErrPrintWriter().println("Exception: " + e.getMessage());
2489 return -1;
2490 }
2491 return 0;
2492 }
2493
2494 private int handleSrcGetFeatureValidationCommand() {
2495 int subId = getSubId("src get-feature-validation");
2496 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2497 return -1;
2498 }
2499
2500 Boolean result = false;
2501 try {
2502 result = mInterface.getImsFeatureValidationOverride(subId);
2503 } catch (RemoteException e) {
2504 return -1;
2505 }
2506 if (VDBG) {
2507 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2508 }
2509 getOutPrintWriter().println(result);
2510 return 0;
2511 }
2512
2513
Hall Liuaa4211e2021-01-20 15:43:39 -08002514 private void onHelpCallComposer() {
2515 PrintWriter pw = getOutPrintWriter();
2516 pw.println("Call composer commands");
2517 pw.println(" callcomposer test-mode enable|disable|query");
2518 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2519 pw.println(" upload/download from carrier servers is disabled, and operations are");
2520 pw.println(" performed using emulated local files instead.");
2521 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2522 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2523 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002524 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2525 pw.println(" Enables or disables the user setting for call composer, as set by");
2526 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002527 }
2528
2529 private int handleCallComposerCommand() {
2530 String arg = getNextArg();
2531 if (arg == null) {
2532 onHelpCallComposer();
2533 return 0;
2534 }
2535
2536 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2537 "MODIFY_PHONE_STATE required for call composer shell cmds");
2538 switch (arg) {
2539 case CALL_COMPOSER_TEST_MODE: {
2540 String enabledStr = getNextArg();
2541 if (ENABLE.equals(enabledStr)) {
2542 CallComposerPictureManager.sTestMode = true;
2543 } else if (DISABLE.equals(enabledStr)) {
2544 CallComposerPictureManager.sTestMode = false;
2545 } else if (QUERY.equals(enabledStr)) {
2546 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2547 } else {
2548 onHelpCallComposer();
2549 return 1;
2550 }
2551 break;
2552 }
2553 case CALL_COMPOSER_SIMULATE_CALL: {
2554 int subscriptionId = Integer.valueOf(getNextArg());
2555 String uuidString = getNextArg();
2556 UUID uuid = UUID.fromString(uuidString);
2557 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2558 Binder.withCleanCallingIdentity(() -> {
2559 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2560 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2561 });
2562 try {
2563 Uri uri = storageUriFuture.get();
2564 getOutPrintWriter().println(String.valueOf(uri));
2565 } catch (Exception e) {
2566 throw new RuntimeException(e);
2567 }
2568 break;
2569 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002570 case CALL_COMPOSER_USER_SETTING: {
2571 try {
2572 int subscriptionId = Integer.valueOf(getNextArg());
2573 String enabledStr = getNextArg();
2574 if (ENABLE.equals(enabledStr)) {
2575 mInterface.setCallComposerStatus(subscriptionId,
2576 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2577 } else if (DISABLE.equals(enabledStr)) {
2578 mInterface.setCallComposerStatus(subscriptionId,
2579 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2580 } else if (QUERY.equals(enabledStr)) {
2581 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2582 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2583 } else {
2584 onHelpCallComposer();
2585 return 1;
2586 }
2587 } catch (RemoteException e) {
2588 e.printStackTrace(getOutPrintWriter());
2589 return 1;
2590 }
2591 break;
2592 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002593 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002594 return 0;
2595 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002596
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002597 private int handleHasCarrierPrivilegesCommand() {
2598 String packageName = getNextArgRequired();
2599
2600 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002601 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002602 try {
2603 hasCarrierPrivileges =
2604 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2605 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2606 } catch (RemoteException e) {
2607 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2608 getErrPrintWriter().println("Exception: " + e.getMessage());
2609 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002610 } finally {
2611 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002612 }
2613
2614 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002615 return 0;
2616 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002617
2618 private int handleAllowedNetworkTypesCommand(String command) {
2619 if (!checkShellUid()) {
2620 return -1;
2621 }
2622
2623 PrintWriter errPw = getErrPrintWriter();
2624 String tag = command + ": ";
2625 String opt;
2626 int subId = -1;
2627 Log.v(LOG_TAG, command + " start");
2628
2629 while ((opt = getNextOption()) != null) {
2630 if (opt.equals("-s")) {
2631 try {
2632 subId = slotStringToSubId(tag, getNextArgRequired());
2633 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2634 errPw.println(tag + "No valid subscription found.");
2635 return -1;
2636 }
2637 } catch (IllegalArgumentException e) {
2638 // Missing slot id
2639 errPw.println(tag + "SLOT_ID expected after -s.");
2640 return -1;
2641 }
2642 } else {
2643 errPw.println(tag + "Unknown option " + opt);
2644 return -1;
2645 }
2646 }
2647
2648 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2649 return handleGetAllowedNetworkTypesCommand(subId);
2650 }
2651 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2652 return handleSetAllowedNetworkTypesCommand(subId);
2653 }
2654 return -1;
2655 }
2656
2657 private int handleGetAllowedNetworkTypesCommand(int subId) {
2658 PrintWriter errPw = getErrPrintWriter();
2659
2660 long result = -1;
2661 try {
2662 if (mInterface != null) {
2663 result = mInterface.getAllowedNetworkTypesForReason(subId,
2664 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2665 } else {
2666 throw new IllegalStateException("telephony service is null.");
2667 }
2668 } catch (RemoteException e) {
2669 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2670 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2671 return -1;
2672 }
2673
2674 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2675 return 0;
2676 }
2677
2678 private int handleSetAllowedNetworkTypesCommand(int subId) {
2679 PrintWriter errPw = getErrPrintWriter();
2680
2681 String bitmaskString = getNextArg();
2682 if (TextUtils.isEmpty(bitmaskString)) {
2683 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2684 return -1;
2685 }
2686 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2687 if (allowedNetworkTypes < 0) {
2688 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2689 return -1;
2690 }
2691 boolean result = false;
2692 try {
2693 if (mInterface != null) {
2694 result = mInterface.setAllowedNetworkTypesForReason(subId,
2695 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2696 } else {
2697 throw new IllegalStateException("telephony service is null.");
2698 }
2699 } catch (RemoteException e) {
2700 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2701 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2702 return -1;
2703 }
2704
2705 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2706 if (result) {
2707 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2708 }
2709 getOutPrintWriter().println(resultMessage);
2710 return 0;
2711 }
2712
2713 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2714 if (TextUtils.isEmpty(bitmaskString)) {
2715 return -1;
2716 }
2717 if (VDBG) {
2718 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2719 + ", length: " + bitmaskString.length());
2720 }
2721 try {
2722 return Long.parseLong(bitmaskString, 2);
2723 } catch (NumberFormatException e) {
2724 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2725 return -1;
2726 }
2727 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002728}