blob: 7eb3bd95854691c9fa130cf9c5ad2bc579bcb27b [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
jimsun38340bf2021-10-26 15:01:23 +0800154 private static final String RADIO_SUBCOMMAND = "radio";
155 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
156 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
157
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800158 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
159 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
160
Jordan Liu0ccee222021-04-27 11:55:13 -0700161 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
162 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
163
Jack Nudelman644b91a2021-03-12 14:09:48 -0800164 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
165 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
166 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
167
SongFerngWang98dd5992021-05-13 17:50:00 +0800168 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
169 "get-allowed-network-types-for-users";
170 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
171 "set-allowed-network-types-for-users";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700172 // Take advantage of existing methods that already contain permissions checks when possible.
173 private final ITelephony mInterface;
174
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100175 private SubscriptionManager mSubscriptionManager;
176 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700177 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700178 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100179
180 private enum CcType {
181 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
182 STRING_ARRAY, UNKNOWN
183 }
184
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100185 private class CcOptionParseResult {
186 public int mSubId;
187 public boolean mPersistent;
188 }
189
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100190 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
191 // keys by looking at the end of the string which usually tells the type.
192 // For instance: "xxxx_string", "xxxx_string_array", etc.
193 // The carrier config keys in this map does not follow this convention. It is therefore not
194 // possible to infer the type for these keys by looking at the string.
195 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
196 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
197 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
198 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
199 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
200 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
206 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
207 CcType.STRING);
208 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
209 CcType.STRING_ARRAY);
210 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
211 CcType.STRING_ARRAY);
212 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
213 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
214 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
215 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
216 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
217 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
219 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
220 }
221 };
222
Brad Ebinger14d467f2021-02-12 06:18:28 +0000223 /**
224 * Map from a shorthand string to the feature tags required in registration required in order
225 * for the RCS feature to be considered "capable".
226 */
227 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
228 static {
229 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
230 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
231 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
232 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
233 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
234 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
235 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
236 FeatureTags.FEATURE_TAG_VIDEO)));
237 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
238 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
239 map.put("call_comp",
240 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
241 map.put("call_comp_mmtel",
242 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
243 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
244 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
245 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
246 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
247 // version
248 map.put("chatbot", new ArraySet<>(Arrays.asList(
249 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
250 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
251 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
252 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
253 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
254 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
255 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
256 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
257 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
258 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
259 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
260 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
261 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
262 }
263
264
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100265 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700266 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100267 mCarrierConfigManager =
268 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
269 mSubscriptionManager = (SubscriptionManager)
270 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700271 mTelephonyRegistryManager = (TelephonyRegistryManager)
272 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700273 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700274 }
275
276 @Override
277 public int onCommand(String cmd) {
278 if (cmd == null) {
279 return handleDefaultCommands(null);
280 }
281
282 switch (cmd) {
283 case IMS_SUBCOMMAND: {
284 return handleImsCommand();
285 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800286 case RCS_UCE_COMMAND:
287 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800288 case NUMBER_VERIFICATION_SUBCOMMAND:
289 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800290 case EMERGENCY_CALLBACK_MODE:
291 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800292 case EMERGENCY_NUMBER_TEST_MODE:
293 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100294 case CARRIER_CONFIG_SUBCOMMAND: {
295 return handleCcCommand();
296 }
Shuo Qianf5125122019-12-16 17:03:07 -0800297 case DATA_TEST_MODE:
298 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700299 case END_BLOCK_SUPPRESSION:
300 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700301 case GBA_SUBCOMMAND:
302 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800303 case D2D_SUBCOMMAND:
304 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700305 case BARRING_SUBCOMMAND:
306 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000307 case SINGLE_REGISTATION_CONFIG:
308 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000309 case RESTART_MODEM:
310 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800311 case CALL_COMPOSER_SUBCOMMAND:
312 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000313 case UNATTENDED_REBOOT:
314 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800315 case HAS_CARRIER_PRIVILEGES_COMMAND:
316 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800317 case THERMAL_MITIGATION_COMMAND:
318 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700319 case DISABLE_PHYSICAL_SUBSCRIPTION:
320 return handleEnablePhysicalSubscription(false);
321 case ENABLE_PHYSICAL_SUBSCRIPTION:
322 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800323 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
324 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
325 return handleAllowedNetworkTypesCommand(cmd);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700326 default: {
327 return handleDefaultCommands(cmd);
328 }
329 }
330 }
331
332 @Override
333 public void onHelp() {
334 PrintWriter pw = getOutPrintWriter();
335 pw.println("Telephony Commands:");
336 pw.println(" help");
337 pw.println(" Print this help text.");
338 pw.println(" ims");
339 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800340 pw.println(" uce");
341 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800342 pw.println(" emergency-number-test-mode");
343 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700344 pw.println(" end-block-suppression");
345 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800346 pw.println(" data");
347 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100348 pw.println(" cc");
349 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700350 pw.println(" gba");
351 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000352 pw.println(" src");
353 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000354 pw.println(" restart-modem");
355 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000356 pw.println(" unattended-reboot");
357 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800358 pw.println(" has-carrier-privileges [package]");
359 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800360 pw.println(" get-allowed-network-types-for-users");
361 pw.println(" Get the Allowed Network Types.");
362 pw.println(" set-allowed-network-types-for-users");
363 pw.println(" Set the Allowed Network Types.");
jimsun38340bf2021-10-26 15:01:23 +0800364 pw.println(" radio");
365 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700366 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800367 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800368 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700369 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800370 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100371 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700372 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000373 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800374 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700375 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800376 onHelpAllowedNetworkTypes();
jimsun38340bf2021-10-26 15:01:23 +0800377 onHelpRadio();
Tyler Gunn92479152021-01-20 16:30:10 -0800378 }
379
380 private void onHelpD2D() {
381 PrintWriter pw = getOutPrintWriter();
382 pw.println("D2D Comms Commands:");
383 pw.println(" d2d send TYPE VALUE");
384 pw.println(" Sends a D2D message of specified type and value.");
385 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
386 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
387 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
388 MESSAGE_CALL_AUDIO_CODEC));
389 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
390 + Communicator.messageToString(
391 MESSAGE_DEVICE_BATTERY_STATE));
392 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
393 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800394 pw.println(" d2d transport TYPE");
395 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
396 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700397 pw.println(" d2d set-device-support true/default");
398 pw.println(" true - forces device support to be enabled for D2D.");
399 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
400 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700401 }
402
Nazanin014f41e2021-05-06 17:26:31 -0700403 private void onHelpBarring() {
404 PrintWriter pw = getOutPrintWriter();
405 pw.println("Barring Commands:");
406 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
407 + " -t CONDITIONAL_BARRING_TIME_SECS");
408 pw.println(" Notifies of a barring info change for the specified slot id.");
409 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
410 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
411 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
412 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
413 }
414
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700415 private void onHelpIms() {
416 PrintWriter pw = getOutPrintWriter();
417 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800418 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700419 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
420 pw.println(" ImsService. Options are:");
421 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
422 pw.println(" is specified, it will choose the default voice SIM slot.");
423 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
424 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800425 pw.println(" -f: Set the feature that this override if for, if no option is");
426 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700427 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
428 pw.println(" Gets the package name of the currently defined ImsService.");
429 pw.println(" Options are:");
430 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
431 pw.println(" is specified, it will choose the default voice SIM slot.");
432 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000433 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800434 pw.println(" -f: The feature type that the query will be requested for. If none is");
435 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800436 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
437 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
438 pw.println(" configuration overrides. Options are:");
439 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
440 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700441 pw.println(" ims enable [-s SLOT_ID]");
442 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
443 pw.println(" if none is specified.");
444 pw.println(" ims disable [-s SLOT_ID]");
445 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
446 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700447 pw.println(" ims conference-event-package [enable/disable]");
448 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700449 }
450
James.cf Linbcdf8b32021-01-14 16:44:13 +0800451 private void onHelpUce() {
452 PrintWriter pw = getOutPrintWriter();
453 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800454 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
455 pw.println(" Get the EAB contacts from the EAB database.");
456 pw.println(" Options are:");
457 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
458 pw.println(" Expected output format :");
459 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800460 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
461 pw.println(" Remove the EAB contacts from the EAB database.");
462 pw.println(" Options are:");
463 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
464 pw.println(" is specified, it will choose the default voice SIM slot.");
465 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800466 pw.println(" uce get-device-enabled");
467 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
468 pw.println(" uce set-device-enabled true|false");
469 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
470 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000471 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
472 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
473 pw.println(" Options are:");
474 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
475 pw.println(" is specified, it will choose the default voice SIM slot.");
476 pw.println(" add [CAPABILITY]: add a new capability");
477 pw.println(" remove [CAPABILITY]: remove a capability");
478 pw.println(" clear: clear all capability overrides");
479 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
480 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
481 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
482 pw.println(" chatbot_sa, chatbot_role] as well as full length");
483 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
484 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
485 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
486 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800487 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
488 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800489 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
490 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800491 }
492
Hall Liud892bec2018-11-30 14:51:45 -0800493 private void onHelpNumberVerification() {
494 PrintWriter pw = getOutPrintWriter();
495 pw.println("Number verification commands");
496 pw.println(" numverify override-package PACKAGE_NAME;");
497 pw.println(" Set the authorized package for number verification.");
498 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800499 pw.println(" numverify fake-call NUMBER;");
500 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
501 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800502 }
503
Jack Nudelman644b91a2021-03-12 14:09:48 -0800504 private void onHelpThermalMitigation() {
505 PrintWriter pw = getOutPrintWriter();
506 pw.println("Thermal mitigation commands");
507 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
508 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
509 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
510 pw.println(" Remove the package from one of the authorized packages for thermal "
511 + "mitigation.");
512 }
513
Jordan Liu0ccee222021-04-27 11:55:13 -0700514 private void onHelpDisableOrEnablePhysicalSubscription() {
515 PrintWriter pw = getOutPrintWriter();
516 pw.println("Disable or enable a physical subscription");
517 pw.println(" disable-physical-subscription SUB_ID");
518 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
519 pw.println(" enable-physical-subscription SUB_ID");
520 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
521 }
522
Shuo Qianf5125122019-12-16 17:03:07 -0800523 private void onHelpDataTestMode() {
524 PrintWriter pw = getOutPrintWriter();
525 pw.println("Mobile Data Test Mode Commands:");
526 pw.println(" data enable: enable mobile data connectivity");
527 pw.println(" data disable: disable mobile data connectivity");
528 }
529
sqian9d4df8b2019-01-15 18:32:07 -0800530 private void onHelpEmergencyNumber() {
531 PrintWriter pw = getOutPrintWriter();
532 pw.println("Emergency Number Test Mode Commands:");
533 pw.println(" emergency-number-test-mode ");
534 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
535 + " the test mode");
536 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700537 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800538 pw.println(" -c: clear the emergency number list in the test mode.");
539 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700540 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800541 pw.println(" -p: get the full emergency number list in the test mode.");
542 }
543
Shuo Qian489d9282020-07-09 11:30:03 -0700544 private void onHelpEndBlockSupperssion() {
545 PrintWriter pw = getOutPrintWriter();
546 pw.println("End Block Suppression command:");
547 pw.println(" end-block-suppression: disable suppressing blocking by contact");
548 pw.println(" with emergency services.");
549 }
550
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100551 private void onHelpCc() {
552 PrintWriter pw = getOutPrintWriter();
553 pw.println("Carrier Config Commands:");
554 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
555 pw.println(" Print carrier config values.");
556 pw.println(" Options are:");
557 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
558 pw.println(" is specified, it will choose the default voice SIM slot.");
559 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
560 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100561 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100562 pw.println(" Set carrier config KEY to NEW_VALUE.");
563 pw.println(" Options are:");
564 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
565 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100566 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100567 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
568 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
569 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
570 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
571 pw.println(" cc clear-values [-s SLOT_ID]");
572 pw.println(" Clear all carrier override values that has previously been set");
573 pw.println(" with set-value");
574 pw.println(" Options are:");
575 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
576 pw.println(" is specified, it will choose the default voice SIM slot.");
577 }
578
Hui Wang641e81c2020-10-12 12:14:23 -0700579 private void onHelpGba() {
580 PrintWriter pw = getOutPrintWriter();
581 pw.println("Gba Commands:");
582 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
583 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
584 pw.println(" Options are:");
585 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
586 pw.println(" is specified, it will choose the default voice SIM slot.");
587 pw.println(" gba get-service [-s SLOT_ID]");
588 pw.println(" Gets the package name of the currently defined GbaService.");
589 pw.println(" Options are:");
590 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
591 pw.println(" is specified, it will choose the default voice SIM slot.");
592 pw.println(" gba set-release [-s SLOT_ID] n");
593 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
594 pw.println(" Do not release/unbind if n is -1.");
595 pw.println(" Options are:");
596 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
597 pw.println(" is specified, it will choose the default voice SIM slot.");
598 pw.println(" gba get-release [-s SLOT_ID]");
599 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
600 pw.println(" Options are:");
601 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
602 pw.println(" is specified, it will choose the default voice SIM slot.");
603 }
604
Hui Wang761a6682020-10-31 05:12:53 +0000605 private void onHelpSrc() {
606 PrintWriter pw = getOutPrintWriter();
607 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800608 pw.println(" src set-test-enabled true|false");
609 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
610 pw.println(" The value could be true, false, or null(undefined).");
611 pw.println(" src get-test-enabled");
612 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000613 pw.println(" src set-device-enabled true|false|null");
614 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
615 pw.println(" The value could be true, false, or null(undefined).");
616 pw.println(" src get-device-enabled");
617 pw.println(" Gets the device config for RCS VoLTE single registration.");
618 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
619 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
620 pw.println(" The value could be true, false, or null(undefined).");
621 pw.println(" Options are:");
622 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
623 pw.println(" is specified, it will choose the default voice SIM slot.");
624 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
625 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
626 pw.println(" Options are:");
627 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
628 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800629 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
630 pw.println(" Sets ims feature validation result.");
631 pw.println(" The value could be true, false, or null(undefined).");
632 pw.println(" Options are:");
633 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
634 pw.println(" is specified, it will choose the default voice SIM slot.");
635 pw.println(" src get-feature-validation [-s SLOT_ID]");
636 pw.println(" Gets ims feature validation override value.");
637 pw.println(" Options are:");
638 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
639 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000640 }
641
SongFerngWang98dd5992021-05-13 17:50:00 +0800642 private void onHelpAllowedNetworkTypes() {
643 PrintWriter pw = getOutPrintWriter();
644 pw.println("Allowed Network Types Commands:");
645 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
646 pw.println(" Print allowed network types value.");
647 pw.println(" Options are:");
648 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
649 pw.println(" option is specified, it will choose the default voice SIM slot.");
650 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
651 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
652 pw.println(" Options are:");
653 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
654 pw.println(" option is specified, it will choose the default voice SIM slot.");
655 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
656 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
657 pw.println(" at TelephonyManager.java");
658 pw.println(" For example:");
659 pw.println(" NR only : 10000000000000000000");
660 pw.println(" NR|LTE : 11000001000000000000");
661 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
662 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
663 pw.println(" LTE only : 01000001000000000000");
664 }
665
jimsun38340bf2021-10-26 15:01:23 +0800666 private void onHelpRadio() {
667 PrintWriter pw = getOutPrintWriter();
668 pw.println("Radio Commands:");
669 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
670 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
671 pw.println(" to be the bound. Options are:");
672 pw.println(" -s: the service name that the modem service should be bound for.");
673 pw.println(" If no option is specified, it will bind to the default.");
674 pw.println(" radio get-modem-service");
675 pw.println(" Gets the service name of the currently defined modem service.");
676 pw.println(" If it is binding to default, 'default' returns.");
677 pw.println(" If it doesn't bind to any modem service for some reasons,");
678 pw.println(" the result would be 'unknown'.");
679 }
680
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700681 private int handleImsCommand() {
682 String arg = getNextArg();
683 if (arg == null) {
684 onHelpIms();
685 return 0;
686 }
687
688 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800689 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700690 return handleImsSetServiceCommand();
691 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800692 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700693 return handleImsGetServiceCommand();
694 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800695 case IMS_CLEAR_SERVICE_OVERRIDE: {
696 return handleImsClearCarrierServiceCommand();
697 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800698 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700699 return handleEnableIms();
700 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800701 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700702 return handleDisableIms();
703 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700704 case IMS_CEP: {
705 return handleCepChange();
706 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700707 }
708
709 return -1;
710 }
711
Shuo Qianf5125122019-12-16 17:03:07 -0800712 private int handleDataTestModeCommand() {
713 PrintWriter errPw = getErrPrintWriter();
714 String arg = getNextArgRequired();
715 if (arg == null) {
716 onHelpDataTestMode();
717 return 0;
718 }
719 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800720 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800721 try {
722 mInterface.enableDataConnectivity();
723 } catch (RemoteException ex) {
724 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
725 errPw.println("Exception: " + ex.getMessage());
726 return -1;
727 }
728 break;
729 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800730 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800731 try {
732 mInterface.disableDataConnectivity();
733 } catch (RemoteException ex) {
734 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
735 errPw.println("Exception: " + ex.getMessage());
736 return -1;
737 }
738 break;
739 }
740 default:
741 onHelpDataTestMode();
742 break;
743 }
744 return 0;
745 }
746
Shuo Qianccbaf742021-02-22 18:32:21 -0800747 private int handleEmergencyCallbackModeCommand() {
748 PrintWriter errPw = getErrPrintWriter();
749 try {
750 mInterface.startEmergencyCallbackMode();
751 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
752 } catch (RemoteException ex) {
753 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
754 errPw.println("Exception: " + ex.getMessage());
755 return -1;
756 }
757 return 0;
758 }
759
sqian9d4df8b2019-01-15 18:32:07 -0800760 private int handleEmergencyNumberTestModeCommand() {
761 PrintWriter errPw = getErrPrintWriter();
762 String opt = getNextOption();
763 if (opt == null) {
764 onHelpEmergencyNumber();
765 return 0;
766 }
767
768 switch (opt) {
769 case "-a": {
770 String emergencyNumberCmd = getNextArgRequired();
771 if (emergencyNumberCmd == null
772 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700773 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800774 + " to be specified after -a in the command ");
775 return -1;
776 }
777 try {
778 mInterface.updateEmergencyNumberListTestMode(
779 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
780 new EmergencyNumber(emergencyNumberCmd, "", "",
781 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
782 new ArrayList<String>(),
783 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
784 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
785 } catch (RemoteException ex) {
786 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
787 + ", error " + ex.getMessage());
788 errPw.println("Exception: " + ex.getMessage());
789 return -1;
790 }
791 break;
792 }
793 case "-c": {
794 try {
795 mInterface.updateEmergencyNumberListTestMode(
796 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
797 } catch (RemoteException ex) {
798 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
799 errPw.println("Exception: " + ex.getMessage());
800 return -1;
801 }
802 break;
803 }
804 case "-r": {
805 String emergencyNumberCmd = getNextArgRequired();
806 if (emergencyNumberCmd == null
807 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700808 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800809 + " to be specified after -r in the command ");
810 return -1;
811 }
812 try {
813 mInterface.updateEmergencyNumberListTestMode(
814 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
815 new EmergencyNumber(emergencyNumberCmd, "", "",
816 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
817 new ArrayList<String>(),
818 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
819 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
820 } catch (RemoteException ex) {
821 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
822 + ", error " + ex.getMessage());
823 errPw.println("Exception: " + ex.getMessage());
824 return -1;
825 }
826 break;
827 }
828 case "-p": {
829 try {
830 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
831 } catch (RemoteException ex) {
832 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
833 errPw.println("Exception: " + ex.getMessage());
834 return -1;
835 }
836 break;
837 }
838 default:
839 onHelpEmergencyNumber();
840 break;
841 }
842 return 0;
843 }
844
Hall Liud892bec2018-11-30 14:51:45 -0800845 private int handleNumberVerificationCommand() {
846 String arg = getNextArg();
847 if (arg == null) {
848 onHelpNumberVerification();
849 return 0;
850 }
851
Hall Liuca5af3a2018-12-04 16:58:23 -0800852 if (!checkShellUid()) {
853 return -1;
854 }
855
Hall Liud892bec2018-11-30 14:51:45 -0800856 switch (arg) {
857 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800858 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
859 return 0;
860 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800861 case NUMBER_VERIFICATION_FAKE_CALL: {
862 boolean val = NumberVerificationManager.getInstance()
863 .checkIncomingCall(getNextArg());
864 getOutPrintWriter().println(val ? "1" : "0");
865 return 0;
866 }
Hall Liud892bec2018-11-30 14:51:45 -0800867 }
868
869 return -1;
870 }
871
Jordan Liu0ccee222021-04-27 11:55:13 -0700872 private boolean subIsEsim(int subId) {
873 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
874 if (info != null) {
875 return info.isEmbedded();
876 }
877 return false;
878 }
879
880 private int handleEnablePhysicalSubscription(boolean enable) {
881 PrintWriter errPw = getErrPrintWriter();
882 int subId = 0;
883 try {
884 subId = Integer.parseInt(getNextArgRequired());
885 } catch (NumberFormatException e) {
886 errPw.println((enable ? "enable" : "disable")
887 + "-physical-subscription requires an integer as a subId.");
888 return -1;
889 }
890 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
891 // non user build.
892 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
893 errPw.println("cc: Permission denied.");
894 return -1;
895 }
896 // Verify that the subId represents a physical sub
897 if (subIsEsim(subId)) {
898 errPw.println("SubId " + subId + " is not for a physical subscription");
899 return -1;
900 }
901 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
902 + " physical subscription with subId=" + subId);
903 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
904 return 0;
905 }
906
Jack Nudelman644b91a2021-03-12 14:09:48 -0800907 private int handleThermalMitigationCommand() {
908 String arg = getNextArg();
909 String packageName = getNextArg();
910 if (arg == null || packageName == null) {
911 onHelpThermalMitigation();
912 return 0;
913 }
914
915 if (!checkShellUid()) {
916 return -1;
917 }
918
919 switch (arg) {
920 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
921 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
922 return 0;
923 }
924 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
925 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
926 mContext);
927 return 0;
928 }
929 default:
930 onHelpThermalMitigation();
931 }
932
933 return -1;
934
935 }
936
Tyler Gunn92479152021-01-20 16:30:10 -0800937 private int handleD2dCommand() {
938 String arg = getNextArg();
939 if (arg == null) {
940 onHelpD2D();
941 return 0;
942 }
943
944 switch (arg) {
945 case D2D_SEND: {
946 return handleD2dSendCommand();
947 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800948 case D2D_TRANSPORT: {
949 return handleD2dTransportCommand();
950 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700951 case D2D_SET_DEVICE_SUPPORT: {
952 return handleD2dDeviceSupportedCommand();
953 }
Tyler Gunn92479152021-01-20 16:30:10 -0800954 }
955
956 return -1;
957 }
958
959 private int handleD2dSendCommand() {
960 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800961 int messageType = -1;
962 int messageValue = -1;
963
Tyler Gunn92479152021-01-20 16:30:10 -0800964 String arg = getNextArg();
965 if (arg == null) {
966 onHelpD2D();
967 return 0;
968 }
969 try {
970 messageType = Integer.parseInt(arg);
971 } catch (NumberFormatException e) {
972 errPw.println("message type must be a valid integer");
973 return -1;
974 }
975
976 arg = getNextArg();
977 if (arg == null) {
978 onHelpD2D();
979 return 0;
980 }
981 try {
982 messageValue = Integer.parseInt(arg);
983 } catch (NumberFormatException e) {
984 errPw.println("message value must be a valid integer");
985 return -1;
986 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800987
Tyler Gunn92479152021-01-20 16:30:10 -0800988 try {
989 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
990 } catch (RemoteException e) {
991 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
992 errPw.println("Exception: " + e.getMessage());
993 return -1;
994 }
995
996 return 0;
997 }
998
Tyler Gunnbabbda02021-02-10 11:05:02 -0800999 private int handleD2dTransportCommand() {
1000 PrintWriter errPw = getErrPrintWriter();
1001
1002 String arg = getNextArg();
1003 if (arg == null) {
1004 onHelpD2D();
1005 return 0;
1006 }
1007
1008 try {
1009 mInterface.setActiveDeviceToDeviceTransport(arg);
1010 } catch (RemoteException e) {
1011 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1012 errPw.println("Exception: " + e.getMessage());
1013 return -1;
1014 }
1015 return 0;
1016 }
Nazanin014f41e2021-05-06 17:26:31 -07001017 private int handleBarringCommand() {
1018 String arg = getNextArg();
1019 if (arg == null) {
1020 onHelpBarring();
1021 return 0;
1022 }
1023
1024 switch (arg) {
1025 case BARRING_SEND_INFO: {
1026 return handleBarringSendCommand();
1027 }
1028 }
1029 return -1;
1030 }
1031
1032 private int handleBarringSendCommand() {
1033 PrintWriter errPw = getErrPrintWriter();
1034 int slotId = getDefaultSlot();
1035 int subId = SubscriptionManager.getSubId(slotId)[0];
1036 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1037 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1038 boolean isConditionallyBarred = false;
1039 int conditionalBarringTimeSeconds = 0;
1040
1041 String opt;
1042 while ((opt = getNextOption()) != null) {
1043 switch (opt) {
1044 case "-s": {
1045 try {
1046 slotId = Integer.parseInt(getNextArgRequired());
1047 subId = SubscriptionManager.getSubId(slotId)[0];
1048 } catch (NumberFormatException e) {
1049 errPw.println("barring send requires an integer as a SLOT_ID.");
1050 return -1;
1051 }
1052 break;
1053 }
1054 case "-b": {
1055 try {
1056 barringType = Integer.parseInt(getNextArgRequired());
1057 if (barringType < -1 || barringType > 2) {
1058 throw new NumberFormatException();
1059 }
1060
1061 } catch (NumberFormatException e) {
1062 errPw.println("barring send requires an integer in range [-1,2] as "
1063 + "a BARRING_TYPE.");
1064 return -1;
1065 }
1066 break;
1067 }
1068 case "-c": {
1069 try {
1070 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1071 } catch (Exception e) {
1072 errPw.println("barring send requires a boolean after -c indicating"
1073 + " conditional barring");
1074 return -1;
1075 }
1076 break;
1077 }
1078 case "-t": {
1079 try {
1080 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1081 } catch (NumberFormatException e) {
1082 errPw.println("barring send requires an integer for time of barring"
1083 + " in seconds after -t for conditional barring");
1084 return -1;
1085 }
1086 break;
1087 }
1088 }
1089 }
1090 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1091 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1092 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1093 barringServiceInfos.append(0, bsi);
1094 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1095 try {
1096 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1097 } catch (Exception e) {
1098 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1099 errPw.println("Exception: " + e.getMessage());
1100 return -1;
1101 }
1102 return 0;
1103 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001104
Tyler Gunnd4575212021-05-03 14:46:49 -07001105 private int handleD2dDeviceSupportedCommand() {
1106 PrintWriter errPw = getErrPrintWriter();
1107
1108 String arg = getNextArg();
1109 if (arg == null) {
1110 onHelpD2D();
1111 return 0;
1112 }
1113
1114 boolean isEnabled = "true".equals(arg.toLowerCase());
1115 try {
1116 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1117 } catch (RemoteException e) {
1118 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1119 errPw.println("Exception: " + e.getMessage());
1120 return -1;
1121 }
1122 return 0;
1123 }
1124
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001125 // ims set-ims-service
1126 private int handleImsSetServiceCommand() {
1127 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001128 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001129 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001130 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001131
1132 String opt;
1133 while ((opt = getNextOption()) != null) {
1134 switch (opt) {
1135 case "-s": {
1136 try {
1137 slotId = Integer.parseInt(getNextArgRequired());
1138 } catch (NumberFormatException e) {
1139 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1140 return -1;
1141 }
1142 break;
1143 }
1144 case "-c": {
1145 isCarrierService = true;
1146 break;
1147 }
1148 case "-d": {
1149 isCarrierService = false;
1150 break;
1151 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001152 case "-f": {
1153 String featureString = getNextArgRequired();
1154 String[] features = featureString.split(",");
1155 for (int i = 0; i < features.length; i++) {
1156 try {
1157 Integer result = Integer.parseInt(features[i]);
1158 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1159 || result >= ImsFeature.FEATURE_MAX) {
1160 errPw.println("ims set-ims-service -f " + result
1161 + " is an invalid feature.");
1162 return -1;
1163 }
1164 featuresList.add(result);
1165 } catch (NumberFormatException e) {
1166 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1167 + " as an integer.");
1168 return -1;
1169 }
1170 }
1171 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001172 }
1173 }
1174 // Mandatory param, either -c or -d
1175 if (isCarrierService == null) {
1176 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1177 return -1;
1178 }
1179
1180 String packageName = getNextArg();
1181
1182 try {
1183 if (packageName == null) {
1184 packageName = "";
1185 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001186 int[] featureArray = new int[featuresList.size()];
1187 for (int i = 0; i < featuresList.size(); i++) {
1188 featureArray[i] = featuresList.get(i);
1189 }
1190 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1191 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001192 if (VDBG) {
1193 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001194 + (isCarrierService ? "-c " : "-d ")
1195 + "-f " + featuresList + " "
1196 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001197 }
1198 getOutPrintWriter().println(result);
1199 } catch (RemoteException e) {
1200 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001201 + (isCarrierService ? "-c " : "-d ")
1202 + "-f " + featuresList + " "
1203 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001204 errPw.println("Exception: " + e.getMessage());
1205 return -1;
1206 }
1207 return 0;
1208 }
1209
Brad Ebinger999d3302020-11-25 14:31:39 -08001210 // ims clear-ims-service-override
1211 private int handleImsClearCarrierServiceCommand() {
1212 PrintWriter errPw = getErrPrintWriter();
1213 int slotId = getDefaultSlot();
1214
1215 String opt;
1216 while ((opt = getNextOption()) != null) {
1217 switch (opt) {
1218 case "-s": {
1219 try {
1220 slotId = Integer.parseInt(getNextArgRequired());
1221 } catch (NumberFormatException e) {
1222 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1223 return -1;
1224 }
1225 break;
1226 }
1227 }
1228 }
1229
1230 try {
1231 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1232 if (VDBG) {
1233 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1234 + ", result=" + result);
1235 }
1236 getOutPrintWriter().println(result);
1237 } catch (RemoteException e) {
1238 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1239 + ", error" + e.getMessage());
1240 errPw.println("Exception: " + e.getMessage());
1241 return -1;
1242 }
1243 return 0;
1244 }
1245
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001246 // ims get-ims-service
1247 private int handleImsGetServiceCommand() {
1248 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001249 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001250 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001251 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001252
1253 String opt;
1254 while ((opt = getNextOption()) != null) {
1255 switch (opt) {
1256 case "-s": {
1257 try {
1258 slotId = Integer.parseInt(getNextArgRequired());
1259 } catch (NumberFormatException e) {
1260 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1261 return -1;
1262 }
1263 break;
1264 }
1265 case "-c": {
1266 isCarrierService = true;
1267 break;
1268 }
1269 case "-d": {
1270 isCarrierService = false;
1271 break;
1272 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001273 case "-f": {
1274 try {
1275 featureType = Integer.parseInt(getNextArg());
1276 } catch (NumberFormatException e) {
1277 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1278 return -1;
1279 }
1280 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1281 || featureType >= ImsFeature.FEATURE_MAX) {
1282 errPw.println("ims get-ims-service -f invalid feature.");
1283 return -1;
1284 }
1285 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001286 }
1287 }
1288 // Mandatory param, either -c or -d
1289 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001290 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001291 return -1;
1292 }
1293
1294 String result;
1295 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001296 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001297 } catch (RemoteException e) {
1298 return -1;
1299 }
1300 if (VDBG) {
1301 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001302 + (isCarrierService ? "-c " : "-d ")
1303 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1304 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001305 }
1306 getOutPrintWriter().println(result);
1307 return 0;
1308 }
1309
1310 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001311 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001312 String opt;
1313 while ((opt = getNextOption()) != null) {
1314 switch (opt) {
1315 case "-s": {
1316 try {
1317 slotId = Integer.parseInt(getNextArgRequired());
1318 } catch (NumberFormatException e) {
1319 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1320 return -1;
1321 }
1322 break;
1323 }
1324 }
1325 }
1326 try {
1327 mInterface.enableIms(slotId);
1328 } catch (RemoteException e) {
1329 return -1;
1330 }
1331 if (VDBG) {
1332 Log.v(LOG_TAG, "ims enable -s " + slotId);
1333 }
1334 return 0;
1335 }
1336
1337 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001338 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001339 String opt;
1340 while ((opt = getNextOption()) != null) {
1341 switch (opt) {
1342 case "-s": {
1343 try {
1344 slotId = Integer.parseInt(getNextArgRequired());
1345 } catch (NumberFormatException e) {
1346 getErrPrintWriter().println(
1347 "ims disable requires an integer as a SLOT_ID.");
1348 return -1;
1349 }
1350 break;
1351 }
1352 }
1353 }
1354 try {
1355 mInterface.disableIms(slotId);
1356 } catch (RemoteException e) {
1357 return -1;
1358 }
1359 if (VDBG) {
1360 Log.v(LOG_TAG, "ims disable -s " + slotId);
1361 }
1362 return 0;
1363 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001364
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001365 private int handleCepChange() {
1366 Log.i(LOG_TAG, "handleCepChange");
1367 String opt = getNextArg();
1368 if (opt == null) {
1369 return -1;
1370 }
1371 boolean isCepEnabled = opt.equals("enable");
1372
1373 try {
1374 mInterface.setCepEnabled(isCepEnabled);
1375 } catch (RemoteException e) {
1376 return -1;
1377 }
1378 return 0;
1379 }
1380
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001381 private int getDefaultSlot() {
1382 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1383 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1384 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1385 // If there is no default, default to slot 0.
1386 slotId = DEFAULT_PHONE_ID;
1387 }
1388 return slotId;
1389 }
sqian2fff4a32018-11-05 14:18:37 -08001390
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001391 // Parse options related to Carrier Config Commands.
1392 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001393 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001394 CcOptionParseResult result = new CcOptionParseResult();
1395 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1396 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001397
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001398 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001399 while ((opt = getNextOption()) != null) {
1400 switch (opt) {
1401 case "-s": {
1402 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001403 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1404 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1405 errPw.println(tag + "No valid subscription found.");
1406 return null;
1407 }
1408
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001409 } catch (IllegalArgumentException e) {
1410 // Missing slot id
1411 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001412 return null;
1413 }
1414 break;
1415 }
1416 case "-p": {
1417 if (allowOptionPersistent) {
1418 result.mPersistent = true;
1419 } else {
1420 errPw.println(tag + "Unexpected option " + opt);
1421 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001422 }
1423 break;
1424 }
1425 default: {
1426 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001427 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001428 }
1429 }
1430 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001431 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001432 }
1433
1434 private int slotStringToSubId(String tag, String slotString) {
1435 int slotId = -1;
1436 try {
1437 slotId = Integer.parseInt(slotString);
1438 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001439 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1440 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1441 }
1442
1443 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001444 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1445 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1446 }
1447
Qiong Liuf25799b2020-09-10 10:13:46 +08001448 Phone phone = PhoneFactory.getPhone(slotId);
1449 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001450 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1451 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1452 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001453 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001454 }
1455
Hall Liud892bec2018-11-30 14:51:45 -08001456 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001457 // adb can run as root or as shell, depending on whether the device is rooted.
1458 return Binder.getCallingUid() == Process.SHELL_UID
1459 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001460 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001461
1462 private int handleCcCommand() {
1463 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1464 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001465 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001466 getErrPrintWriter().println("cc: Permission denied.");
1467 return -1;
1468 }
1469
1470 String arg = getNextArg();
1471 if (arg == null) {
1472 onHelpCc();
1473 return 0;
1474 }
1475
1476 switch (arg) {
1477 case CC_GET_VALUE: {
1478 return handleCcGetValue();
1479 }
1480 case CC_SET_VALUE: {
1481 return handleCcSetValue();
1482 }
1483 case CC_CLEAR_VALUES: {
1484 return handleCcClearValues();
1485 }
1486 default: {
1487 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1488 }
1489 }
1490 return -1;
1491 }
1492
1493 // cc get-value
1494 private int handleCcGetValue() {
1495 PrintWriter errPw = getErrPrintWriter();
1496 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1497 String key = null;
1498
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001499 // Parse all options
1500 CcOptionParseResult options = parseCcOptions(tag, false);
1501 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001502 return -1;
1503 }
1504
1505 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001506 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001507 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001508 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001509 return -1;
1510 }
1511
1512 // Get the key.
1513 key = getNextArg();
1514 if (key != null) {
1515 // A key was provided. Verify if it is a valid key
1516 if (!bundle.containsKey(key)) {
1517 errPw.println(tag + key + " is not a valid key.");
1518 return -1;
1519 }
1520
1521 // Print the carrier config value for key.
1522 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1523 } else {
1524 // No key provided. Show all values.
1525 // Iterate over a sorted list of all carrier config keys and print them.
1526 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1527 for (String k : sortedSet) {
1528 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1529 }
1530 }
1531 return 0;
1532 }
1533
1534 // cc set-value
1535 private int handleCcSetValue() {
1536 PrintWriter errPw = getErrPrintWriter();
1537 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1538
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001539 // Parse all options
1540 CcOptionParseResult options = parseCcOptions(tag, true);
1541 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001542 return -1;
1543 }
1544
1545 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001546 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001547 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001548 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001549 return -1;
1550 }
1551
1552 // Get the key.
1553 String key = getNextArg();
1554 if (key == null || key.equals("")) {
1555 errPw.println(tag + "KEY is missing");
1556 return -1;
1557 }
1558
1559 // Verify if the key is valid
1560 if (!originalValues.containsKey(key)) {
1561 errPw.println(tag + key + " is not a valid key.");
1562 return -1;
1563 }
1564
1565 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1566 ArrayList<String> valueList = new ArrayList<String>();
1567 while (peekNextArg() != null) {
1568 valueList.add(getNextArg());
1569 }
1570
1571 // Find the type of the carrier config value
1572 CcType type = getType(tag, key, originalValues);
1573 if (type == CcType.UNKNOWN) {
1574 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1575 return -1;
1576 }
1577
1578 // Create an override bundle containing the key and value that should be overriden.
1579 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1580 if (overrideBundle == null) {
1581 return -1;
1582 }
1583
1584 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001585 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001586
1587 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001588 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001589 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001590 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001591 return -1;
1592 }
1593
1594 // Print the original and new value.
1595 String originalValueString = ccValueToString(key, type, originalValues);
1596 String newValueString = ccValueToString(key, type, newValues);
1597 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1598 getOutPrintWriter().println("New value: \n" + newValueString);
1599
1600 return 0;
1601 }
1602
1603 // cc clear-values
1604 private int handleCcClearValues() {
1605 PrintWriter errPw = getErrPrintWriter();
1606 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1607
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001608 // Parse all options
1609 CcOptionParseResult options = parseCcOptions(tag, false);
1610 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001611 return -1;
1612 }
1613
1614 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001615 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001616 getOutPrintWriter()
1617 .println("All previously set carrier config override values has been cleared");
1618 return 0;
1619 }
1620
1621 private CcType getType(String tag, String key, PersistableBundle bundle) {
1622 // Find the type by checking the type of the current value stored in the bundle.
1623 Object value = bundle.get(key);
1624
1625 if (CC_TYPE_MAP.containsKey(key)) {
1626 return CC_TYPE_MAP.get(key);
1627 } else if (value != null) {
1628 if (value instanceof Boolean) {
1629 return CcType.BOOLEAN;
1630 } else if (value instanceof Double) {
1631 return CcType.DOUBLE;
1632 } else if (value instanceof double[]) {
1633 return CcType.DOUBLE_ARRAY;
1634 } else if (value instanceof Integer) {
1635 return CcType.INT;
1636 } else if (value instanceof int[]) {
1637 return CcType.INT_ARRAY;
1638 } else if (value instanceof Long) {
1639 return CcType.LONG;
1640 } else if (value instanceof long[]) {
1641 return CcType.LONG_ARRAY;
1642 } else if (value instanceof String) {
1643 return CcType.STRING;
1644 } else if (value instanceof String[]) {
1645 return CcType.STRING_ARRAY;
1646 }
1647 } else {
1648 // Current value was null and can therefore not be used in order to find the type.
1649 // Check the name of the key to infer the type. This check is not needed for primitive
1650 // data types (boolean, double, int and long), since they can not be null.
1651 if (key.endsWith("double_array")) {
1652 return CcType.DOUBLE_ARRAY;
1653 }
1654 if (key.endsWith("int_array")) {
1655 return CcType.INT_ARRAY;
1656 }
1657 if (key.endsWith("long_array")) {
1658 return CcType.LONG_ARRAY;
1659 }
1660 if (key.endsWith("string")) {
1661 return CcType.STRING;
1662 }
1663 if (key.endsWith("string_array") || key.endsWith("strings")) {
1664 return CcType.STRING_ARRAY;
1665 }
1666 }
1667
1668 // Not possible to infer the type by looking at the current value or the key.
1669 PrintWriter errPw = getErrPrintWriter();
1670 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1671 return CcType.UNKNOWN;
1672 }
1673
1674 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1675 String result;
1676 StringBuilder valueString = new StringBuilder();
1677 String typeString = type.toString();
1678 Object value = bundle.get(key);
1679
1680 if (value == null) {
1681 valueString.append("null");
1682 } else {
1683 switch (type) {
1684 case DOUBLE_ARRAY: {
1685 // Format the string representation of the int array as value1 value2......
1686 double[] valueArray = (double[]) 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 INT_ARRAY: {
1696 // Format the string representation of the int array as value1 value2......
1697 int[] valueArray = (int[]) value;
1698 for (int i = 0; i < valueArray.length; i++) {
1699 if (i != 0) {
1700 valueString.append(" ");
1701 }
1702 valueString.append(valueArray[i]);
1703 }
1704 break;
1705 }
1706 case LONG_ARRAY: {
1707 // Format the string representation of the int array as value1 value2......
1708 long[] valueArray = (long[]) value;
1709 for (int i = 0; i < valueArray.length; i++) {
1710 if (i != 0) {
1711 valueString.append(" ");
1712 }
1713 valueString.append(valueArray[i]);
1714 }
1715 break;
1716 }
1717 case STRING: {
1718 valueString.append("\"" + value.toString() + "\"");
1719 break;
1720 }
1721 case STRING_ARRAY: {
1722 // Format the string representation of the string array as "value1" "value2"....
1723 String[] valueArray = (String[]) value;
1724 for (int i = 0; i < valueArray.length; i++) {
1725 if (i != 0) {
1726 valueString.append(" ");
1727 }
1728 if (valueArray[i] != null) {
1729 valueString.append("\"" + valueArray[i] + "\"");
1730 } else {
1731 valueString.append("null");
1732 }
1733 }
1734 break;
1735 }
1736 default: {
1737 valueString.append(value.toString());
1738 }
1739 }
1740 }
1741 return String.format("%-70s %-15s %s", key, typeString, valueString);
1742 }
1743
1744 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1745 ArrayList<String> valueList) {
1746 PrintWriter errPw = getErrPrintWriter();
1747 PersistableBundle bundle = new PersistableBundle();
1748
1749 // First verify that a valid number of values has been provided for the type.
1750 switch (type) {
1751 case BOOLEAN:
1752 case DOUBLE:
1753 case INT:
1754 case LONG: {
1755 if (valueList.size() != 1) {
1756 errPw.println(tag + "Expected 1 value for type " + type
1757 + ". Found: " + valueList.size());
1758 return null;
1759 }
1760 break;
1761 }
1762 case STRING: {
1763 if (valueList.size() > 1) {
1764 errPw.println(tag + "Expected 0 or 1 values for type " + type
1765 + ". Found: " + valueList.size());
1766 return null;
1767 }
1768 break;
1769 }
1770 }
1771
1772 // Parse the value according to type and add it to the Bundle.
1773 switch (type) {
1774 case BOOLEAN: {
1775 if ("true".equalsIgnoreCase(valueList.get(0))) {
1776 bundle.putBoolean(key, true);
1777 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1778 bundle.putBoolean(key, false);
1779 } else {
1780 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1781 return null;
1782 }
1783 break;
1784 }
1785 case DOUBLE: {
1786 try {
1787 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1788 } catch (NumberFormatException nfe) {
1789 // Not a valid double
1790 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1791 return null;
1792 }
1793 break;
1794 }
1795 case DOUBLE_ARRAY: {
1796 double[] valueDoubleArray = null;
1797 if (valueList.size() > 0) {
1798 valueDoubleArray = new double[valueList.size()];
1799 for (int i = 0; i < valueList.size(); i++) {
1800 try {
1801 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1802 } catch (NumberFormatException nfe) {
1803 // Not a valid double
1804 errPw.println(
1805 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1806 return null;
1807 }
1808 }
1809 }
1810 bundle.putDoubleArray(key, valueDoubleArray);
1811 break;
1812 }
1813 case INT: {
1814 try {
1815 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1816 } catch (NumberFormatException nfe) {
1817 // Not a valid integer
1818 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1819 return null;
1820 }
1821 break;
1822 }
1823 case INT_ARRAY: {
1824 int[] valueIntArray = null;
1825 if (valueList.size() > 0) {
1826 valueIntArray = new int[valueList.size()];
1827 for (int i = 0; i < valueList.size(); i++) {
1828 try {
1829 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1830 } catch (NumberFormatException nfe) {
1831 // Not a valid integer
1832 errPw.println(tag
1833 + "Unable to parse " + valueList.get(i) + " as an integer.");
1834 return null;
1835 }
1836 }
1837 }
1838 bundle.putIntArray(key, valueIntArray);
1839 break;
1840 }
1841 case LONG: {
1842 try {
1843 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1844 } catch (NumberFormatException nfe) {
1845 // Not a valid long
1846 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1847 return null;
1848 }
1849 break;
1850 }
1851 case LONG_ARRAY: {
1852 long[] valueLongArray = null;
1853 if (valueList.size() > 0) {
1854 valueLongArray = new long[valueList.size()];
1855 for (int i = 0; i < valueList.size(); i++) {
1856 try {
1857 valueLongArray[i] = Long.parseLong(valueList.get(i));
1858 } catch (NumberFormatException nfe) {
1859 // Not a valid long
1860 errPw.println(
1861 tag + "Unable to parse " + valueList.get(i) + " as a long");
1862 return null;
1863 }
1864 }
1865 }
1866 bundle.putLongArray(key, valueLongArray);
1867 break;
1868 }
1869 case STRING: {
1870 String value = null;
1871 if (valueList.size() > 0) {
1872 value = valueList.get(0);
1873 }
1874 bundle.putString(key, value);
1875 break;
1876 }
1877 case STRING_ARRAY: {
1878 String[] valueStringArray = null;
1879 if (valueList.size() > 0) {
1880 valueStringArray = new String[valueList.size()];
1881 valueList.toArray(valueStringArray);
1882 }
1883 bundle.putStringArray(key, valueStringArray);
1884 break;
1885 }
1886 }
1887 return bundle;
1888 }
Shuo Qian489d9282020-07-09 11:30:03 -07001889
1890 private int handleEndBlockSuppressionCommand() {
1891 if (!checkShellUid()) {
1892 return -1;
1893 }
1894
1895 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1896 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1897 }
1898 return 0;
1899 }
Hui Wang641e81c2020-10-12 12:14:23 -07001900
Michele Berionne54af4632020-12-28 20:23:16 +00001901 private int handleRestartModemCommand() {
1902 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1903 // non user build.
1904 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1905 getErrPrintWriter().println("RestartModem: Permission denied.");
1906 return -1;
1907 }
1908
1909 boolean result = TelephonyManager.getDefault().rebootRadio();
1910 getOutPrintWriter().println(result);
1911
1912 return result ? 0 : -1;
1913 }
1914
Michele Berionne5e411512020-11-13 02:36:59 +00001915 private int handleUnattendedReboot() {
1916 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1917 // non user build.
1918 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1919 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1920 return -1;
1921 }
1922
1923 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1924 getOutPrintWriter().println("result: " + result);
1925
1926 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1927 }
1928
Hui Wang641e81c2020-10-12 12:14:23 -07001929 private int handleGbaCommand() {
1930 String arg = getNextArg();
1931 if (arg == null) {
1932 onHelpGba();
1933 return 0;
1934 }
1935
1936 switch (arg) {
1937 case GBA_SET_SERVICE: {
1938 return handleGbaSetServiceCommand();
1939 }
1940 case GBA_GET_SERVICE: {
1941 return handleGbaGetServiceCommand();
1942 }
1943 case GBA_SET_RELEASE_TIME: {
1944 return handleGbaSetReleaseCommand();
1945 }
1946 case GBA_GET_RELEASE_TIME: {
1947 return handleGbaGetReleaseCommand();
1948 }
1949 }
1950
1951 return -1;
1952 }
1953
1954 private int getSubId(String cmd) {
1955 int slotId = getDefaultSlot();
1956 String opt = getNextOption();
1957 if (opt != null && opt.equals("-s")) {
1958 try {
1959 slotId = Integer.parseInt(getNextArgRequired());
1960 } catch (NumberFormatException e) {
1961 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1962 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1963 }
1964 }
1965 int[] subIds = SubscriptionManager.getSubId(slotId);
1966 return subIds[0];
1967 }
1968
1969 private int handleGbaSetServiceCommand() {
1970 int subId = getSubId("gba set-service");
1971 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1972 return -1;
1973 }
1974
1975 String packageName = getNextArg();
1976 try {
1977 if (packageName == null) {
1978 packageName = "";
1979 }
1980 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1981 if (VDBG) {
1982 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1983 + packageName + ", result=" + result);
1984 }
1985 getOutPrintWriter().println(result);
1986 } catch (RemoteException e) {
1987 Log.w(LOG_TAG, "gba set-service " + subId + " "
1988 + packageName + ", error" + e.getMessage());
1989 getErrPrintWriter().println("Exception: " + e.getMessage());
1990 return -1;
1991 }
1992 return 0;
1993 }
1994
1995 private int handleGbaGetServiceCommand() {
1996 String result;
1997
1998 int subId = getSubId("gba get-service");
1999 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2000 return -1;
2001 }
2002
2003 try {
2004 result = mInterface.getBoundGbaService(subId);
2005 } catch (RemoteException e) {
2006 return -1;
2007 }
2008 if (VDBG) {
2009 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2010 }
2011 getOutPrintWriter().println(result);
2012 return 0;
2013 }
2014
2015 private int handleGbaSetReleaseCommand() {
2016 //the release time value could be -1
2017 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2018 : SubscriptionManager.getDefaultSubscriptionId();
2019 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2020 return -1;
2021 }
2022
2023 String intervalStr = getNextArg();
2024 if (intervalStr == null) {
2025 return -1;
2026 }
2027
2028 try {
2029 int interval = Integer.parseInt(intervalStr);
2030 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2031 if (VDBG) {
2032 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2033 + intervalStr + ", result=" + result);
2034 }
2035 getOutPrintWriter().println(result);
2036 } catch (NumberFormatException | RemoteException e) {
2037 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2038 + intervalStr + ", error" + e.getMessage());
2039 getErrPrintWriter().println("Exception: " + e.getMessage());
2040 return -1;
2041 }
2042 return 0;
2043 }
2044
2045 private int handleGbaGetReleaseCommand() {
2046 int subId = getSubId("gba get-release");
2047 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2048 return -1;
2049 }
2050
2051 int result = 0;
2052 try {
2053 result = mInterface.getGbaReleaseTime(subId);
2054 } catch (RemoteException e) {
2055 return -1;
2056 }
2057 if (VDBG) {
2058 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2059 }
2060 getOutPrintWriter().println(result);
2061 return 0;
2062 }
Hui Wang761a6682020-10-31 05:12:53 +00002063
2064 private int handleSingleRegistrationConfigCommand() {
2065 String arg = getNextArg();
2066 if (arg == null) {
2067 onHelpSrc();
2068 return 0;
2069 }
2070
2071 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002072 case SRC_SET_TEST_ENABLED: {
2073 return handleSrcSetTestEnabledCommand();
2074 }
2075 case SRC_GET_TEST_ENABLED: {
2076 return handleSrcGetTestEnabledCommand();
2077 }
Hui Wang761a6682020-10-31 05:12:53 +00002078 case SRC_SET_DEVICE_ENABLED: {
2079 return handleSrcSetDeviceEnabledCommand();
2080 }
2081 case SRC_GET_DEVICE_ENABLED: {
2082 return handleSrcGetDeviceEnabledCommand();
2083 }
2084 case SRC_SET_CARRIER_ENABLED: {
2085 return handleSrcSetCarrierEnabledCommand();
2086 }
2087 case SRC_GET_CARRIER_ENABLED: {
2088 return handleSrcGetCarrierEnabledCommand();
2089 }
Hui Wangb647abe2021-02-26 09:33:38 -08002090 case SRC_SET_FEATURE_ENABLED: {
2091 return handleSrcSetFeatureValidationCommand();
2092 }
2093 case SRC_GET_FEATURE_ENABLED: {
2094 return handleSrcGetFeatureValidationCommand();
2095 }
Hui Wang761a6682020-10-31 05:12:53 +00002096 }
2097
2098 return -1;
2099 }
2100
James.cf Linbcdf8b32021-01-14 16:44:13 +08002101 private int handleRcsUceCommand() {
2102 String arg = getNextArg();
2103 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002104 onHelpUce();
2105 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002106 }
2107
2108 switch (arg) {
2109 case UCE_REMOVE_EAB_CONTACT:
2110 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002111 case UCE_GET_EAB_CONTACT:
2112 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002113 case UCE_GET_EAB_CAPABILITY:
2114 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002115 case UCE_GET_DEVICE_ENABLED:
2116 return handleUceGetDeviceEnabledCommand();
2117 case UCE_SET_DEVICE_ENABLED:
2118 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002119 case UCE_OVERRIDE_PUBLISH_CAPS:
2120 return handleUceOverridePublishCaps();
2121 case UCE_GET_LAST_PIDF_XML:
2122 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002123 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2124 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002125 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2126 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002127 }
2128 return -1;
2129 }
2130
2131 private int handleRemovingEabContactCommand() {
2132 int subId = getSubId("uce remove-eab-contact");
2133 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2134 return -1;
2135 }
2136
2137 String phoneNumber = getNextArgRequired();
2138 if (TextUtils.isEmpty(phoneNumber)) {
2139 return -1;
2140 }
2141 int result = 0;
2142 try {
2143 result = mInterface.removeContactFromEab(subId, phoneNumber);
2144 } catch (RemoteException e) {
2145 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2146 getErrPrintWriter().println("Exception: " + e.getMessage());
2147 return -1;
2148 }
2149
2150 if (VDBG) {
2151 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2152 }
calvinpan293ea1b2021-02-04 17:52:13 +08002153 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002154 }
2155
calvinpane4a8a1d2021-01-25 13:51:18 +08002156 private int handleGettingEabContactCommand() {
2157 String phoneNumber = getNextArgRequired();
2158 if (TextUtils.isEmpty(phoneNumber)) {
2159 return -1;
2160 }
2161 String result = "";
2162 try {
2163 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002164 } catch (RemoteException e) {
2165 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2166 getErrPrintWriter().println("Exception: " + e.getMessage());
2167 return -1;
2168 }
2169
2170 if (VDBG) {
2171 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2172 }
calvinpan293ea1b2021-02-04 17:52:13 +08002173 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002174 return 0;
2175 }
2176
Calvin Pana1434322021-07-01 19:27:01 +08002177 private int handleGettingEabCapabilityCommand() {
2178 String phoneNumber = getNextArgRequired();
2179 if (TextUtils.isEmpty(phoneNumber)) {
2180 return -1;
2181 }
2182 String result = "";
2183 try {
2184 result = mInterface.getCapabilityFromEab(phoneNumber);
2185 } catch (RemoteException e) {
2186 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2187 getErrPrintWriter().println("Exception: " + e.getMessage());
2188 return -1;
2189 }
2190
2191 if (VDBG) {
2192 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2193 }
2194 getOutPrintWriter().println(result);
2195 return 0;
2196 }
2197
James.cf Lin4b784aa2021-01-31 03:25:15 +08002198 private int handleUceGetDeviceEnabledCommand() {
2199 boolean result = false;
2200 try {
2201 result = mInterface.getDeviceUceEnabled();
2202 } catch (RemoteException e) {
2203 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2204 return -1;
2205 }
2206 if (VDBG) {
2207 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2208 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002209 getOutPrintWriter().println(result);
2210 return 0;
2211 }
2212
James.cf Lin4b784aa2021-01-31 03:25:15 +08002213 private int handleUceSetDeviceEnabledCommand() {
2214 String enabledStr = getNextArg();
2215 if (TextUtils.isEmpty(enabledStr)) {
2216 return -1;
2217 }
2218
2219 try {
2220 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2221 mInterface.setDeviceUceEnabled(isEnabled);
2222 if (VDBG) {
2223 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2224 }
2225 } catch (NumberFormatException | RemoteException e) {
2226 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2227 getErrPrintWriter().println("Exception: " + e.getMessage());
2228 return -1;
2229 }
2230 return 0;
2231 }
2232
James.cf Line8713a42021-04-29 16:04:26 +08002233 private int handleUceRemoveRequestDisallowedStatus() {
2234 int subId = getSubId("uce remove-request-disallowed-status");
2235 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2236 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2237 return -1;
2238 }
2239 boolean result;
2240 try {
2241 result = mInterface.removeUceRequestDisallowedStatus(subId);
2242 } catch (RemoteException e) {
2243 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2244 return -1;
2245 }
2246 if (VDBG) {
2247 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2248 }
2249 getOutPrintWriter().println(result);
2250 return 0;
2251 }
2252
James.cf Lin0fc71b02021-05-25 01:37:38 +08002253 private int handleUceSetCapRequestTimeout() {
2254 int subId = getSubId("uce set-capabilities-request-timeout");
2255 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2256 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2257 return -1;
2258 }
2259 long timeoutAfterMs = Long.valueOf(getNextArg());
2260 boolean result;
2261 try {
2262 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2263 } catch (RemoteException e) {
2264 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2265 return -1;
2266 }
2267 if (VDBG) {
2268 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2269 }
2270 getOutPrintWriter().println(result);
2271 return 0;
2272 }
2273
Hui Wangbaaee6a2021-02-19 20:45:36 -08002274 private int handleSrcSetTestEnabledCommand() {
2275 String enabledStr = getNextArg();
2276 if (enabledStr == null) {
2277 return -1;
2278 }
2279
2280 try {
2281 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2282 if (VDBG) {
2283 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2284 }
2285 getOutPrintWriter().println("Done");
2286 } catch (NumberFormatException | RemoteException e) {
2287 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2288 getErrPrintWriter().println("Exception: " + e.getMessage());
2289 return -1;
2290 }
2291 return 0;
2292 }
2293
2294 private int handleSrcGetTestEnabledCommand() {
2295 boolean result = false;
2296 try {
2297 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2298 } catch (RemoteException e) {
2299 return -1;
2300 }
2301 if (VDBG) {
2302 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2303 }
2304 getOutPrintWriter().println(result);
2305 return 0;
2306 }
2307
Brad Ebinger14d467f2021-02-12 06:18:28 +00002308 private int handleUceOverridePublishCaps() {
2309 int subId = getSubId("uce override-published-caps");
2310 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2311 return -1;
2312 }
2313 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2314 String operation = getNextArgRequired();
2315 String caps = getNextArg();
2316 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2317 && !"list".equals(operation)) {
2318 getErrPrintWriter().println("Invalid operation: " + operation);
2319 return -1;
2320 }
2321
2322 // add/remove requires capabilities to be specified.
2323 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2324 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2325 + "specified");
2326 return -1;
2327 }
2328
2329 ArraySet<String> capSet = new ArraySet<>();
2330 if (!TextUtils.isEmpty(caps)) {
2331 String[] capArray = caps.split(":");
2332 for (String cap : capArray) {
2333 // Allow unknown tags to be passed in as well.
2334 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2335 }
2336 }
2337
2338 RcsContactUceCapability result = null;
2339 try {
2340 switch (operation) {
2341 case "add":
2342 result = mInterface.addUceRegistrationOverrideShell(subId,
2343 new ArrayList<>(capSet));
2344 break;
2345 case "remove":
2346 result = mInterface.removeUceRegistrationOverrideShell(subId,
2347 new ArrayList<>(capSet));
2348 break;
2349 case "clear":
2350 result = mInterface.clearUceRegistrationOverrideShell(subId);
2351 break;
2352 case "list":
2353 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2354 break;
2355 }
2356 } catch (RemoteException e) {
2357 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2358 getErrPrintWriter().println("Exception: " + e.getMessage());
2359 return -1;
2360 } catch (ServiceSpecificException sse) {
2361 // Reconstruct ImsException
2362 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2363 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2364 getErrPrintWriter().println("Exception: " + imsException);
2365 return -1;
2366 }
2367 if (result == null) {
2368 getErrPrintWriter().println("Service not available");
2369 return -1;
2370 }
2371 getOutPrintWriter().println(result);
2372 return 0;
2373 }
2374
2375 private int handleUceGetPidfXml() {
2376 int subId = getSubId("uce get-last-publish-pidf");
2377 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2378 return -1;
2379 }
2380
2381 String result;
2382 try {
2383 result = mInterface.getLastUcePidfXmlShell(subId);
2384 } catch (RemoteException e) {
2385 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2386 getErrPrintWriter().println("Exception: " + e.getMessage());
2387 return -1;
2388 } catch (ServiceSpecificException sse) {
2389 // Reconstruct ImsException
2390 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2391 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2392 getErrPrintWriter().println("Exception: " + imsException);
2393 return -1;
2394 }
2395 if (result == null) {
2396 getErrPrintWriter().println("Service not available");
2397 return -1;
2398 }
2399 getOutPrintWriter().println(result);
2400 return 0;
2401 }
2402
Hui Wang761a6682020-10-31 05:12:53 +00002403 private int handleSrcSetDeviceEnabledCommand() {
2404 String enabledStr = getNextArg();
2405 if (enabledStr == null) {
2406 return -1;
2407 }
2408
2409 try {
2410 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2411 if (VDBG) {
2412 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2413 }
2414 getOutPrintWriter().println("Done");
2415 } catch (NumberFormatException | RemoteException e) {
2416 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2417 getErrPrintWriter().println("Exception: " + e.getMessage());
2418 return -1;
2419 }
2420 return 0;
2421 }
2422
2423 private int handleSrcGetDeviceEnabledCommand() {
2424 boolean result = false;
2425 try {
2426 result = mInterface.getDeviceSingleRegistrationEnabled();
2427 } catch (RemoteException e) {
2428 return -1;
2429 }
2430 if (VDBG) {
2431 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2432 }
2433 getOutPrintWriter().println(result);
2434 return 0;
2435 }
2436
2437 private int handleSrcSetCarrierEnabledCommand() {
2438 //the release time value could be -1
2439 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2440 : SubscriptionManager.getDefaultSubscriptionId();
2441 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2442 return -1;
2443 }
2444
2445 String enabledStr = getNextArg();
2446 if (enabledStr == null) {
2447 return -1;
2448 }
2449
2450 try {
2451 boolean result =
2452 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2453 if (VDBG) {
2454 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2455 + enabledStr + ", result=" + result);
2456 }
2457 getOutPrintWriter().println(result);
2458 } catch (NumberFormatException | RemoteException e) {
2459 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2460 + enabledStr + ", error" + e.getMessage());
2461 getErrPrintWriter().println("Exception: " + e.getMessage());
2462 return -1;
2463 }
2464 return 0;
2465 }
2466
2467 private int handleSrcGetCarrierEnabledCommand() {
2468 int subId = getSubId("src get-carrier-enabled");
2469 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2470 return -1;
2471 }
2472
2473 boolean result = false;
2474 try {
2475 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2476 } catch (RemoteException e) {
2477 return -1;
2478 }
2479 if (VDBG) {
2480 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2481 }
2482 getOutPrintWriter().println(result);
2483 return 0;
2484 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002485
Hui Wangb647abe2021-02-26 09:33:38 -08002486 private int handleSrcSetFeatureValidationCommand() {
2487 //the release time value could be -1
2488 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2489 : SubscriptionManager.getDefaultSubscriptionId();
2490 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2491 return -1;
2492 }
2493
2494 String enabledStr = getNextArg();
2495 if (enabledStr == null) {
2496 return -1;
2497 }
2498
2499 try {
2500 boolean result =
2501 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2502 if (VDBG) {
2503 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2504 + enabledStr + ", result=" + result);
2505 }
2506 getOutPrintWriter().println(result);
2507 } catch (NumberFormatException | RemoteException e) {
2508 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2509 + enabledStr + ", error" + e.getMessage());
2510 getErrPrintWriter().println("Exception: " + e.getMessage());
2511 return -1;
2512 }
2513 return 0;
2514 }
2515
2516 private int handleSrcGetFeatureValidationCommand() {
2517 int subId = getSubId("src get-feature-validation");
2518 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2519 return -1;
2520 }
2521
2522 Boolean result = false;
2523 try {
2524 result = mInterface.getImsFeatureValidationOverride(subId);
2525 } catch (RemoteException e) {
2526 return -1;
2527 }
2528 if (VDBG) {
2529 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2530 }
2531 getOutPrintWriter().println(result);
2532 return 0;
2533 }
2534
2535
Hall Liuaa4211e2021-01-20 15:43:39 -08002536 private void onHelpCallComposer() {
2537 PrintWriter pw = getOutPrintWriter();
2538 pw.println("Call composer commands");
2539 pw.println(" callcomposer test-mode enable|disable|query");
2540 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2541 pw.println(" upload/download from carrier servers is disabled, and operations are");
2542 pw.println(" performed using emulated local files instead.");
2543 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2544 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2545 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002546 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2547 pw.println(" Enables or disables the user setting for call composer, as set by");
2548 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002549 }
2550
2551 private int handleCallComposerCommand() {
2552 String arg = getNextArg();
2553 if (arg == null) {
2554 onHelpCallComposer();
2555 return 0;
2556 }
2557
2558 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2559 "MODIFY_PHONE_STATE required for call composer shell cmds");
2560 switch (arg) {
2561 case CALL_COMPOSER_TEST_MODE: {
2562 String enabledStr = getNextArg();
2563 if (ENABLE.equals(enabledStr)) {
2564 CallComposerPictureManager.sTestMode = true;
2565 } else if (DISABLE.equals(enabledStr)) {
2566 CallComposerPictureManager.sTestMode = false;
2567 } else if (QUERY.equals(enabledStr)) {
2568 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2569 } else {
2570 onHelpCallComposer();
2571 return 1;
2572 }
2573 break;
2574 }
2575 case CALL_COMPOSER_SIMULATE_CALL: {
2576 int subscriptionId = Integer.valueOf(getNextArg());
2577 String uuidString = getNextArg();
2578 UUID uuid = UUID.fromString(uuidString);
2579 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2580 Binder.withCleanCallingIdentity(() -> {
2581 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2582 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2583 });
2584 try {
2585 Uri uri = storageUriFuture.get();
2586 getOutPrintWriter().println(String.valueOf(uri));
2587 } catch (Exception e) {
2588 throw new RuntimeException(e);
2589 }
2590 break;
2591 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002592 case CALL_COMPOSER_USER_SETTING: {
2593 try {
2594 int subscriptionId = Integer.valueOf(getNextArg());
2595 String enabledStr = getNextArg();
2596 if (ENABLE.equals(enabledStr)) {
2597 mInterface.setCallComposerStatus(subscriptionId,
2598 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2599 } else if (DISABLE.equals(enabledStr)) {
2600 mInterface.setCallComposerStatus(subscriptionId,
2601 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2602 } else if (QUERY.equals(enabledStr)) {
2603 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2604 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2605 } else {
2606 onHelpCallComposer();
2607 return 1;
2608 }
2609 } catch (RemoteException e) {
2610 e.printStackTrace(getOutPrintWriter());
2611 return 1;
2612 }
2613 break;
2614 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002615 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002616 return 0;
2617 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002618
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002619 private int handleHasCarrierPrivilegesCommand() {
2620 String packageName = getNextArgRequired();
2621
2622 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002623 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002624 try {
2625 hasCarrierPrivileges =
2626 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2627 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2628 } catch (RemoteException e) {
2629 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2630 getErrPrintWriter().println("Exception: " + e.getMessage());
2631 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002632 } finally {
2633 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002634 }
2635
2636 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002637 return 0;
2638 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002639
2640 private int handleAllowedNetworkTypesCommand(String command) {
2641 if (!checkShellUid()) {
2642 return -1;
2643 }
2644
2645 PrintWriter errPw = getErrPrintWriter();
2646 String tag = command + ": ";
2647 String opt;
2648 int subId = -1;
2649 Log.v(LOG_TAG, command + " start");
2650
2651 while ((opt = getNextOption()) != null) {
2652 if (opt.equals("-s")) {
2653 try {
2654 subId = slotStringToSubId(tag, getNextArgRequired());
2655 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2656 errPw.println(tag + "No valid subscription found.");
2657 return -1;
2658 }
2659 } catch (IllegalArgumentException e) {
2660 // Missing slot id
2661 errPw.println(tag + "SLOT_ID expected after -s.");
2662 return -1;
2663 }
2664 } else {
2665 errPw.println(tag + "Unknown option " + opt);
2666 return -1;
2667 }
2668 }
2669
2670 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2671 return handleGetAllowedNetworkTypesCommand(subId);
2672 }
2673 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2674 return handleSetAllowedNetworkTypesCommand(subId);
2675 }
2676 return -1;
2677 }
2678
2679 private int handleGetAllowedNetworkTypesCommand(int subId) {
2680 PrintWriter errPw = getErrPrintWriter();
2681
2682 long result = -1;
2683 try {
2684 if (mInterface != null) {
2685 result = mInterface.getAllowedNetworkTypesForReason(subId,
2686 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2687 } else {
2688 throw new IllegalStateException("telephony service is null.");
2689 }
2690 } catch (RemoteException e) {
2691 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2692 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2693 return -1;
2694 }
2695
2696 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2697 return 0;
2698 }
2699
2700 private int handleSetAllowedNetworkTypesCommand(int subId) {
2701 PrintWriter errPw = getErrPrintWriter();
2702
2703 String bitmaskString = getNextArg();
2704 if (TextUtils.isEmpty(bitmaskString)) {
2705 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2706 return -1;
2707 }
2708 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2709 if (allowedNetworkTypes < 0) {
2710 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2711 return -1;
2712 }
2713 boolean result = false;
2714 try {
2715 if (mInterface != null) {
2716 result = mInterface.setAllowedNetworkTypesForReason(subId,
2717 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2718 } else {
2719 throw new IllegalStateException("telephony service is null.");
2720 }
2721 } catch (RemoteException e) {
2722 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2723 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2724 return -1;
2725 }
2726
2727 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2728 if (result) {
2729 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2730 }
2731 getOutPrintWriter().println(resultMessage);
2732 return 0;
2733 }
2734
2735 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2736 if (TextUtils.isEmpty(bitmaskString)) {
2737 return -1;
2738 }
2739 if (VDBG) {
2740 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2741 + ", length: " + bitmaskString.length());
2742 }
2743 try {
2744 return Long.parseLong(bitmaskString, 2);
2745 } catch (NumberFormatException e) {
2746 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2747 return -1;
2748 }
2749 }
jimsun38340bf2021-10-26 15:01:23 +08002750
2751 private int handleRadioSetModemServiceCommand() {
2752 PrintWriter errPw = getErrPrintWriter();
2753 String serviceName = null;
2754
2755 String opt;
2756 while ((opt = getNextOption()) != null) {
2757 switch (opt) {
2758 case "-s": {
2759 serviceName = getNextArgRequired();
2760 break;
2761 }
2762 }
2763 }
2764
2765 try {
2766 boolean result = mInterface.setModemService(serviceName);
2767 if (VDBG) {
2768 Log.v(LOG_TAG,
2769 "RadioSetModemService " + serviceName + ", result = " + result);
2770 }
2771 getOutPrintWriter().println(result);
2772 } catch (RemoteException e) {
2773 Log.w(LOG_TAG,
2774 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2775 errPw.println("Exception: " + e.getMessage());
2776 return -1;
2777 }
2778 return 0;
2779 }
2780
2781 private int handleRadioGetModemServiceCommand() {
2782 PrintWriter errPw = getErrPrintWriter();
2783 String result;
2784
2785 try {
2786 result = mInterface.getModemService();
2787 getOutPrintWriter().println(result);
2788 } catch (RemoteException e) {
2789 errPw.println("Exception: " + e.getMessage());
2790 return -1;
2791 }
2792 if (VDBG) {
2793 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2794 }
2795 return 0;
2796 }
2797
2798 private int handleRadioCommand() {
2799 String arg = getNextArg();
2800 if (arg == null) {
2801 onHelpRadio();
2802 return 0;
2803 }
2804
2805 switch (arg) {
2806 case RADIO_SET_MODEM_SERVICE:
2807 return handleRadioSetModemServiceCommand();
2808
2809 case RADIO_GET_MODEM_SERVICE:
2810 return handleRadioGetModemServiceCommand();
2811 }
2812
2813 return -1;
2814 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002815}