blob: bde719faee4ccebc174663876c5711833189290f [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,
Hyunhofa4ac962022-01-11 12:44:19 +0000253 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000254 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,
Hyunhofa4ac962022-01-11 12:44:19 +0000259 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000260 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);
jimsunf0c52e22021-12-23 09:11:36 +0800326 case RADIO_SUBCOMMAND:
327 return handleRadioCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700328 default: {
329 return handleDefaultCommands(cmd);
330 }
331 }
332 }
333
334 @Override
335 public void onHelp() {
336 PrintWriter pw = getOutPrintWriter();
337 pw.println("Telephony Commands:");
338 pw.println(" help");
339 pw.println(" Print this help text.");
340 pw.println(" ims");
341 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800342 pw.println(" uce");
343 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800344 pw.println(" emergency-number-test-mode");
345 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700346 pw.println(" end-block-suppression");
347 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800348 pw.println(" data");
349 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100350 pw.println(" cc");
351 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700352 pw.println(" gba");
353 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000354 pw.println(" src");
355 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000356 pw.println(" restart-modem");
357 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000358 pw.println(" unattended-reboot");
359 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800360 pw.println(" has-carrier-privileges [package]");
361 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800362 pw.println(" get-allowed-network-types-for-users");
363 pw.println(" Get the Allowed Network Types.");
364 pw.println(" set-allowed-network-types-for-users");
365 pw.println(" Set the Allowed Network Types.");
jimsun38340bf2021-10-26 15:01:23 +0800366 pw.println(" radio");
367 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700368 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800369 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800370 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700371 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800372 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100373 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700374 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000375 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800376 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700377 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800378 onHelpAllowedNetworkTypes();
jimsun38340bf2021-10-26 15:01:23 +0800379 onHelpRadio();
Tyler Gunn92479152021-01-20 16:30:10 -0800380 }
381
382 private void onHelpD2D() {
383 PrintWriter pw = getOutPrintWriter();
384 pw.println("D2D Comms Commands:");
385 pw.println(" d2d send TYPE VALUE");
386 pw.println(" Sends a D2D message of specified type and value.");
387 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
388 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
389 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
390 MESSAGE_CALL_AUDIO_CODEC));
391 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
392 + Communicator.messageToString(
393 MESSAGE_DEVICE_BATTERY_STATE));
394 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
395 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800396 pw.println(" d2d transport TYPE");
397 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
398 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700399 pw.println(" d2d set-device-support true/default");
400 pw.println(" true - forces device support to be enabled for D2D.");
401 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
402 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700403 }
404
Nazanin014f41e2021-05-06 17:26:31 -0700405 private void onHelpBarring() {
406 PrintWriter pw = getOutPrintWriter();
407 pw.println("Barring Commands:");
408 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
409 + " -t CONDITIONAL_BARRING_TIME_SECS");
410 pw.println(" Notifies of a barring info change for the specified slot id.");
411 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
412 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
413 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
414 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
415 }
416
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700417 private void onHelpIms() {
418 PrintWriter pw = getOutPrintWriter();
419 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800420 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700421 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
422 pw.println(" ImsService. Options are:");
423 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
424 pw.println(" is specified, it will choose the default voice SIM slot.");
425 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
426 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800427 pw.println(" -f: Set the feature that this override if for, if no option is");
428 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700429 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
430 pw.println(" Gets the package name of the currently defined ImsService.");
431 pw.println(" Options are:");
432 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
433 pw.println(" is specified, it will choose the default voice SIM slot.");
434 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000435 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800436 pw.println(" -f: The feature type that the query will be requested for. If none is");
437 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800438 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
439 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
440 pw.println(" configuration overrides. Options are:");
441 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
442 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700443 pw.println(" ims enable [-s SLOT_ID]");
444 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
445 pw.println(" if none is specified.");
446 pw.println(" ims disable [-s SLOT_ID]");
447 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
448 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700449 pw.println(" ims conference-event-package [enable/disable]");
450 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700451 }
452
James.cf Linbcdf8b32021-01-14 16:44:13 +0800453 private void onHelpUce() {
454 PrintWriter pw = getOutPrintWriter();
455 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800456 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
457 pw.println(" Get the EAB contacts from the EAB database.");
458 pw.println(" Options are:");
459 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
460 pw.println(" Expected output format :");
461 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800462 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
463 pw.println(" Remove the EAB contacts from the EAB database.");
464 pw.println(" Options are:");
465 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
466 pw.println(" is specified, it will choose the default voice SIM slot.");
467 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800468 pw.println(" uce get-device-enabled");
469 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
470 pw.println(" uce set-device-enabled true|false");
471 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
472 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000473 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
474 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
475 pw.println(" Options are:");
476 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
477 pw.println(" is specified, it will choose the default voice SIM slot.");
478 pw.println(" add [CAPABILITY]: add a new capability");
479 pw.println(" remove [CAPABILITY]: remove a capability");
480 pw.println(" clear: clear all capability overrides");
481 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
482 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
483 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
484 pw.println(" chatbot_sa, chatbot_role] as well as full length");
485 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
486 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
487 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
488 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800489 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
490 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800491 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
492 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800493 }
494
Hall Liud892bec2018-11-30 14:51:45 -0800495 private void onHelpNumberVerification() {
496 PrintWriter pw = getOutPrintWriter();
497 pw.println("Number verification commands");
498 pw.println(" numverify override-package PACKAGE_NAME;");
499 pw.println(" Set the authorized package for number verification.");
500 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800501 pw.println(" numverify fake-call NUMBER;");
502 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
503 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800504 }
505
Jack Nudelman644b91a2021-03-12 14:09:48 -0800506 private void onHelpThermalMitigation() {
507 PrintWriter pw = getOutPrintWriter();
508 pw.println("Thermal mitigation commands");
509 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
510 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
511 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
512 pw.println(" Remove the package from one of the authorized packages for thermal "
513 + "mitigation.");
514 }
515
Jordan Liu0ccee222021-04-27 11:55:13 -0700516 private void onHelpDisableOrEnablePhysicalSubscription() {
517 PrintWriter pw = getOutPrintWriter();
518 pw.println("Disable or enable a physical subscription");
519 pw.println(" disable-physical-subscription SUB_ID");
520 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
521 pw.println(" enable-physical-subscription SUB_ID");
522 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
523 }
524
Shuo Qianf5125122019-12-16 17:03:07 -0800525 private void onHelpDataTestMode() {
526 PrintWriter pw = getOutPrintWriter();
527 pw.println("Mobile Data Test Mode Commands:");
528 pw.println(" data enable: enable mobile data connectivity");
529 pw.println(" data disable: disable mobile data connectivity");
530 }
531
sqian9d4df8b2019-01-15 18:32:07 -0800532 private void onHelpEmergencyNumber() {
533 PrintWriter pw = getOutPrintWriter();
534 pw.println("Emergency Number Test Mode Commands:");
535 pw.println(" emergency-number-test-mode ");
536 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
537 + " the test mode");
538 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700539 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800540 pw.println(" -c: clear the emergency number list in the test mode.");
541 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700542 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800543 pw.println(" -p: get the full emergency number list in the test mode.");
544 }
545
Shuo Qian489d9282020-07-09 11:30:03 -0700546 private void onHelpEndBlockSupperssion() {
547 PrintWriter pw = getOutPrintWriter();
548 pw.println("End Block Suppression command:");
549 pw.println(" end-block-suppression: disable suppressing blocking by contact");
550 pw.println(" with emergency services.");
551 }
552
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100553 private void onHelpCc() {
554 PrintWriter pw = getOutPrintWriter();
555 pw.println("Carrier Config Commands:");
556 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
557 pw.println(" Print carrier config values.");
558 pw.println(" Options are:");
559 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
560 pw.println(" is specified, it will choose the default voice SIM slot.");
561 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
562 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100563 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100564 pw.println(" Set carrier config KEY to NEW_VALUE.");
565 pw.println(" Options are:");
566 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
567 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100568 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100569 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
570 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
571 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
572 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
573 pw.println(" cc clear-values [-s SLOT_ID]");
574 pw.println(" Clear all carrier override values that has previously been set");
575 pw.println(" with set-value");
576 pw.println(" Options are:");
577 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
578 pw.println(" is specified, it will choose the default voice SIM slot.");
579 }
580
Hui Wang641e81c2020-10-12 12:14:23 -0700581 private void onHelpGba() {
582 PrintWriter pw = getOutPrintWriter();
583 pw.println("Gba Commands:");
584 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
585 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
586 pw.println(" Options are:");
587 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
588 pw.println(" is specified, it will choose the default voice SIM slot.");
589 pw.println(" gba get-service [-s SLOT_ID]");
590 pw.println(" Gets the package name of the currently defined GbaService.");
591 pw.println(" Options are:");
592 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
593 pw.println(" is specified, it will choose the default voice SIM slot.");
594 pw.println(" gba set-release [-s SLOT_ID] n");
595 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
596 pw.println(" Do not release/unbind if n is -1.");
597 pw.println(" Options are:");
598 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
599 pw.println(" is specified, it will choose the default voice SIM slot.");
600 pw.println(" gba get-release [-s SLOT_ID]");
601 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
602 pw.println(" Options are:");
603 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
604 pw.println(" is specified, it will choose the default voice SIM slot.");
605 }
606
Hui Wang761a6682020-10-31 05:12:53 +0000607 private void onHelpSrc() {
608 PrintWriter pw = getOutPrintWriter();
609 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800610 pw.println(" src set-test-enabled true|false");
611 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
612 pw.println(" The value could be true, false, or null(undefined).");
613 pw.println(" src get-test-enabled");
614 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000615 pw.println(" src set-device-enabled true|false|null");
616 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
617 pw.println(" The value could be true, false, or null(undefined).");
618 pw.println(" src get-device-enabled");
619 pw.println(" Gets the device config for RCS VoLTE single registration.");
620 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
621 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
622 pw.println(" The value could be true, false, or null(undefined).");
623 pw.println(" Options are:");
624 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
625 pw.println(" is specified, it will choose the default voice SIM slot.");
626 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
627 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
628 pw.println(" Options are:");
629 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
630 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800631 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
632 pw.println(" Sets ims feature validation result.");
633 pw.println(" The value could be true, false, or null(undefined).");
634 pw.println(" Options are:");
635 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
636 pw.println(" is specified, it will choose the default voice SIM slot.");
637 pw.println(" src get-feature-validation [-s SLOT_ID]");
638 pw.println(" Gets ims feature validation override value.");
639 pw.println(" Options are:");
640 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
641 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000642 }
643
SongFerngWang98dd5992021-05-13 17:50:00 +0800644 private void onHelpAllowedNetworkTypes() {
645 PrintWriter pw = getOutPrintWriter();
646 pw.println("Allowed Network Types Commands:");
647 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
648 pw.println(" Print allowed network types value.");
649 pw.println(" Options are:");
650 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
651 pw.println(" option is specified, it will choose the default voice SIM slot.");
652 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
653 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
654 pw.println(" Options are:");
655 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
656 pw.println(" option is specified, it will choose the default voice SIM slot.");
657 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
658 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
659 pw.println(" at TelephonyManager.java");
660 pw.println(" For example:");
661 pw.println(" NR only : 10000000000000000000");
662 pw.println(" NR|LTE : 11000001000000000000");
663 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
664 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
665 pw.println(" LTE only : 01000001000000000000");
666 }
667
jimsun38340bf2021-10-26 15:01:23 +0800668 private void onHelpRadio() {
669 PrintWriter pw = getOutPrintWriter();
670 pw.println("Radio Commands:");
671 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
672 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
673 pw.println(" to be the bound. Options are:");
674 pw.println(" -s: the service name that the modem service should be bound for.");
675 pw.println(" If no option is specified, it will bind to the default.");
676 pw.println(" radio get-modem-service");
677 pw.println(" Gets the service name of the currently defined modem service.");
678 pw.println(" If it is binding to default, 'default' returns.");
679 pw.println(" If it doesn't bind to any modem service for some reasons,");
680 pw.println(" the result would be 'unknown'.");
681 }
682
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700683 private int handleImsCommand() {
684 String arg = getNextArg();
685 if (arg == null) {
686 onHelpIms();
687 return 0;
688 }
689
690 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800691 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700692 return handleImsSetServiceCommand();
693 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800694 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700695 return handleImsGetServiceCommand();
696 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800697 case IMS_CLEAR_SERVICE_OVERRIDE: {
698 return handleImsClearCarrierServiceCommand();
699 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800700 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700701 return handleEnableIms();
702 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800703 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700704 return handleDisableIms();
705 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700706 case IMS_CEP: {
707 return handleCepChange();
708 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700709 }
710
711 return -1;
712 }
713
Shuo Qianf5125122019-12-16 17:03:07 -0800714 private int handleDataTestModeCommand() {
715 PrintWriter errPw = getErrPrintWriter();
716 String arg = getNextArgRequired();
717 if (arg == null) {
718 onHelpDataTestMode();
719 return 0;
720 }
721 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800722 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800723 try {
724 mInterface.enableDataConnectivity();
725 } catch (RemoteException ex) {
726 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
727 errPw.println("Exception: " + ex.getMessage());
728 return -1;
729 }
730 break;
731 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800732 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800733 try {
734 mInterface.disableDataConnectivity();
735 } catch (RemoteException ex) {
736 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
737 errPw.println("Exception: " + ex.getMessage());
738 return -1;
739 }
740 break;
741 }
742 default:
743 onHelpDataTestMode();
744 break;
745 }
746 return 0;
747 }
748
Shuo Qianccbaf742021-02-22 18:32:21 -0800749 private int handleEmergencyCallbackModeCommand() {
750 PrintWriter errPw = getErrPrintWriter();
751 try {
752 mInterface.startEmergencyCallbackMode();
753 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
754 } catch (RemoteException ex) {
755 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
756 errPw.println("Exception: " + ex.getMessage());
757 return -1;
758 }
759 return 0;
760 }
761
sqian9d4df8b2019-01-15 18:32:07 -0800762 private int handleEmergencyNumberTestModeCommand() {
763 PrintWriter errPw = getErrPrintWriter();
764 String opt = getNextOption();
765 if (opt == null) {
766 onHelpEmergencyNumber();
767 return 0;
768 }
769
770 switch (opt) {
771 case "-a": {
772 String emergencyNumberCmd = getNextArgRequired();
773 if (emergencyNumberCmd == null
774 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700775 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800776 + " to be specified after -a in the command ");
777 return -1;
778 }
779 try {
780 mInterface.updateEmergencyNumberListTestMode(
781 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
782 new EmergencyNumber(emergencyNumberCmd, "", "",
783 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
784 new ArrayList<String>(),
785 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
786 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
787 } catch (RemoteException ex) {
788 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
789 + ", error " + ex.getMessage());
790 errPw.println("Exception: " + ex.getMessage());
791 return -1;
792 }
793 break;
794 }
795 case "-c": {
796 try {
797 mInterface.updateEmergencyNumberListTestMode(
798 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
799 } catch (RemoteException ex) {
800 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
801 errPw.println("Exception: " + ex.getMessage());
802 return -1;
803 }
804 break;
805 }
806 case "-r": {
807 String emergencyNumberCmd = getNextArgRequired();
808 if (emergencyNumberCmd == null
809 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700810 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800811 + " to be specified after -r in the command ");
812 return -1;
813 }
814 try {
815 mInterface.updateEmergencyNumberListTestMode(
816 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
817 new EmergencyNumber(emergencyNumberCmd, "", "",
818 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
819 new ArrayList<String>(),
820 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
821 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
822 } catch (RemoteException ex) {
823 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
824 + ", error " + ex.getMessage());
825 errPw.println("Exception: " + ex.getMessage());
826 return -1;
827 }
828 break;
829 }
830 case "-p": {
831 try {
832 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
833 } catch (RemoteException ex) {
834 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
835 errPw.println("Exception: " + ex.getMessage());
836 return -1;
837 }
838 break;
839 }
840 default:
841 onHelpEmergencyNumber();
842 break;
843 }
844 return 0;
845 }
846
Hall Liud892bec2018-11-30 14:51:45 -0800847 private int handleNumberVerificationCommand() {
848 String arg = getNextArg();
849 if (arg == null) {
850 onHelpNumberVerification();
851 return 0;
852 }
853
Hall Liuca5af3a2018-12-04 16:58:23 -0800854 if (!checkShellUid()) {
855 return -1;
856 }
857
Hall Liud892bec2018-11-30 14:51:45 -0800858 switch (arg) {
859 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800860 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
861 return 0;
862 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800863 case NUMBER_VERIFICATION_FAKE_CALL: {
864 boolean val = NumberVerificationManager.getInstance()
865 .checkIncomingCall(getNextArg());
866 getOutPrintWriter().println(val ? "1" : "0");
867 return 0;
868 }
Hall Liud892bec2018-11-30 14:51:45 -0800869 }
870
871 return -1;
872 }
873
Jordan Liu0ccee222021-04-27 11:55:13 -0700874 private boolean subIsEsim(int subId) {
875 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
876 if (info != null) {
877 return info.isEmbedded();
878 }
879 return false;
880 }
881
882 private int handleEnablePhysicalSubscription(boolean enable) {
883 PrintWriter errPw = getErrPrintWriter();
884 int subId = 0;
885 try {
886 subId = Integer.parseInt(getNextArgRequired());
887 } catch (NumberFormatException e) {
888 errPw.println((enable ? "enable" : "disable")
889 + "-physical-subscription requires an integer as a subId.");
890 return -1;
891 }
892 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
893 // non user build.
894 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
895 errPw.println("cc: Permission denied.");
896 return -1;
897 }
898 // Verify that the subId represents a physical sub
899 if (subIsEsim(subId)) {
900 errPw.println("SubId " + subId + " is not for a physical subscription");
901 return -1;
902 }
903 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
904 + " physical subscription with subId=" + subId);
905 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
906 return 0;
907 }
908
Jack Nudelman644b91a2021-03-12 14:09:48 -0800909 private int handleThermalMitigationCommand() {
910 String arg = getNextArg();
911 String packageName = getNextArg();
912 if (arg == null || packageName == null) {
913 onHelpThermalMitigation();
914 return 0;
915 }
916
917 if (!checkShellUid()) {
918 return -1;
919 }
920
921 switch (arg) {
922 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
923 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
924 return 0;
925 }
926 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
927 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
928 mContext);
929 return 0;
930 }
931 default:
932 onHelpThermalMitigation();
933 }
934
935 return -1;
936
937 }
938
Tyler Gunn92479152021-01-20 16:30:10 -0800939 private int handleD2dCommand() {
940 String arg = getNextArg();
941 if (arg == null) {
942 onHelpD2D();
943 return 0;
944 }
945
946 switch (arg) {
947 case D2D_SEND: {
948 return handleD2dSendCommand();
949 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800950 case D2D_TRANSPORT: {
951 return handleD2dTransportCommand();
952 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700953 case D2D_SET_DEVICE_SUPPORT: {
954 return handleD2dDeviceSupportedCommand();
955 }
Tyler Gunn92479152021-01-20 16:30:10 -0800956 }
957
958 return -1;
959 }
960
961 private int handleD2dSendCommand() {
962 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800963 int messageType = -1;
964 int messageValue = -1;
965
Tyler Gunn92479152021-01-20 16:30:10 -0800966 String arg = getNextArg();
967 if (arg == null) {
968 onHelpD2D();
969 return 0;
970 }
971 try {
972 messageType = Integer.parseInt(arg);
973 } catch (NumberFormatException e) {
974 errPw.println("message type must be a valid integer");
975 return -1;
976 }
977
978 arg = getNextArg();
979 if (arg == null) {
980 onHelpD2D();
981 return 0;
982 }
983 try {
984 messageValue = Integer.parseInt(arg);
985 } catch (NumberFormatException e) {
986 errPw.println("message value must be a valid integer");
987 return -1;
988 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800989
Tyler Gunn92479152021-01-20 16:30:10 -0800990 try {
991 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
992 } catch (RemoteException e) {
993 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
994 errPw.println("Exception: " + e.getMessage());
995 return -1;
996 }
997
998 return 0;
999 }
1000
Tyler Gunnbabbda02021-02-10 11:05:02 -08001001 private int handleD2dTransportCommand() {
1002 PrintWriter errPw = getErrPrintWriter();
1003
1004 String arg = getNextArg();
1005 if (arg == null) {
1006 onHelpD2D();
1007 return 0;
1008 }
1009
1010 try {
1011 mInterface.setActiveDeviceToDeviceTransport(arg);
1012 } catch (RemoteException e) {
1013 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1014 errPw.println("Exception: " + e.getMessage());
1015 return -1;
1016 }
1017 return 0;
1018 }
Nazanin014f41e2021-05-06 17:26:31 -07001019 private int handleBarringCommand() {
1020 String arg = getNextArg();
1021 if (arg == null) {
1022 onHelpBarring();
1023 return 0;
1024 }
1025
1026 switch (arg) {
1027 case BARRING_SEND_INFO: {
1028 return handleBarringSendCommand();
1029 }
1030 }
1031 return -1;
1032 }
1033
1034 private int handleBarringSendCommand() {
1035 PrintWriter errPw = getErrPrintWriter();
1036 int slotId = getDefaultSlot();
1037 int subId = SubscriptionManager.getSubId(slotId)[0];
1038 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1039 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1040 boolean isConditionallyBarred = false;
1041 int conditionalBarringTimeSeconds = 0;
1042
1043 String opt;
1044 while ((opt = getNextOption()) != null) {
1045 switch (opt) {
1046 case "-s": {
1047 try {
1048 slotId = Integer.parseInt(getNextArgRequired());
1049 subId = SubscriptionManager.getSubId(slotId)[0];
1050 } catch (NumberFormatException e) {
1051 errPw.println("barring send requires an integer as a SLOT_ID.");
1052 return -1;
1053 }
1054 break;
1055 }
1056 case "-b": {
1057 try {
1058 barringType = Integer.parseInt(getNextArgRequired());
1059 if (barringType < -1 || barringType > 2) {
1060 throw new NumberFormatException();
1061 }
1062
1063 } catch (NumberFormatException e) {
1064 errPw.println("barring send requires an integer in range [-1,2] as "
1065 + "a BARRING_TYPE.");
1066 return -1;
1067 }
1068 break;
1069 }
1070 case "-c": {
1071 try {
1072 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1073 } catch (Exception e) {
1074 errPw.println("barring send requires a boolean after -c indicating"
1075 + " conditional barring");
1076 return -1;
1077 }
1078 break;
1079 }
1080 case "-t": {
1081 try {
1082 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1083 } catch (NumberFormatException e) {
1084 errPw.println("barring send requires an integer for time of barring"
1085 + " in seconds after -t for conditional barring");
1086 return -1;
1087 }
1088 break;
1089 }
1090 }
1091 }
1092 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1093 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1094 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1095 barringServiceInfos.append(0, bsi);
1096 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1097 try {
1098 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1099 } catch (Exception e) {
1100 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1101 errPw.println("Exception: " + e.getMessage());
1102 return -1;
1103 }
1104 return 0;
1105 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001106
Tyler Gunnd4575212021-05-03 14:46:49 -07001107 private int handleD2dDeviceSupportedCommand() {
1108 PrintWriter errPw = getErrPrintWriter();
1109
1110 String arg = getNextArg();
1111 if (arg == null) {
1112 onHelpD2D();
1113 return 0;
1114 }
1115
1116 boolean isEnabled = "true".equals(arg.toLowerCase());
1117 try {
1118 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1119 } catch (RemoteException e) {
1120 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1121 errPw.println("Exception: " + e.getMessage());
1122 return -1;
1123 }
1124 return 0;
1125 }
1126
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001127 // ims set-ims-service
1128 private int handleImsSetServiceCommand() {
1129 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001130 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001131 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001132 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001133
1134 String opt;
1135 while ((opt = getNextOption()) != null) {
1136 switch (opt) {
1137 case "-s": {
1138 try {
1139 slotId = Integer.parseInt(getNextArgRequired());
1140 } catch (NumberFormatException e) {
1141 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1142 return -1;
1143 }
1144 break;
1145 }
1146 case "-c": {
1147 isCarrierService = true;
1148 break;
1149 }
1150 case "-d": {
1151 isCarrierService = false;
1152 break;
1153 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001154 case "-f": {
1155 String featureString = getNextArgRequired();
1156 String[] features = featureString.split(",");
1157 for (int i = 0; i < features.length; i++) {
1158 try {
1159 Integer result = Integer.parseInt(features[i]);
1160 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1161 || result >= ImsFeature.FEATURE_MAX) {
1162 errPw.println("ims set-ims-service -f " + result
1163 + " is an invalid feature.");
1164 return -1;
1165 }
1166 featuresList.add(result);
1167 } catch (NumberFormatException e) {
1168 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1169 + " as an integer.");
1170 return -1;
1171 }
1172 }
1173 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001174 }
1175 }
1176 // Mandatory param, either -c or -d
1177 if (isCarrierService == null) {
1178 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1179 return -1;
1180 }
1181
1182 String packageName = getNextArg();
1183
1184 try {
1185 if (packageName == null) {
1186 packageName = "";
1187 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001188 int[] featureArray = new int[featuresList.size()];
1189 for (int i = 0; i < featuresList.size(); i++) {
1190 featureArray[i] = featuresList.get(i);
1191 }
1192 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1193 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001194 if (VDBG) {
1195 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001196 + (isCarrierService ? "-c " : "-d ")
1197 + "-f " + featuresList + " "
1198 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001199 }
1200 getOutPrintWriter().println(result);
1201 } catch (RemoteException e) {
1202 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001203 + (isCarrierService ? "-c " : "-d ")
1204 + "-f " + featuresList + " "
1205 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001206 errPw.println("Exception: " + e.getMessage());
1207 return -1;
1208 }
1209 return 0;
1210 }
1211
Brad Ebinger999d3302020-11-25 14:31:39 -08001212 // ims clear-ims-service-override
1213 private int handleImsClearCarrierServiceCommand() {
1214 PrintWriter errPw = getErrPrintWriter();
1215 int slotId = getDefaultSlot();
1216
1217 String opt;
1218 while ((opt = getNextOption()) != null) {
1219 switch (opt) {
1220 case "-s": {
1221 try {
1222 slotId = Integer.parseInt(getNextArgRequired());
1223 } catch (NumberFormatException e) {
1224 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1225 return -1;
1226 }
1227 break;
1228 }
1229 }
1230 }
1231
1232 try {
1233 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1234 if (VDBG) {
1235 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1236 + ", result=" + result);
1237 }
1238 getOutPrintWriter().println(result);
1239 } catch (RemoteException e) {
1240 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1241 + ", error" + e.getMessage());
1242 errPw.println("Exception: " + e.getMessage());
1243 return -1;
1244 }
1245 return 0;
1246 }
1247
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001248 // ims get-ims-service
1249 private int handleImsGetServiceCommand() {
1250 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001251 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001252 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001253 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001254
1255 String opt;
1256 while ((opt = getNextOption()) != null) {
1257 switch (opt) {
1258 case "-s": {
1259 try {
1260 slotId = Integer.parseInt(getNextArgRequired());
1261 } catch (NumberFormatException e) {
1262 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1263 return -1;
1264 }
1265 break;
1266 }
1267 case "-c": {
1268 isCarrierService = true;
1269 break;
1270 }
1271 case "-d": {
1272 isCarrierService = false;
1273 break;
1274 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001275 case "-f": {
1276 try {
1277 featureType = Integer.parseInt(getNextArg());
1278 } catch (NumberFormatException e) {
1279 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1280 return -1;
1281 }
1282 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1283 || featureType >= ImsFeature.FEATURE_MAX) {
1284 errPw.println("ims get-ims-service -f invalid feature.");
1285 return -1;
1286 }
1287 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001288 }
1289 }
1290 // Mandatory param, either -c or -d
1291 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001292 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001293 return -1;
1294 }
1295
1296 String result;
1297 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001298 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001299 } catch (RemoteException e) {
1300 return -1;
1301 }
1302 if (VDBG) {
1303 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001304 + (isCarrierService ? "-c " : "-d ")
1305 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1306 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001307 }
1308 getOutPrintWriter().println(result);
1309 return 0;
1310 }
1311
1312 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001313 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001314 String opt;
1315 while ((opt = getNextOption()) != null) {
1316 switch (opt) {
1317 case "-s": {
1318 try {
1319 slotId = Integer.parseInt(getNextArgRequired());
1320 } catch (NumberFormatException e) {
1321 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1322 return -1;
1323 }
1324 break;
1325 }
1326 }
1327 }
1328 try {
1329 mInterface.enableIms(slotId);
1330 } catch (RemoteException e) {
1331 return -1;
1332 }
1333 if (VDBG) {
1334 Log.v(LOG_TAG, "ims enable -s " + slotId);
1335 }
1336 return 0;
1337 }
1338
1339 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001340 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001341 String opt;
1342 while ((opt = getNextOption()) != null) {
1343 switch (opt) {
1344 case "-s": {
1345 try {
1346 slotId = Integer.parseInt(getNextArgRequired());
1347 } catch (NumberFormatException e) {
1348 getErrPrintWriter().println(
1349 "ims disable requires an integer as a SLOT_ID.");
1350 return -1;
1351 }
1352 break;
1353 }
1354 }
1355 }
1356 try {
1357 mInterface.disableIms(slotId);
1358 } catch (RemoteException e) {
1359 return -1;
1360 }
1361 if (VDBG) {
1362 Log.v(LOG_TAG, "ims disable -s " + slotId);
1363 }
1364 return 0;
1365 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001366
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001367 private int handleCepChange() {
1368 Log.i(LOG_TAG, "handleCepChange");
1369 String opt = getNextArg();
1370 if (opt == null) {
1371 return -1;
1372 }
1373 boolean isCepEnabled = opt.equals("enable");
1374
1375 try {
1376 mInterface.setCepEnabled(isCepEnabled);
1377 } catch (RemoteException e) {
1378 return -1;
1379 }
1380 return 0;
1381 }
1382
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001383 private int getDefaultSlot() {
1384 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1385 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1386 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1387 // If there is no default, default to slot 0.
1388 slotId = DEFAULT_PHONE_ID;
1389 }
1390 return slotId;
1391 }
sqian2fff4a32018-11-05 14:18:37 -08001392
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001393 // Parse options related to Carrier Config Commands.
1394 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001395 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001396 CcOptionParseResult result = new CcOptionParseResult();
1397 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1398 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001399
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001400 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001401 while ((opt = getNextOption()) != null) {
1402 switch (opt) {
1403 case "-s": {
1404 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001405 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1406 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1407 errPw.println(tag + "No valid subscription found.");
1408 return null;
1409 }
1410
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001411 } catch (IllegalArgumentException e) {
1412 // Missing slot id
1413 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001414 return null;
1415 }
1416 break;
1417 }
1418 case "-p": {
1419 if (allowOptionPersistent) {
1420 result.mPersistent = true;
1421 } else {
1422 errPw.println(tag + "Unexpected option " + opt);
1423 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001424 }
1425 break;
1426 }
1427 default: {
1428 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001429 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001430 }
1431 }
1432 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001433 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001434 }
1435
1436 private int slotStringToSubId(String tag, String slotString) {
1437 int slotId = -1;
1438 try {
1439 slotId = Integer.parseInt(slotString);
1440 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001441 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1442 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1443 }
1444
1445 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001446 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1447 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1448 }
1449
Qiong Liuf25799b2020-09-10 10:13:46 +08001450 Phone phone = PhoneFactory.getPhone(slotId);
1451 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001452 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1453 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1454 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001455 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001456 }
1457
Hall Liud892bec2018-11-30 14:51:45 -08001458 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001459 // adb can run as root or as shell, depending on whether the device is rooted.
1460 return Binder.getCallingUid() == Process.SHELL_UID
1461 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001462 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001463
1464 private int handleCcCommand() {
1465 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1466 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001467 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001468 getErrPrintWriter().println("cc: Permission denied.");
1469 return -1;
1470 }
1471
1472 String arg = getNextArg();
1473 if (arg == null) {
1474 onHelpCc();
1475 return 0;
1476 }
1477
1478 switch (arg) {
1479 case CC_GET_VALUE: {
1480 return handleCcGetValue();
1481 }
1482 case CC_SET_VALUE: {
1483 return handleCcSetValue();
1484 }
1485 case CC_CLEAR_VALUES: {
1486 return handleCcClearValues();
1487 }
1488 default: {
1489 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1490 }
1491 }
1492 return -1;
1493 }
1494
1495 // cc get-value
1496 private int handleCcGetValue() {
1497 PrintWriter errPw = getErrPrintWriter();
1498 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1499 String key = null;
1500
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001501 // Parse all options
1502 CcOptionParseResult options = parseCcOptions(tag, false);
1503 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001504 return -1;
1505 }
1506
1507 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001508 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001509 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001510 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001511 return -1;
1512 }
1513
1514 // Get the key.
1515 key = getNextArg();
1516 if (key != null) {
1517 // A key was provided. Verify if it is a valid key
1518 if (!bundle.containsKey(key)) {
1519 errPw.println(tag + key + " is not a valid key.");
1520 return -1;
1521 }
1522
1523 // Print the carrier config value for key.
1524 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1525 } else {
1526 // No key provided. Show all values.
1527 // Iterate over a sorted list of all carrier config keys and print them.
1528 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1529 for (String k : sortedSet) {
1530 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1531 }
1532 }
1533 return 0;
1534 }
1535
1536 // cc set-value
1537 private int handleCcSetValue() {
1538 PrintWriter errPw = getErrPrintWriter();
1539 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1540
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001541 // Parse all options
1542 CcOptionParseResult options = parseCcOptions(tag, true);
1543 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001544 return -1;
1545 }
1546
1547 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001548 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001549 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001550 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001551 return -1;
1552 }
1553
1554 // Get the key.
1555 String key = getNextArg();
1556 if (key == null || key.equals("")) {
1557 errPw.println(tag + "KEY is missing");
1558 return -1;
1559 }
1560
1561 // Verify if the key is valid
1562 if (!originalValues.containsKey(key)) {
1563 errPw.println(tag + key + " is not a valid key.");
1564 return -1;
1565 }
1566
1567 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1568 ArrayList<String> valueList = new ArrayList<String>();
1569 while (peekNextArg() != null) {
1570 valueList.add(getNextArg());
1571 }
1572
1573 // Find the type of the carrier config value
1574 CcType type = getType(tag, key, originalValues);
1575 if (type == CcType.UNKNOWN) {
1576 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1577 return -1;
1578 }
1579
1580 // Create an override bundle containing the key and value that should be overriden.
1581 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1582 if (overrideBundle == null) {
1583 return -1;
1584 }
1585
1586 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001587 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001588
1589 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001590 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001591 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001592 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001593 return -1;
1594 }
1595
1596 // Print the original and new value.
1597 String originalValueString = ccValueToString(key, type, originalValues);
1598 String newValueString = ccValueToString(key, type, newValues);
1599 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1600 getOutPrintWriter().println("New value: \n" + newValueString);
1601
1602 return 0;
1603 }
1604
1605 // cc clear-values
1606 private int handleCcClearValues() {
1607 PrintWriter errPw = getErrPrintWriter();
1608 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1609
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001610 // Parse all options
1611 CcOptionParseResult options = parseCcOptions(tag, false);
1612 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001613 return -1;
1614 }
1615
1616 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001617 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001618 getOutPrintWriter()
1619 .println("All previously set carrier config override values has been cleared");
1620 return 0;
1621 }
1622
1623 private CcType getType(String tag, String key, PersistableBundle bundle) {
1624 // Find the type by checking the type of the current value stored in the bundle.
1625 Object value = bundle.get(key);
1626
1627 if (CC_TYPE_MAP.containsKey(key)) {
1628 return CC_TYPE_MAP.get(key);
1629 } else if (value != null) {
1630 if (value instanceof Boolean) {
1631 return CcType.BOOLEAN;
1632 } else if (value instanceof Double) {
1633 return CcType.DOUBLE;
1634 } else if (value instanceof double[]) {
1635 return CcType.DOUBLE_ARRAY;
1636 } else if (value instanceof Integer) {
1637 return CcType.INT;
1638 } else if (value instanceof int[]) {
1639 return CcType.INT_ARRAY;
1640 } else if (value instanceof Long) {
1641 return CcType.LONG;
1642 } else if (value instanceof long[]) {
1643 return CcType.LONG_ARRAY;
1644 } else if (value instanceof String) {
1645 return CcType.STRING;
1646 } else if (value instanceof String[]) {
1647 return CcType.STRING_ARRAY;
1648 }
1649 } else {
1650 // Current value was null and can therefore not be used in order to find the type.
1651 // Check the name of the key to infer the type. This check is not needed for primitive
1652 // data types (boolean, double, int and long), since they can not be null.
1653 if (key.endsWith("double_array")) {
1654 return CcType.DOUBLE_ARRAY;
1655 }
1656 if (key.endsWith("int_array")) {
1657 return CcType.INT_ARRAY;
1658 }
1659 if (key.endsWith("long_array")) {
1660 return CcType.LONG_ARRAY;
1661 }
1662 if (key.endsWith("string")) {
1663 return CcType.STRING;
1664 }
1665 if (key.endsWith("string_array") || key.endsWith("strings")) {
1666 return CcType.STRING_ARRAY;
1667 }
1668 }
1669
1670 // Not possible to infer the type by looking at the current value or the key.
1671 PrintWriter errPw = getErrPrintWriter();
1672 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1673 return CcType.UNKNOWN;
1674 }
1675
1676 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1677 String result;
1678 StringBuilder valueString = new StringBuilder();
1679 String typeString = type.toString();
1680 Object value = bundle.get(key);
1681
1682 if (value == null) {
1683 valueString.append("null");
1684 } else {
1685 switch (type) {
1686 case DOUBLE_ARRAY: {
1687 // Format the string representation of the int array as value1 value2......
1688 double[] valueArray = (double[]) value;
1689 for (int i = 0; i < valueArray.length; i++) {
1690 if (i != 0) {
1691 valueString.append(" ");
1692 }
1693 valueString.append(valueArray[i]);
1694 }
1695 break;
1696 }
1697 case INT_ARRAY: {
1698 // Format the string representation of the int array as value1 value2......
1699 int[] valueArray = (int[]) value;
1700 for (int i = 0; i < valueArray.length; i++) {
1701 if (i != 0) {
1702 valueString.append(" ");
1703 }
1704 valueString.append(valueArray[i]);
1705 }
1706 break;
1707 }
1708 case LONG_ARRAY: {
1709 // Format the string representation of the int array as value1 value2......
1710 long[] valueArray = (long[]) value;
1711 for (int i = 0; i < valueArray.length; i++) {
1712 if (i != 0) {
1713 valueString.append(" ");
1714 }
1715 valueString.append(valueArray[i]);
1716 }
1717 break;
1718 }
1719 case STRING: {
1720 valueString.append("\"" + value.toString() + "\"");
1721 break;
1722 }
1723 case STRING_ARRAY: {
1724 // Format the string representation of the string array as "value1" "value2"....
1725 String[] valueArray = (String[]) value;
1726 for (int i = 0; i < valueArray.length; i++) {
1727 if (i != 0) {
1728 valueString.append(" ");
1729 }
1730 if (valueArray[i] != null) {
1731 valueString.append("\"" + valueArray[i] + "\"");
1732 } else {
1733 valueString.append("null");
1734 }
1735 }
1736 break;
1737 }
1738 default: {
1739 valueString.append(value.toString());
1740 }
1741 }
1742 }
1743 return String.format("%-70s %-15s %s", key, typeString, valueString);
1744 }
1745
1746 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1747 ArrayList<String> valueList) {
1748 PrintWriter errPw = getErrPrintWriter();
1749 PersistableBundle bundle = new PersistableBundle();
1750
1751 // First verify that a valid number of values has been provided for the type.
1752 switch (type) {
1753 case BOOLEAN:
1754 case DOUBLE:
1755 case INT:
1756 case LONG: {
1757 if (valueList.size() != 1) {
1758 errPw.println(tag + "Expected 1 value for type " + type
1759 + ". Found: " + valueList.size());
1760 return null;
1761 }
1762 break;
1763 }
1764 case STRING: {
1765 if (valueList.size() > 1) {
1766 errPw.println(tag + "Expected 0 or 1 values for type " + type
1767 + ". Found: " + valueList.size());
1768 return null;
1769 }
1770 break;
1771 }
1772 }
1773
1774 // Parse the value according to type and add it to the Bundle.
1775 switch (type) {
1776 case BOOLEAN: {
1777 if ("true".equalsIgnoreCase(valueList.get(0))) {
1778 bundle.putBoolean(key, true);
1779 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1780 bundle.putBoolean(key, false);
1781 } else {
1782 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1783 return null;
1784 }
1785 break;
1786 }
1787 case DOUBLE: {
1788 try {
1789 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1790 } catch (NumberFormatException nfe) {
1791 // Not a valid double
1792 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1793 return null;
1794 }
1795 break;
1796 }
1797 case DOUBLE_ARRAY: {
1798 double[] valueDoubleArray = null;
1799 if (valueList.size() > 0) {
1800 valueDoubleArray = new double[valueList.size()];
1801 for (int i = 0; i < valueList.size(); i++) {
1802 try {
1803 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1804 } catch (NumberFormatException nfe) {
1805 // Not a valid double
1806 errPw.println(
1807 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1808 return null;
1809 }
1810 }
1811 }
1812 bundle.putDoubleArray(key, valueDoubleArray);
1813 break;
1814 }
1815 case INT: {
1816 try {
1817 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1818 } catch (NumberFormatException nfe) {
1819 // Not a valid integer
1820 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1821 return null;
1822 }
1823 break;
1824 }
1825 case INT_ARRAY: {
1826 int[] valueIntArray = null;
1827 if (valueList.size() > 0) {
1828 valueIntArray = new int[valueList.size()];
1829 for (int i = 0; i < valueList.size(); i++) {
1830 try {
1831 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1832 } catch (NumberFormatException nfe) {
1833 // Not a valid integer
1834 errPw.println(tag
1835 + "Unable to parse " + valueList.get(i) + " as an integer.");
1836 return null;
1837 }
1838 }
1839 }
1840 bundle.putIntArray(key, valueIntArray);
1841 break;
1842 }
1843 case LONG: {
1844 try {
1845 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1846 } catch (NumberFormatException nfe) {
1847 // Not a valid long
1848 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1849 return null;
1850 }
1851 break;
1852 }
1853 case LONG_ARRAY: {
1854 long[] valueLongArray = null;
1855 if (valueList.size() > 0) {
1856 valueLongArray = new long[valueList.size()];
1857 for (int i = 0; i < valueList.size(); i++) {
1858 try {
1859 valueLongArray[i] = Long.parseLong(valueList.get(i));
1860 } catch (NumberFormatException nfe) {
1861 // Not a valid long
1862 errPw.println(
1863 tag + "Unable to parse " + valueList.get(i) + " as a long");
1864 return null;
1865 }
1866 }
1867 }
1868 bundle.putLongArray(key, valueLongArray);
1869 break;
1870 }
1871 case STRING: {
1872 String value = null;
1873 if (valueList.size() > 0) {
1874 value = valueList.get(0);
1875 }
1876 bundle.putString(key, value);
1877 break;
1878 }
1879 case STRING_ARRAY: {
1880 String[] valueStringArray = null;
1881 if (valueList.size() > 0) {
1882 valueStringArray = new String[valueList.size()];
1883 valueList.toArray(valueStringArray);
1884 }
1885 bundle.putStringArray(key, valueStringArray);
1886 break;
1887 }
1888 }
1889 return bundle;
1890 }
Shuo Qian489d9282020-07-09 11:30:03 -07001891
1892 private int handleEndBlockSuppressionCommand() {
1893 if (!checkShellUid()) {
1894 return -1;
1895 }
1896
1897 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1898 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1899 }
1900 return 0;
1901 }
Hui Wang641e81c2020-10-12 12:14:23 -07001902
Michele Berionne54af4632020-12-28 20:23:16 +00001903 private int handleRestartModemCommand() {
1904 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1905 // non user build.
1906 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1907 getErrPrintWriter().println("RestartModem: Permission denied.");
1908 return -1;
1909 }
1910
1911 boolean result = TelephonyManager.getDefault().rebootRadio();
1912 getOutPrintWriter().println(result);
1913
1914 return result ? 0 : -1;
1915 }
1916
Michele Berionne5e411512020-11-13 02:36:59 +00001917 private int handleUnattendedReboot() {
1918 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1919 // non user build.
1920 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1921 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1922 return -1;
1923 }
1924
1925 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1926 getOutPrintWriter().println("result: " + result);
1927
1928 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1929 }
1930
Hui Wang641e81c2020-10-12 12:14:23 -07001931 private int handleGbaCommand() {
1932 String arg = getNextArg();
1933 if (arg == null) {
1934 onHelpGba();
1935 return 0;
1936 }
1937
1938 switch (arg) {
1939 case GBA_SET_SERVICE: {
1940 return handleGbaSetServiceCommand();
1941 }
1942 case GBA_GET_SERVICE: {
1943 return handleGbaGetServiceCommand();
1944 }
1945 case GBA_SET_RELEASE_TIME: {
1946 return handleGbaSetReleaseCommand();
1947 }
1948 case GBA_GET_RELEASE_TIME: {
1949 return handleGbaGetReleaseCommand();
1950 }
1951 }
1952
1953 return -1;
1954 }
1955
1956 private int getSubId(String cmd) {
1957 int slotId = getDefaultSlot();
1958 String opt = getNextOption();
1959 if (opt != null && opt.equals("-s")) {
1960 try {
1961 slotId = Integer.parseInt(getNextArgRequired());
1962 } catch (NumberFormatException e) {
1963 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1964 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1965 }
1966 }
1967 int[] subIds = SubscriptionManager.getSubId(slotId);
1968 return subIds[0];
1969 }
1970
1971 private int handleGbaSetServiceCommand() {
1972 int subId = getSubId("gba set-service");
1973 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1974 return -1;
1975 }
1976
1977 String packageName = getNextArg();
1978 try {
1979 if (packageName == null) {
1980 packageName = "";
1981 }
1982 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1983 if (VDBG) {
1984 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1985 + packageName + ", result=" + result);
1986 }
1987 getOutPrintWriter().println(result);
1988 } catch (RemoteException e) {
1989 Log.w(LOG_TAG, "gba set-service " + subId + " "
1990 + packageName + ", error" + e.getMessage());
1991 getErrPrintWriter().println("Exception: " + e.getMessage());
1992 return -1;
1993 }
1994 return 0;
1995 }
1996
1997 private int handleGbaGetServiceCommand() {
1998 String result;
1999
2000 int subId = getSubId("gba get-service");
2001 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2002 return -1;
2003 }
2004
2005 try {
2006 result = mInterface.getBoundGbaService(subId);
2007 } catch (RemoteException e) {
2008 return -1;
2009 }
2010 if (VDBG) {
2011 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2012 }
2013 getOutPrintWriter().println(result);
2014 return 0;
2015 }
2016
2017 private int handleGbaSetReleaseCommand() {
2018 //the release time value could be -1
2019 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2020 : SubscriptionManager.getDefaultSubscriptionId();
2021 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2022 return -1;
2023 }
2024
2025 String intervalStr = getNextArg();
2026 if (intervalStr == null) {
2027 return -1;
2028 }
2029
2030 try {
2031 int interval = Integer.parseInt(intervalStr);
2032 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2033 if (VDBG) {
2034 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2035 + intervalStr + ", result=" + result);
2036 }
2037 getOutPrintWriter().println(result);
2038 } catch (NumberFormatException | RemoteException e) {
2039 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2040 + intervalStr + ", error" + e.getMessage());
2041 getErrPrintWriter().println("Exception: " + e.getMessage());
2042 return -1;
2043 }
2044 return 0;
2045 }
2046
2047 private int handleGbaGetReleaseCommand() {
2048 int subId = getSubId("gba get-release");
2049 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2050 return -1;
2051 }
2052
2053 int result = 0;
2054 try {
2055 result = mInterface.getGbaReleaseTime(subId);
2056 } catch (RemoteException e) {
2057 return -1;
2058 }
2059 if (VDBG) {
2060 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2061 }
2062 getOutPrintWriter().println(result);
2063 return 0;
2064 }
Hui Wang761a6682020-10-31 05:12:53 +00002065
2066 private int handleSingleRegistrationConfigCommand() {
2067 String arg = getNextArg();
2068 if (arg == null) {
2069 onHelpSrc();
2070 return 0;
2071 }
2072
2073 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002074 case SRC_SET_TEST_ENABLED: {
2075 return handleSrcSetTestEnabledCommand();
2076 }
2077 case SRC_GET_TEST_ENABLED: {
2078 return handleSrcGetTestEnabledCommand();
2079 }
Hui Wang761a6682020-10-31 05:12:53 +00002080 case SRC_SET_DEVICE_ENABLED: {
2081 return handleSrcSetDeviceEnabledCommand();
2082 }
2083 case SRC_GET_DEVICE_ENABLED: {
2084 return handleSrcGetDeviceEnabledCommand();
2085 }
2086 case SRC_SET_CARRIER_ENABLED: {
2087 return handleSrcSetCarrierEnabledCommand();
2088 }
2089 case SRC_GET_CARRIER_ENABLED: {
2090 return handleSrcGetCarrierEnabledCommand();
2091 }
Hui Wangb647abe2021-02-26 09:33:38 -08002092 case SRC_SET_FEATURE_ENABLED: {
2093 return handleSrcSetFeatureValidationCommand();
2094 }
2095 case SRC_GET_FEATURE_ENABLED: {
2096 return handleSrcGetFeatureValidationCommand();
2097 }
Hui Wang761a6682020-10-31 05:12:53 +00002098 }
2099
2100 return -1;
2101 }
2102
James.cf Linbcdf8b32021-01-14 16:44:13 +08002103 private int handleRcsUceCommand() {
2104 String arg = getNextArg();
2105 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002106 onHelpUce();
2107 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002108 }
2109
2110 switch (arg) {
2111 case UCE_REMOVE_EAB_CONTACT:
2112 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002113 case UCE_GET_EAB_CONTACT:
2114 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002115 case UCE_GET_EAB_CAPABILITY:
2116 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002117 case UCE_GET_DEVICE_ENABLED:
2118 return handleUceGetDeviceEnabledCommand();
2119 case UCE_SET_DEVICE_ENABLED:
2120 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002121 case UCE_OVERRIDE_PUBLISH_CAPS:
2122 return handleUceOverridePublishCaps();
2123 case UCE_GET_LAST_PIDF_XML:
2124 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002125 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2126 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002127 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2128 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002129 }
2130 return -1;
2131 }
2132
2133 private int handleRemovingEabContactCommand() {
2134 int subId = getSubId("uce remove-eab-contact");
2135 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2136 return -1;
2137 }
2138
2139 String phoneNumber = getNextArgRequired();
2140 if (TextUtils.isEmpty(phoneNumber)) {
2141 return -1;
2142 }
2143 int result = 0;
2144 try {
2145 result = mInterface.removeContactFromEab(subId, phoneNumber);
2146 } catch (RemoteException e) {
2147 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2148 getErrPrintWriter().println("Exception: " + e.getMessage());
2149 return -1;
2150 }
2151
2152 if (VDBG) {
2153 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2154 }
calvinpan293ea1b2021-02-04 17:52:13 +08002155 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002156 }
2157
calvinpane4a8a1d2021-01-25 13:51:18 +08002158 private int handleGettingEabContactCommand() {
2159 String phoneNumber = getNextArgRequired();
2160 if (TextUtils.isEmpty(phoneNumber)) {
2161 return -1;
2162 }
2163 String result = "";
2164 try {
2165 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002166 } catch (RemoteException e) {
2167 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2168 getErrPrintWriter().println("Exception: " + e.getMessage());
2169 return -1;
2170 }
2171
2172 if (VDBG) {
2173 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2174 }
calvinpan293ea1b2021-02-04 17:52:13 +08002175 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002176 return 0;
2177 }
2178
Calvin Pana1434322021-07-01 19:27:01 +08002179 private int handleGettingEabCapabilityCommand() {
2180 String phoneNumber = getNextArgRequired();
2181 if (TextUtils.isEmpty(phoneNumber)) {
2182 return -1;
2183 }
2184 String result = "";
2185 try {
2186 result = mInterface.getCapabilityFromEab(phoneNumber);
2187 } catch (RemoteException e) {
2188 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2189 getErrPrintWriter().println("Exception: " + e.getMessage());
2190 return -1;
2191 }
2192
2193 if (VDBG) {
2194 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2195 }
2196 getOutPrintWriter().println(result);
2197 return 0;
2198 }
2199
James.cf Lin4b784aa2021-01-31 03:25:15 +08002200 private int handleUceGetDeviceEnabledCommand() {
2201 boolean result = false;
2202 try {
2203 result = mInterface.getDeviceUceEnabled();
2204 } catch (RemoteException e) {
2205 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2206 return -1;
2207 }
2208 if (VDBG) {
2209 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2210 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002211 getOutPrintWriter().println(result);
2212 return 0;
2213 }
2214
James.cf Lin4b784aa2021-01-31 03:25:15 +08002215 private int handleUceSetDeviceEnabledCommand() {
2216 String enabledStr = getNextArg();
2217 if (TextUtils.isEmpty(enabledStr)) {
2218 return -1;
2219 }
2220
2221 try {
2222 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2223 mInterface.setDeviceUceEnabled(isEnabled);
2224 if (VDBG) {
2225 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2226 }
2227 } catch (NumberFormatException | RemoteException e) {
2228 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2229 getErrPrintWriter().println("Exception: " + e.getMessage());
2230 return -1;
2231 }
2232 return 0;
2233 }
2234
James.cf Line8713a42021-04-29 16:04:26 +08002235 private int handleUceRemoveRequestDisallowedStatus() {
2236 int subId = getSubId("uce remove-request-disallowed-status");
2237 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2238 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2239 return -1;
2240 }
2241 boolean result;
2242 try {
2243 result = mInterface.removeUceRequestDisallowedStatus(subId);
2244 } catch (RemoteException e) {
2245 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2246 return -1;
2247 }
2248 if (VDBG) {
2249 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2250 }
2251 getOutPrintWriter().println(result);
2252 return 0;
2253 }
2254
James.cf Lin0fc71b02021-05-25 01:37:38 +08002255 private int handleUceSetCapRequestTimeout() {
2256 int subId = getSubId("uce set-capabilities-request-timeout");
2257 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2258 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2259 return -1;
2260 }
2261 long timeoutAfterMs = Long.valueOf(getNextArg());
2262 boolean result;
2263 try {
2264 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2265 } catch (RemoteException e) {
2266 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2267 return -1;
2268 }
2269 if (VDBG) {
2270 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2271 }
2272 getOutPrintWriter().println(result);
2273 return 0;
2274 }
2275
Hui Wangbaaee6a2021-02-19 20:45:36 -08002276 private int handleSrcSetTestEnabledCommand() {
2277 String enabledStr = getNextArg();
2278 if (enabledStr == null) {
2279 return -1;
2280 }
2281
2282 try {
2283 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2284 if (VDBG) {
2285 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2286 }
2287 getOutPrintWriter().println("Done");
2288 } catch (NumberFormatException | RemoteException e) {
2289 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2290 getErrPrintWriter().println("Exception: " + e.getMessage());
2291 return -1;
2292 }
2293 return 0;
2294 }
2295
2296 private int handleSrcGetTestEnabledCommand() {
2297 boolean result = false;
2298 try {
2299 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2300 } catch (RemoteException e) {
2301 return -1;
2302 }
2303 if (VDBG) {
2304 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2305 }
2306 getOutPrintWriter().println(result);
2307 return 0;
2308 }
2309
Brad Ebinger14d467f2021-02-12 06:18:28 +00002310 private int handleUceOverridePublishCaps() {
2311 int subId = getSubId("uce override-published-caps");
2312 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2313 return -1;
2314 }
2315 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2316 String operation = getNextArgRequired();
2317 String caps = getNextArg();
2318 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2319 && !"list".equals(operation)) {
2320 getErrPrintWriter().println("Invalid operation: " + operation);
2321 return -1;
2322 }
2323
2324 // add/remove requires capabilities to be specified.
2325 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2326 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2327 + "specified");
2328 return -1;
2329 }
2330
2331 ArraySet<String> capSet = new ArraySet<>();
2332 if (!TextUtils.isEmpty(caps)) {
2333 String[] capArray = caps.split(":");
2334 for (String cap : capArray) {
2335 // Allow unknown tags to be passed in as well.
2336 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2337 }
2338 }
2339
2340 RcsContactUceCapability result = null;
2341 try {
2342 switch (operation) {
2343 case "add":
2344 result = mInterface.addUceRegistrationOverrideShell(subId,
2345 new ArrayList<>(capSet));
2346 break;
2347 case "remove":
2348 result = mInterface.removeUceRegistrationOverrideShell(subId,
2349 new ArrayList<>(capSet));
2350 break;
2351 case "clear":
2352 result = mInterface.clearUceRegistrationOverrideShell(subId);
2353 break;
2354 case "list":
2355 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2356 break;
2357 }
2358 } catch (RemoteException e) {
2359 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2360 getErrPrintWriter().println("Exception: " + e.getMessage());
2361 return -1;
2362 } catch (ServiceSpecificException sse) {
2363 // Reconstruct ImsException
2364 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2365 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2366 getErrPrintWriter().println("Exception: " + imsException);
2367 return -1;
2368 }
2369 if (result == null) {
2370 getErrPrintWriter().println("Service not available");
2371 return -1;
2372 }
2373 getOutPrintWriter().println(result);
2374 return 0;
2375 }
2376
2377 private int handleUceGetPidfXml() {
2378 int subId = getSubId("uce get-last-publish-pidf");
2379 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2380 return -1;
2381 }
2382
2383 String result;
2384 try {
2385 result = mInterface.getLastUcePidfXmlShell(subId);
2386 } catch (RemoteException e) {
2387 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2388 getErrPrintWriter().println("Exception: " + e.getMessage());
2389 return -1;
2390 } catch (ServiceSpecificException sse) {
2391 // Reconstruct ImsException
2392 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2393 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2394 getErrPrintWriter().println("Exception: " + imsException);
2395 return -1;
2396 }
2397 if (result == null) {
2398 getErrPrintWriter().println("Service not available");
2399 return -1;
2400 }
2401 getOutPrintWriter().println(result);
2402 return 0;
2403 }
2404
Hui Wang761a6682020-10-31 05:12:53 +00002405 private int handleSrcSetDeviceEnabledCommand() {
2406 String enabledStr = getNextArg();
2407 if (enabledStr == null) {
2408 return -1;
2409 }
2410
2411 try {
2412 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2413 if (VDBG) {
2414 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2415 }
2416 getOutPrintWriter().println("Done");
2417 } catch (NumberFormatException | RemoteException e) {
2418 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2419 getErrPrintWriter().println("Exception: " + e.getMessage());
2420 return -1;
2421 }
2422 return 0;
2423 }
2424
2425 private int handleSrcGetDeviceEnabledCommand() {
2426 boolean result = false;
2427 try {
2428 result = mInterface.getDeviceSingleRegistrationEnabled();
2429 } catch (RemoteException e) {
2430 return -1;
2431 }
2432 if (VDBG) {
2433 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2434 }
2435 getOutPrintWriter().println(result);
2436 return 0;
2437 }
2438
2439 private int handleSrcSetCarrierEnabledCommand() {
2440 //the release time value could be -1
2441 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2442 : SubscriptionManager.getDefaultSubscriptionId();
2443 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2444 return -1;
2445 }
2446
2447 String enabledStr = getNextArg();
2448 if (enabledStr == null) {
2449 return -1;
2450 }
2451
2452 try {
2453 boolean result =
2454 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2455 if (VDBG) {
2456 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2457 + enabledStr + ", result=" + result);
2458 }
2459 getOutPrintWriter().println(result);
2460 } catch (NumberFormatException | RemoteException e) {
2461 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2462 + enabledStr + ", error" + e.getMessage());
2463 getErrPrintWriter().println("Exception: " + e.getMessage());
2464 return -1;
2465 }
2466 return 0;
2467 }
2468
2469 private int handleSrcGetCarrierEnabledCommand() {
2470 int subId = getSubId("src get-carrier-enabled");
2471 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2472 return -1;
2473 }
2474
2475 boolean result = false;
2476 try {
2477 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2478 } catch (RemoteException e) {
2479 return -1;
2480 }
2481 if (VDBG) {
2482 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2483 }
2484 getOutPrintWriter().println(result);
2485 return 0;
2486 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002487
Hui Wangb647abe2021-02-26 09:33:38 -08002488 private int handleSrcSetFeatureValidationCommand() {
2489 //the release time value could be -1
2490 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2491 : SubscriptionManager.getDefaultSubscriptionId();
2492 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2493 return -1;
2494 }
2495
2496 String enabledStr = getNextArg();
2497 if (enabledStr == null) {
2498 return -1;
2499 }
2500
2501 try {
2502 boolean result =
2503 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2504 if (VDBG) {
2505 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2506 + enabledStr + ", result=" + result);
2507 }
2508 getOutPrintWriter().println(result);
2509 } catch (NumberFormatException | RemoteException e) {
2510 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2511 + enabledStr + ", error" + e.getMessage());
2512 getErrPrintWriter().println("Exception: " + e.getMessage());
2513 return -1;
2514 }
2515 return 0;
2516 }
2517
2518 private int handleSrcGetFeatureValidationCommand() {
2519 int subId = getSubId("src get-feature-validation");
2520 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2521 return -1;
2522 }
2523
2524 Boolean result = false;
2525 try {
2526 result = mInterface.getImsFeatureValidationOverride(subId);
2527 } catch (RemoteException e) {
2528 return -1;
2529 }
2530 if (VDBG) {
2531 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2532 }
2533 getOutPrintWriter().println(result);
2534 return 0;
2535 }
2536
2537
Hall Liuaa4211e2021-01-20 15:43:39 -08002538 private void onHelpCallComposer() {
2539 PrintWriter pw = getOutPrintWriter();
2540 pw.println("Call composer commands");
2541 pw.println(" callcomposer test-mode enable|disable|query");
2542 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2543 pw.println(" upload/download from carrier servers is disabled, and operations are");
2544 pw.println(" performed using emulated local files instead.");
2545 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2546 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2547 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002548 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2549 pw.println(" Enables or disables the user setting for call composer, as set by");
2550 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002551 }
2552
2553 private int handleCallComposerCommand() {
2554 String arg = getNextArg();
2555 if (arg == null) {
2556 onHelpCallComposer();
2557 return 0;
2558 }
2559
2560 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2561 "MODIFY_PHONE_STATE required for call composer shell cmds");
2562 switch (arg) {
2563 case CALL_COMPOSER_TEST_MODE: {
2564 String enabledStr = getNextArg();
2565 if (ENABLE.equals(enabledStr)) {
2566 CallComposerPictureManager.sTestMode = true;
2567 } else if (DISABLE.equals(enabledStr)) {
2568 CallComposerPictureManager.sTestMode = false;
2569 } else if (QUERY.equals(enabledStr)) {
2570 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2571 } else {
2572 onHelpCallComposer();
2573 return 1;
2574 }
2575 break;
2576 }
2577 case CALL_COMPOSER_SIMULATE_CALL: {
2578 int subscriptionId = Integer.valueOf(getNextArg());
2579 String uuidString = getNextArg();
2580 UUID uuid = UUID.fromString(uuidString);
2581 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2582 Binder.withCleanCallingIdentity(() -> {
2583 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2584 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2585 });
2586 try {
2587 Uri uri = storageUriFuture.get();
2588 getOutPrintWriter().println(String.valueOf(uri));
2589 } catch (Exception e) {
2590 throw new RuntimeException(e);
2591 }
2592 break;
2593 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002594 case CALL_COMPOSER_USER_SETTING: {
2595 try {
2596 int subscriptionId = Integer.valueOf(getNextArg());
2597 String enabledStr = getNextArg();
2598 if (ENABLE.equals(enabledStr)) {
2599 mInterface.setCallComposerStatus(subscriptionId,
2600 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2601 } else if (DISABLE.equals(enabledStr)) {
2602 mInterface.setCallComposerStatus(subscriptionId,
2603 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2604 } else if (QUERY.equals(enabledStr)) {
2605 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2606 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2607 } else {
2608 onHelpCallComposer();
2609 return 1;
2610 }
2611 } catch (RemoteException e) {
2612 e.printStackTrace(getOutPrintWriter());
2613 return 1;
2614 }
2615 break;
2616 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002617 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002618 return 0;
2619 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002620
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002621 private int handleHasCarrierPrivilegesCommand() {
2622 String packageName = getNextArgRequired();
2623
2624 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002625 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002626 try {
2627 hasCarrierPrivileges =
2628 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2629 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2630 } catch (RemoteException e) {
2631 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2632 getErrPrintWriter().println("Exception: " + e.getMessage());
2633 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002634 } finally {
2635 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002636 }
2637
2638 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002639 return 0;
2640 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002641
2642 private int handleAllowedNetworkTypesCommand(String command) {
2643 if (!checkShellUid()) {
2644 return -1;
2645 }
2646
2647 PrintWriter errPw = getErrPrintWriter();
2648 String tag = command + ": ";
2649 String opt;
2650 int subId = -1;
2651 Log.v(LOG_TAG, command + " start");
2652
2653 while ((opt = getNextOption()) != null) {
2654 if (opt.equals("-s")) {
2655 try {
2656 subId = slotStringToSubId(tag, getNextArgRequired());
2657 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2658 errPw.println(tag + "No valid subscription found.");
2659 return -1;
2660 }
2661 } catch (IllegalArgumentException e) {
2662 // Missing slot id
2663 errPw.println(tag + "SLOT_ID expected after -s.");
2664 return -1;
2665 }
2666 } else {
2667 errPw.println(tag + "Unknown option " + opt);
2668 return -1;
2669 }
2670 }
2671
2672 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2673 return handleGetAllowedNetworkTypesCommand(subId);
2674 }
2675 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2676 return handleSetAllowedNetworkTypesCommand(subId);
2677 }
2678 return -1;
2679 }
2680
2681 private int handleGetAllowedNetworkTypesCommand(int subId) {
2682 PrintWriter errPw = getErrPrintWriter();
2683
2684 long result = -1;
2685 try {
2686 if (mInterface != null) {
2687 result = mInterface.getAllowedNetworkTypesForReason(subId,
2688 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2689 } else {
2690 throw new IllegalStateException("telephony service is null.");
2691 }
2692 } catch (RemoteException e) {
2693 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2694 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2695 return -1;
2696 }
2697
2698 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2699 return 0;
2700 }
2701
2702 private int handleSetAllowedNetworkTypesCommand(int subId) {
2703 PrintWriter errPw = getErrPrintWriter();
2704
2705 String bitmaskString = getNextArg();
2706 if (TextUtils.isEmpty(bitmaskString)) {
2707 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2708 return -1;
2709 }
2710 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2711 if (allowedNetworkTypes < 0) {
2712 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2713 return -1;
2714 }
2715 boolean result = false;
2716 try {
2717 if (mInterface != null) {
2718 result = mInterface.setAllowedNetworkTypesForReason(subId,
2719 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2720 } else {
2721 throw new IllegalStateException("telephony service is null.");
2722 }
2723 } catch (RemoteException e) {
2724 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2725 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2726 return -1;
2727 }
2728
2729 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2730 if (result) {
2731 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2732 }
2733 getOutPrintWriter().println(resultMessage);
2734 return 0;
2735 }
2736
2737 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2738 if (TextUtils.isEmpty(bitmaskString)) {
2739 return -1;
2740 }
2741 if (VDBG) {
2742 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2743 + ", length: " + bitmaskString.length());
2744 }
2745 try {
2746 return Long.parseLong(bitmaskString, 2);
2747 } catch (NumberFormatException e) {
2748 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2749 return -1;
2750 }
2751 }
jimsun38340bf2021-10-26 15:01:23 +08002752
2753 private int handleRadioSetModemServiceCommand() {
2754 PrintWriter errPw = getErrPrintWriter();
2755 String serviceName = null;
2756
2757 String opt;
2758 while ((opt = getNextOption()) != null) {
2759 switch (opt) {
2760 case "-s": {
2761 serviceName = getNextArgRequired();
2762 break;
2763 }
2764 }
2765 }
2766
2767 try {
2768 boolean result = mInterface.setModemService(serviceName);
2769 if (VDBG) {
2770 Log.v(LOG_TAG,
2771 "RadioSetModemService " + serviceName + ", result = " + result);
2772 }
2773 getOutPrintWriter().println(result);
2774 } catch (RemoteException e) {
2775 Log.w(LOG_TAG,
2776 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2777 errPw.println("Exception: " + e.getMessage());
2778 return -1;
2779 }
2780 return 0;
2781 }
2782
2783 private int handleRadioGetModemServiceCommand() {
2784 PrintWriter errPw = getErrPrintWriter();
2785 String result;
2786
2787 try {
2788 result = mInterface.getModemService();
2789 getOutPrintWriter().println(result);
2790 } catch (RemoteException e) {
2791 errPw.println("Exception: " + e.getMessage());
2792 return -1;
2793 }
2794 if (VDBG) {
2795 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2796 }
2797 return 0;
2798 }
2799
2800 private int handleRadioCommand() {
2801 String arg = getNextArg();
2802 if (arg == null) {
2803 onHelpRadio();
2804 return 0;
2805 }
2806
2807 switch (arg) {
2808 case RADIO_SET_MODEM_SERVICE:
2809 return handleRadioSetModemServiceCommand();
2810
2811 case RADIO_GET_MODEM_SERVICE:
2812 return handleRadioGetModemServiceCommand();
2813 }
2814
2815 return -1;
2816 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002817}