blob: 090f405b4ac52084c81c51271c5c82c65ac96dfa [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";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800143 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800144 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
145 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000146 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
147 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800148 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
149 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800150 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
151 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800152
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800153 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
154 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
155
Jordan Liu0ccee222021-04-27 11:55:13 -0700156 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
157 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
158
Jack Nudelman644b91a2021-03-12 14:09:48 -0800159 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
160 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
161 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
162
SongFerngWang98dd5992021-05-13 17:50:00 +0800163 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
164 "get-allowed-network-types-for-users";
165 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
166 "set-allowed-network-types-for-users";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700167 // Take advantage of existing methods that already contain permissions checks when possible.
168 private final ITelephony mInterface;
169
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100170 private SubscriptionManager mSubscriptionManager;
171 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700172 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700173 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100174
175 private enum CcType {
176 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
177 STRING_ARRAY, UNKNOWN
178 }
179
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100180 private class CcOptionParseResult {
181 public int mSubId;
182 public boolean mPersistent;
183 }
184
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100185 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
186 // keys by looking at the end of the string which usually tells the type.
187 // For instance: "xxxx_string", "xxxx_string_array", etc.
188 // The carrier config keys in this map does not follow this convention. It is therefore not
189 // possible to infer the type for these keys by looking at the string.
190 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
191 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
192 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
193 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
194 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
195 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
196 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
197 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
198 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
199 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
200 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
202 CcType.STRING);
203 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
204 CcType.STRING_ARRAY);
205 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
206 CcType.STRING_ARRAY);
207 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
208 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
209 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
210 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
211 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
212 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
213 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
214 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
215 }
216 };
217
Brad Ebinger14d467f2021-02-12 06:18:28 +0000218 /**
219 * Map from a shorthand string to the feature tags required in registration required in order
220 * for the RCS feature to be considered "capable".
221 */
222 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
223 static {
224 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
225 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
226 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
227 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
228 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
229 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
230 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
231 FeatureTags.FEATURE_TAG_VIDEO)));
232 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
233 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
234 map.put("call_comp",
235 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
236 map.put("call_comp_mmtel",
237 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
238 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
239 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
240 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
241 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
242 // version
243 map.put("chatbot", new ArraySet<>(Arrays.asList(
244 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
245 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
246 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
247 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
248 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
249 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
250 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
251 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
252 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
253 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
254 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
255 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
256 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
257 }
258
259
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100260 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700261 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100262 mCarrierConfigManager =
263 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
264 mSubscriptionManager = (SubscriptionManager)
265 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700266 mTelephonyRegistryManager = (TelephonyRegistryManager)
267 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700268 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700269 }
270
271 @Override
272 public int onCommand(String cmd) {
273 if (cmd == null) {
274 return handleDefaultCommands(null);
275 }
276
277 switch (cmd) {
278 case IMS_SUBCOMMAND: {
279 return handleImsCommand();
280 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800281 case RCS_UCE_COMMAND:
282 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800283 case NUMBER_VERIFICATION_SUBCOMMAND:
284 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800285 case EMERGENCY_CALLBACK_MODE:
286 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800287 case EMERGENCY_NUMBER_TEST_MODE:
288 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100289 case CARRIER_CONFIG_SUBCOMMAND: {
290 return handleCcCommand();
291 }
Shuo Qianf5125122019-12-16 17:03:07 -0800292 case DATA_TEST_MODE:
293 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700294 case END_BLOCK_SUPPRESSION:
295 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700296 case GBA_SUBCOMMAND:
297 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800298 case D2D_SUBCOMMAND:
299 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700300 case BARRING_SUBCOMMAND:
301 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000302 case SINGLE_REGISTATION_CONFIG:
303 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000304 case RESTART_MODEM:
305 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800306 case CALL_COMPOSER_SUBCOMMAND:
307 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000308 case UNATTENDED_REBOOT:
309 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800310 case HAS_CARRIER_PRIVILEGES_COMMAND:
311 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800312 case THERMAL_MITIGATION_COMMAND:
313 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700314 case DISABLE_PHYSICAL_SUBSCRIPTION:
315 return handleEnablePhysicalSubscription(false);
316 case ENABLE_PHYSICAL_SUBSCRIPTION:
317 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800318 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
319 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
320 return handleAllowedNetworkTypesCommand(cmd);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700321 default: {
322 return handleDefaultCommands(cmd);
323 }
324 }
325 }
326
327 @Override
328 public void onHelp() {
329 PrintWriter pw = getOutPrintWriter();
330 pw.println("Telephony Commands:");
331 pw.println(" help");
332 pw.println(" Print this help text.");
333 pw.println(" ims");
334 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800335 pw.println(" uce");
336 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800337 pw.println(" emergency-number-test-mode");
338 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700339 pw.println(" end-block-suppression");
340 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800341 pw.println(" data");
342 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100343 pw.println(" cc");
344 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700345 pw.println(" gba");
346 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000347 pw.println(" src");
348 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000349 pw.println(" restart-modem");
350 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000351 pw.println(" unattended-reboot");
352 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800353 pw.println(" has-carrier-privileges [package]");
354 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800355 pw.println(" get-allowed-network-types-for-users");
356 pw.println(" Get the Allowed Network Types.");
357 pw.println(" set-allowed-network-types-for-users");
358 pw.println(" Set the Allowed Network Types.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700359 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800360 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800361 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700362 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800363 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100364 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700365 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000366 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800367 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700368 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800369 onHelpAllowedNetworkTypes();
Tyler Gunn92479152021-01-20 16:30:10 -0800370 }
371
372 private void onHelpD2D() {
373 PrintWriter pw = getOutPrintWriter();
374 pw.println("D2D Comms Commands:");
375 pw.println(" d2d send TYPE VALUE");
376 pw.println(" Sends a D2D message of specified type and value.");
377 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
378 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
379 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
380 MESSAGE_CALL_AUDIO_CODEC));
381 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
382 + Communicator.messageToString(
383 MESSAGE_DEVICE_BATTERY_STATE));
384 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
385 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800386 pw.println(" d2d transport TYPE");
387 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
388 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700389 pw.println(" d2d set-device-support true/default");
390 pw.println(" true - forces device support to be enabled for D2D.");
391 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
392 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700393 }
394
Nazanin014f41e2021-05-06 17:26:31 -0700395 private void onHelpBarring() {
396 PrintWriter pw = getOutPrintWriter();
397 pw.println("Barring Commands:");
398 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
399 + " -t CONDITIONAL_BARRING_TIME_SECS");
400 pw.println(" Notifies of a barring info change for the specified slot id.");
401 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
402 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
403 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
404 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
405 }
406
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700407 private void onHelpIms() {
408 PrintWriter pw = getOutPrintWriter();
409 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800410 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700411 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
412 pw.println(" ImsService. Options are:");
413 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
414 pw.println(" is specified, it will choose the default voice SIM slot.");
415 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
416 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800417 pw.println(" -f: Set the feature that this override if for, if no option is");
418 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700419 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
420 pw.println(" Gets the package name of the currently defined ImsService.");
421 pw.println(" Options are:");
422 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
423 pw.println(" is specified, it will choose the default voice SIM slot.");
424 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000425 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800426 pw.println(" -f: The feature type that the query will be requested for. If none is");
427 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800428 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
429 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
430 pw.println(" configuration overrides. Options are:");
431 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
432 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700433 pw.println(" ims enable [-s SLOT_ID]");
434 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
435 pw.println(" if none is specified.");
436 pw.println(" ims disable [-s SLOT_ID]");
437 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
438 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700439 pw.println(" ims conference-event-package [enable/disable]");
440 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700441 }
442
James.cf Linbcdf8b32021-01-14 16:44:13 +0800443 private void onHelpUce() {
444 PrintWriter pw = getOutPrintWriter();
445 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800446 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
447 pw.println(" Get the EAB contacts from the EAB database.");
448 pw.println(" Options are:");
449 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
450 pw.println(" Expected output format :");
451 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800452 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
453 pw.println(" Remove the EAB contacts from the EAB database.");
454 pw.println(" Options are:");
455 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
456 pw.println(" is specified, it will choose the default voice SIM slot.");
457 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800458 pw.println(" uce get-device-enabled");
459 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
460 pw.println(" uce set-device-enabled true|false");
461 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
462 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000463 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
464 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
465 pw.println(" Options are:");
466 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
467 pw.println(" is specified, it will choose the default voice SIM slot.");
468 pw.println(" add [CAPABILITY]: add a new capability");
469 pw.println(" remove [CAPABILITY]: remove a capability");
470 pw.println(" clear: clear all capability overrides");
471 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
472 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
473 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
474 pw.println(" chatbot_sa, chatbot_role] as well as full length");
475 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
476 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
477 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
478 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800479 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
480 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800481 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
482 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800483 }
484
Hall Liud892bec2018-11-30 14:51:45 -0800485 private void onHelpNumberVerification() {
486 PrintWriter pw = getOutPrintWriter();
487 pw.println("Number verification commands");
488 pw.println(" numverify override-package PACKAGE_NAME;");
489 pw.println(" Set the authorized package for number verification.");
490 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800491 pw.println(" numverify fake-call NUMBER;");
492 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
493 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800494 }
495
Jack Nudelman644b91a2021-03-12 14:09:48 -0800496 private void onHelpThermalMitigation() {
497 PrintWriter pw = getOutPrintWriter();
498 pw.println("Thermal mitigation commands");
499 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
500 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
501 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
502 pw.println(" Remove the package from one of the authorized packages for thermal "
503 + "mitigation.");
504 }
505
Jordan Liu0ccee222021-04-27 11:55:13 -0700506 private void onHelpDisableOrEnablePhysicalSubscription() {
507 PrintWriter pw = getOutPrintWriter();
508 pw.println("Disable or enable a physical subscription");
509 pw.println(" disable-physical-subscription SUB_ID");
510 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
511 pw.println(" enable-physical-subscription SUB_ID");
512 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
513 }
514
Shuo Qianf5125122019-12-16 17:03:07 -0800515 private void onHelpDataTestMode() {
516 PrintWriter pw = getOutPrintWriter();
517 pw.println("Mobile Data Test Mode Commands:");
518 pw.println(" data enable: enable mobile data connectivity");
519 pw.println(" data disable: disable mobile data connectivity");
520 }
521
sqian9d4df8b2019-01-15 18:32:07 -0800522 private void onHelpEmergencyNumber() {
523 PrintWriter pw = getOutPrintWriter();
524 pw.println("Emergency Number Test Mode Commands:");
525 pw.println(" emergency-number-test-mode ");
526 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
527 + " the test mode");
528 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700529 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800530 pw.println(" -c: clear the emergency number list in the test mode.");
531 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700532 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800533 pw.println(" -p: get the full emergency number list in the test mode.");
534 }
535
Shuo Qian489d9282020-07-09 11:30:03 -0700536 private void onHelpEndBlockSupperssion() {
537 PrintWriter pw = getOutPrintWriter();
538 pw.println("End Block Suppression command:");
539 pw.println(" end-block-suppression: disable suppressing blocking by contact");
540 pw.println(" with emergency services.");
541 }
542
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100543 private void onHelpCc() {
544 PrintWriter pw = getOutPrintWriter();
545 pw.println("Carrier Config Commands:");
546 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
547 pw.println(" Print carrier config values.");
548 pw.println(" Options are:");
549 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
550 pw.println(" is specified, it will choose the default voice SIM slot.");
551 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
552 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100553 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100554 pw.println(" Set carrier config KEY to NEW_VALUE.");
555 pw.println(" Options are:");
556 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
557 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100558 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100559 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
560 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
561 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
562 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
563 pw.println(" cc clear-values [-s SLOT_ID]");
564 pw.println(" Clear all carrier override values that has previously been set");
565 pw.println(" with set-value");
566 pw.println(" Options are:");
567 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
568 pw.println(" is specified, it will choose the default voice SIM slot.");
569 }
570
Hui Wang641e81c2020-10-12 12:14:23 -0700571 private void onHelpGba() {
572 PrintWriter pw = getOutPrintWriter();
573 pw.println("Gba Commands:");
574 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
575 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
576 pw.println(" Options are:");
577 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
578 pw.println(" is specified, it will choose the default voice SIM slot.");
579 pw.println(" gba get-service [-s SLOT_ID]");
580 pw.println(" Gets the package name of the currently defined GbaService.");
581 pw.println(" Options are:");
582 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
583 pw.println(" is specified, it will choose the default voice SIM slot.");
584 pw.println(" gba set-release [-s SLOT_ID] n");
585 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
586 pw.println(" Do not release/unbind if n is -1.");
587 pw.println(" Options are:");
588 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
589 pw.println(" is specified, it will choose the default voice SIM slot.");
590 pw.println(" gba get-release [-s SLOT_ID]");
591 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
592 pw.println(" Options are:");
593 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
594 pw.println(" is specified, it will choose the default voice SIM slot.");
595 }
596
Hui Wang761a6682020-10-31 05:12:53 +0000597 private void onHelpSrc() {
598 PrintWriter pw = getOutPrintWriter();
599 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800600 pw.println(" src set-test-enabled true|false");
601 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
602 pw.println(" The value could be true, false, or null(undefined).");
603 pw.println(" src get-test-enabled");
604 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000605 pw.println(" src set-device-enabled true|false|null");
606 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
607 pw.println(" The value could be true, false, or null(undefined).");
608 pw.println(" src get-device-enabled");
609 pw.println(" Gets the device config for RCS VoLTE single registration.");
610 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
611 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
612 pw.println(" The value could be true, false, or null(undefined).");
613 pw.println(" Options are:");
614 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
615 pw.println(" is specified, it will choose the default voice SIM slot.");
616 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
617 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
618 pw.println(" Options are:");
619 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
620 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800621 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
622 pw.println(" Sets ims feature validation result.");
623 pw.println(" The value could be true, false, or null(undefined).");
624 pw.println(" Options are:");
625 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
626 pw.println(" is specified, it will choose the default voice SIM slot.");
627 pw.println(" src get-feature-validation [-s SLOT_ID]");
628 pw.println(" Gets ims feature validation override value.");
629 pw.println(" Options are:");
630 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
631 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000632 }
633
SongFerngWang98dd5992021-05-13 17:50:00 +0800634 private void onHelpAllowedNetworkTypes() {
635 PrintWriter pw = getOutPrintWriter();
636 pw.println("Allowed Network Types Commands:");
637 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
638 pw.println(" Print allowed network types value.");
639 pw.println(" Options are:");
640 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
641 pw.println(" option is specified, it will choose the default voice SIM slot.");
642 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
643 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
644 pw.println(" Options are:");
645 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
646 pw.println(" option is specified, it will choose the default voice SIM slot.");
647 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
648 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
649 pw.println(" at TelephonyManager.java");
650 pw.println(" For example:");
651 pw.println(" NR only : 10000000000000000000");
652 pw.println(" NR|LTE : 11000001000000000000");
653 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
654 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
655 pw.println(" LTE only : 01000001000000000000");
656 }
657
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700658 private int handleImsCommand() {
659 String arg = getNextArg();
660 if (arg == null) {
661 onHelpIms();
662 return 0;
663 }
664
665 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800666 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700667 return handleImsSetServiceCommand();
668 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800669 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700670 return handleImsGetServiceCommand();
671 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800672 case IMS_CLEAR_SERVICE_OVERRIDE: {
673 return handleImsClearCarrierServiceCommand();
674 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800675 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700676 return handleEnableIms();
677 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800678 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700679 return handleDisableIms();
680 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700681 case IMS_CEP: {
682 return handleCepChange();
683 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700684 }
685
686 return -1;
687 }
688
Shuo Qianf5125122019-12-16 17:03:07 -0800689 private int handleDataTestModeCommand() {
690 PrintWriter errPw = getErrPrintWriter();
691 String arg = getNextArgRequired();
692 if (arg == null) {
693 onHelpDataTestMode();
694 return 0;
695 }
696 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800697 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800698 try {
699 mInterface.enableDataConnectivity();
700 } catch (RemoteException ex) {
701 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
702 errPw.println("Exception: " + ex.getMessage());
703 return -1;
704 }
705 break;
706 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800707 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800708 try {
709 mInterface.disableDataConnectivity();
710 } catch (RemoteException ex) {
711 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
712 errPw.println("Exception: " + ex.getMessage());
713 return -1;
714 }
715 break;
716 }
717 default:
718 onHelpDataTestMode();
719 break;
720 }
721 return 0;
722 }
723
Shuo Qianccbaf742021-02-22 18:32:21 -0800724 private int handleEmergencyCallbackModeCommand() {
725 PrintWriter errPw = getErrPrintWriter();
726 try {
727 mInterface.startEmergencyCallbackMode();
728 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
729 } catch (RemoteException ex) {
730 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
731 errPw.println("Exception: " + ex.getMessage());
732 return -1;
733 }
734 return 0;
735 }
736
sqian9d4df8b2019-01-15 18:32:07 -0800737 private int handleEmergencyNumberTestModeCommand() {
738 PrintWriter errPw = getErrPrintWriter();
739 String opt = getNextOption();
740 if (opt == null) {
741 onHelpEmergencyNumber();
742 return 0;
743 }
744
745 switch (opt) {
746 case "-a": {
747 String emergencyNumberCmd = getNextArgRequired();
748 if (emergencyNumberCmd == null
749 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700750 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800751 + " to be specified after -a in the command ");
752 return -1;
753 }
754 try {
755 mInterface.updateEmergencyNumberListTestMode(
756 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
757 new EmergencyNumber(emergencyNumberCmd, "", "",
758 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
759 new ArrayList<String>(),
760 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
761 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
762 } catch (RemoteException ex) {
763 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
764 + ", error " + ex.getMessage());
765 errPw.println("Exception: " + ex.getMessage());
766 return -1;
767 }
768 break;
769 }
770 case "-c": {
771 try {
772 mInterface.updateEmergencyNumberListTestMode(
773 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
774 } catch (RemoteException ex) {
775 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
776 errPw.println("Exception: " + ex.getMessage());
777 return -1;
778 }
779 break;
780 }
781 case "-r": {
782 String emergencyNumberCmd = getNextArgRequired();
783 if (emergencyNumberCmd == null
784 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700785 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800786 + " to be specified after -r in the command ");
787 return -1;
788 }
789 try {
790 mInterface.updateEmergencyNumberListTestMode(
791 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
792 new EmergencyNumber(emergencyNumberCmd, "", "",
793 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
794 new ArrayList<String>(),
795 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
796 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
797 } catch (RemoteException ex) {
798 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
799 + ", error " + ex.getMessage());
800 errPw.println("Exception: " + ex.getMessage());
801 return -1;
802 }
803 break;
804 }
805 case "-p": {
806 try {
807 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
808 } catch (RemoteException ex) {
809 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
810 errPw.println("Exception: " + ex.getMessage());
811 return -1;
812 }
813 break;
814 }
815 default:
816 onHelpEmergencyNumber();
817 break;
818 }
819 return 0;
820 }
821
Hall Liud892bec2018-11-30 14:51:45 -0800822 private int handleNumberVerificationCommand() {
823 String arg = getNextArg();
824 if (arg == null) {
825 onHelpNumberVerification();
826 return 0;
827 }
828
Hall Liuca5af3a2018-12-04 16:58:23 -0800829 if (!checkShellUid()) {
830 return -1;
831 }
832
Hall Liud892bec2018-11-30 14:51:45 -0800833 switch (arg) {
834 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800835 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
836 return 0;
837 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800838 case NUMBER_VERIFICATION_FAKE_CALL: {
839 boolean val = NumberVerificationManager.getInstance()
840 .checkIncomingCall(getNextArg());
841 getOutPrintWriter().println(val ? "1" : "0");
842 return 0;
843 }
Hall Liud892bec2018-11-30 14:51:45 -0800844 }
845
846 return -1;
847 }
848
Jordan Liu0ccee222021-04-27 11:55:13 -0700849 private boolean subIsEsim(int subId) {
850 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
851 if (info != null) {
852 return info.isEmbedded();
853 }
854 return false;
855 }
856
857 private int handleEnablePhysicalSubscription(boolean enable) {
858 PrintWriter errPw = getErrPrintWriter();
859 int subId = 0;
860 try {
861 subId = Integer.parseInt(getNextArgRequired());
862 } catch (NumberFormatException e) {
863 errPw.println((enable ? "enable" : "disable")
864 + "-physical-subscription requires an integer as a subId.");
865 return -1;
866 }
867 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
868 // non user build.
869 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
870 errPw.println("cc: Permission denied.");
871 return -1;
872 }
873 // Verify that the subId represents a physical sub
874 if (subIsEsim(subId)) {
875 errPw.println("SubId " + subId + " is not for a physical subscription");
876 return -1;
877 }
878 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
879 + " physical subscription with subId=" + subId);
880 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
881 return 0;
882 }
883
Jack Nudelman644b91a2021-03-12 14:09:48 -0800884 private int handleThermalMitigationCommand() {
885 String arg = getNextArg();
886 String packageName = getNextArg();
887 if (arg == null || packageName == null) {
888 onHelpThermalMitigation();
889 return 0;
890 }
891
892 if (!checkShellUid()) {
893 return -1;
894 }
895
896 switch (arg) {
897 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
898 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
899 return 0;
900 }
901 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
902 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
903 mContext);
904 return 0;
905 }
906 default:
907 onHelpThermalMitigation();
908 }
909
910 return -1;
911
912 }
913
Tyler Gunn92479152021-01-20 16:30:10 -0800914 private int handleD2dCommand() {
915 String arg = getNextArg();
916 if (arg == null) {
917 onHelpD2D();
918 return 0;
919 }
920
921 switch (arg) {
922 case D2D_SEND: {
923 return handleD2dSendCommand();
924 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800925 case D2D_TRANSPORT: {
926 return handleD2dTransportCommand();
927 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700928 case D2D_SET_DEVICE_SUPPORT: {
929 return handleD2dDeviceSupportedCommand();
930 }
Tyler Gunn92479152021-01-20 16:30:10 -0800931 }
932
933 return -1;
934 }
935
936 private int handleD2dSendCommand() {
937 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800938 int messageType = -1;
939 int messageValue = -1;
940
Tyler Gunn92479152021-01-20 16:30:10 -0800941 String arg = getNextArg();
942 if (arg == null) {
943 onHelpD2D();
944 return 0;
945 }
946 try {
947 messageType = Integer.parseInt(arg);
948 } catch (NumberFormatException e) {
949 errPw.println("message type must be a valid integer");
950 return -1;
951 }
952
953 arg = getNextArg();
954 if (arg == null) {
955 onHelpD2D();
956 return 0;
957 }
958 try {
959 messageValue = Integer.parseInt(arg);
960 } catch (NumberFormatException e) {
961 errPw.println("message value must be a valid integer");
962 return -1;
963 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800964
Tyler Gunn92479152021-01-20 16:30:10 -0800965 try {
966 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
967 } catch (RemoteException e) {
968 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
969 errPw.println("Exception: " + e.getMessage());
970 return -1;
971 }
972
973 return 0;
974 }
975
Tyler Gunnbabbda02021-02-10 11:05:02 -0800976 private int handleD2dTransportCommand() {
977 PrintWriter errPw = getErrPrintWriter();
978
979 String arg = getNextArg();
980 if (arg == null) {
981 onHelpD2D();
982 return 0;
983 }
984
985 try {
986 mInterface.setActiveDeviceToDeviceTransport(arg);
987 } catch (RemoteException e) {
988 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
989 errPw.println("Exception: " + e.getMessage());
990 return -1;
991 }
992 return 0;
993 }
Nazanin014f41e2021-05-06 17:26:31 -0700994 private int handleBarringCommand() {
995 String arg = getNextArg();
996 if (arg == null) {
997 onHelpBarring();
998 return 0;
999 }
1000
1001 switch (arg) {
1002 case BARRING_SEND_INFO: {
1003 return handleBarringSendCommand();
1004 }
1005 }
1006 return -1;
1007 }
1008
1009 private int handleBarringSendCommand() {
1010 PrintWriter errPw = getErrPrintWriter();
1011 int slotId = getDefaultSlot();
1012 int subId = SubscriptionManager.getSubId(slotId)[0];
1013 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1014 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1015 boolean isConditionallyBarred = false;
1016 int conditionalBarringTimeSeconds = 0;
1017
1018 String opt;
1019 while ((opt = getNextOption()) != null) {
1020 switch (opt) {
1021 case "-s": {
1022 try {
1023 slotId = Integer.parseInt(getNextArgRequired());
1024 subId = SubscriptionManager.getSubId(slotId)[0];
1025 } catch (NumberFormatException e) {
1026 errPw.println("barring send requires an integer as a SLOT_ID.");
1027 return -1;
1028 }
1029 break;
1030 }
1031 case "-b": {
1032 try {
1033 barringType = Integer.parseInt(getNextArgRequired());
1034 if (barringType < -1 || barringType > 2) {
1035 throw new NumberFormatException();
1036 }
1037
1038 } catch (NumberFormatException e) {
1039 errPw.println("barring send requires an integer in range [-1,2] as "
1040 + "a BARRING_TYPE.");
1041 return -1;
1042 }
1043 break;
1044 }
1045 case "-c": {
1046 try {
1047 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1048 } catch (Exception e) {
1049 errPw.println("barring send requires a boolean after -c indicating"
1050 + " conditional barring");
1051 return -1;
1052 }
1053 break;
1054 }
1055 case "-t": {
1056 try {
1057 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1058 } catch (NumberFormatException e) {
1059 errPw.println("barring send requires an integer for time of barring"
1060 + " in seconds after -t for conditional barring");
1061 return -1;
1062 }
1063 break;
1064 }
1065 }
1066 }
1067 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1068 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1069 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1070 barringServiceInfos.append(0, bsi);
1071 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1072 try {
1073 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1074 } catch (Exception e) {
1075 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1076 errPw.println("Exception: " + e.getMessage());
1077 return -1;
1078 }
1079 return 0;
1080 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001081
Tyler Gunnd4575212021-05-03 14:46:49 -07001082 private int handleD2dDeviceSupportedCommand() {
1083 PrintWriter errPw = getErrPrintWriter();
1084
1085 String arg = getNextArg();
1086 if (arg == null) {
1087 onHelpD2D();
1088 return 0;
1089 }
1090
1091 boolean isEnabled = "true".equals(arg.toLowerCase());
1092 try {
1093 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1094 } catch (RemoteException e) {
1095 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1096 errPw.println("Exception: " + e.getMessage());
1097 return -1;
1098 }
1099 return 0;
1100 }
1101
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001102 // ims set-ims-service
1103 private int handleImsSetServiceCommand() {
1104 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001105 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001106 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001107 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001108
1109 String opt;
1110 while ((opt = getNextOption()) != null) {
1111 switch (opt) {
1112 case "-s": {
1113 try {
1114 slotId = Integer.parseInt(getNextArgRequired());
1115 } catch (NumberFormatException e) {
1116 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1117 return -1;
1118 }
1119 break;
1120 }
1121 case "-c": {
1122 isCarrierService = true;
1123 break;
1124 }
1125 case "-d": {
1126 isCarrierService = false;
1127 break;
1128 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001129 case "-f": {
1130 String featureString = getNextArgRequired();
1131 String[] features = featureString.split(",");
1132 for (int i = 0; i < features.length; i++) {
1133 try {
1134 Integer result = Integer.parseInt(features[i]);
1135 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1136 || result >= ImsFeature.FEATURE_MAX) {
1137 errPw.println("ims set-ims-service -f " + result
1138 + " is an invalid feature.");
1139 return -1;
1140 }
1141 featuresList.add(result);
1142 } catch (NumberFormatException e) {
1143 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1144 + " as an integer.");
1145 return -1;
1146 }
1147 }
1148 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001149 }
1150 }
1151 // Mandatory param, either -c or -d
1152 if (isCarrierService == null) {
1153 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1154 return -1;
1155 }
1156
1157 String packageName = getNextArg();
1158
1159 try {
1160 if (packageName == null) {
1161 packageName = "";
1162 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001163 int[] featureArray = new int[featuresList.size()];
1164 for (int i = 0; i < featuresList.size(); i++) {
1165 featureArray[i] = featuresList.get(i);
1166 }
1167 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1168 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001169 if (VDBG) {
1170 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001171 + (isCarrierService ? "-c " : "-d ")
1172 + "-f " + featuresList + " "
1173 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001174 }
1175 getOutPrintWriter().println(result);
1176 } catch (RemoteException e) {
1177 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001178 + (isCarrierService ? "-c " : "-d ")
1179 + "-f " + featuresList + " "
1180 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001181 errPw.println("Exception: " + e.getMessage());
1182 return -1;
1183 }
1184 return 0;
1185 }
1186
Brad Ebinger999d3302020-11-25 14:31:39 -08001187 // ims clear-ims-service-override
1188 private int handleImsClearCarrierServiceCommand() {
1189 PrintWriter errPw = getErrPrintWriter();
1190 int slotId = getDefaultSlot();
1191
1192 String opt;
1193 while ((opt = getNextOption()) != null) {
1194 switch (opt) {
1195 case "-s": {
1196 try {
1197 slotId = Integer.parseInt(getNextArgRequired());
1198 } catch (NumberFormatException e) {
1199 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1200 return -1;
1201 }
1202 break;
1203 }
1204 }
1205 }
1206
1207 try {
1208 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1209 if (VDBG) {
1210 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1211 + ", result=" + result);
1212 }
1213 getOutPrintWriter().println(result);
1214 } catch (RemoteException e) {
1215 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1216 + ", error" + e.getMessage());
1217 errPw.println("Exception: " + e.getMessage());
1218 return -1;
1219 }
1220 return 0;
1221 }
1222
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001223 // ims get-ims-service
1224 private int handleImsGetServiceCommand() {
1225 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001226 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001227 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001228 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001229
1230 String opt;
1231 while ((opt = getNextOption()) != null) {
1232 switch (opt) {
1233 case "-s": {
1234 try {
1235 slotId = Integer.parseInt(getNextArgRequired());
1236 } catch (NumberFormatException e) {
1237 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1238 return -1;
1239 }
1240 break;
1241 }
1242 case "-c": {
1243 isCarrierService = true;
1244 break;
1245 }
1246 case "-d": {
1247 isCarrierService = false;
1248 break;
1249 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001250 case "-f": {
1251 try {
1252 featureType = Integer.parseInt(getNextArg());
1253 } catch (NumberFormatException e) {
1254 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1255 return -1;
1256 }
1257 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1258 || featureType >= ImsFeature.FEATURE_MAX) {
1259 errPw.println("ims get-ims-service -f invalid feature.");
1260 return -1;
1261 }
1262 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001263 }
1264 }
1265 // Mandatory param, either -c or -d
1266 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001267 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001268 return -1;
1269 }
1270
1271 String result;
1272 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001273 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001274 } catch (RemoteException e) {
1275 return -1;
1276 }
1277 if (VDBG) {
1278 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001279 + (isCarrierService ? "-c " : "-d ")
1280 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1281 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001282 }
1283 getOutPrintWriter().println(result);
1284 return 0;
1285 }
1286
1287 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001288 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001289 String opt;
1290 while ((opt = getNextOption()) != null) {
1291 switch (opt) {
1292 case "-s": {
1293 try {
1294 slotId = Integer.parseInt(getNextArgRequired());
1295 } catch (NumberFormatException e) {
1296 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1297 return -1;
1298 }
1299 break;
1300 }
1301 }
1302 }
1303 try {
1304 mInterface.enableIms(slotId);
1305 } catch (RemoteException e) {
1306 return -1;
1307 }
1308 if (VDBG) {
1309 Log.v(LOG_TAG, "ims enable -s " + slotId);
1310 }
1311 return 0;
1312 }
1313
1314 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001315 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001316 String opt;
1317 while ((opt = getNextOption()) != null) {
1318 switch (opt) {
1319 case "-s": {
1320 try {
1321 slotId = Integer.parseInt(getNextArgRequired());
1322 } catch (NumberFormatException e) {
1323 getErrPrintWriter().println(
1324 "ims disable requires an integer as a SLOT_ID.");
1325 return -1;
1326 }
1327 break;
1328 }
1329 }
1330 }
1331 try {
1332 mInterface.disableIms(slotId);
1333 } catch (RemoteException e) {
1334 return -1;
1335 }
1336 if (VDBG) {
1337 Log.v(LOG_TAG, "ims disable -s " + slotId);
1338 }
1339 return 0;
1340 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001341
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001342 private int handleCepChange() {
1343 Log.i(LOG_TAG, "handleCepChange");
1344 String opt = getNextArg();
1345 if (opt == null) {
1346 return -1;
1347 }
1348 boolean isCepEnabled = opt.equals("enable");
1349
1350 try {
1351 mInterface.setCepEnabled(isCepEnabled);
1352 } catch (RemoteException e) {
1353 return -1;
1354 }
1355 return 0;
1356 }
1357
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001358 private int getDefaultSlot() {
1359 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1360 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1361 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1362 // If there is no default, default to slot 0.
1363 slotId = DEFAULT_PHONE_ID;
1364 }
1365 return slotId;
1366 }
sqian2fff4a32018-11-05 14:18:37 -08001367
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001368 // Parse options related to Carrier Config Commands.
1369 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001370 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001371 CcOptionParseResult result = new CcOptionParseResult();
1372 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1373 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001374
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001375 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001376 while ((opt = getNextOption()) != null) {
1377 switch (opt) {
1378 case "-s": {
1379 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001380 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1381 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1382 errPw.println(tag + "No valid subscription found.");
1383 return null;
1384 }
1385
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001386 } catch (IllegalArgumentException e) {
1387 // Missing slot id
1388 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001389 return null;
1390 }
1391 break;
1392 }
1393 case "-p": {
1394 if (allowOptionPersistent) {
1395 result.mPersistent = true;
1396 } else {
1397 errPw.println(tag + "Unexpected option " + opt);
1398 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001399 }
1400 break;
1401 }
1402 default: {
1403 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001404 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001405 }
1406 }
1407 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001408 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001409 }
1410
1411 private int slotStringToSubId(String tag, String slotString) {
1412 int slotId = -1;
1413 try {
1414 slotId = Integer.parseInt(slotString);
1415 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001416 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1417 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1418 }
1419
1420 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001421 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1422 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1423 }
1424
Qiong Liuf25799b2020-09-10 10:13:46 +08001425 Phone phone = PhoneFactory.getPhone(slotId);
1426 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001427 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1428 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1429 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001430 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001431 }
1432
Hall Liud892bec2018-11-30 14:51:45 -08001433 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001434 // adb can run as root or as shell, depending on whether the device is rooted.
1435 return Binder.getCallingUid() == Process.SHELL_UID
1436 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001437 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001438
1439 private int handleCcCommand() {
1440 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1441 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001442 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001443 getErrPrintWriter().println("cc: Permission denied.");
1444 return -1;
1445 }
1446
1447 String arg = getNextArg();
1448 if (arg == null) {
1449 onHelpCc();
1450 return 0;
1451 }
1452
1453 switch (arg) {
1454 case CC_GET_VALUE: {
1455 return handleCcGetValue();
1456 }
1457 case CC_SET_VALUE: {
1458 return handleCcSetValue();
1459 }
1460 case CC_CLEAR_VALUES: {
1461 return handleCcClearValues();
1462 }
1463 default: {
1464 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1465 }
1466 }
1467 return -1;
1468 }
1469
1470 // cc get-value
1471 private int handleCcGetValue() {
1472 PrintWriter errPw = getErrPrintWriter();
1473 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1474 String key = null;
1475
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001476 // Parse all options
1477 CcOptionParseResult options = parseCcOptions(tag, false);
1478 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001479 return -1;
1480 }
1481
1482 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001483 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001484 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001485 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001486 return -1;
1487 }
1488
1489 // Get the key.
1490 key = getNextArg();
1491 if (key != null) {
1492 // A key was provided. Verify if it is a valid key
1493 if (!bundle.containsKey(key)) {
1494 errPw.println(tag + key + " is not a valid key.");
1495 return -1;
1496 }
1497
1498 // Print the carrier config value for key.
1499 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1500 } else {
1501 // No key provided. Show all values.
1502 // Iterate over a sorted list of all carrier config keys and print them.
1503 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1504 for (String k : sortedSet) {
1505 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1506 }
1507 }
1508 return 0;
1509 }
1510
1511 // cc set-value
1512 private int handleCcSetValue() {
1513 PrintWriter errPw = getErrPrintWriter();
1514 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1515
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001516 // Parse all options
1517 CcOptionParseResult options = parseCcOptions(tag, true);
1518 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001519 return -1;
1520 }
1521
1522 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001523 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001524 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001525 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001526 return -1;
1527 }
1528
1529 // Get the key.
1530 String key = getNextArg();
1531 if (key == null || key.equals("")) {
1532 errPw.println(tag + "KEY is missing");
1533 return -1;
1534 }
1535
1536 // Verify if the key is valid
1537 if (!originalValues.containsKey(key)) {
1538 errPw.println(tag + key + " is not a valid key.");
1539 return -1;
1540 }
1541
1542 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1543 ArrayList<String> valueList = new ArrayList<String>();
1544 while (peekNextArg() != null) {
1545 valueList.add(getNextArg());
1546 }
1547
1548 // Find the type of the carrier config value
1549 CcType type = getType(tag, key, originalValues);
1550 if (type == CcType.UNKNOWN) {
1551 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1552 return -1;
1553 }
1554
1555 // Create an override bundle containing the key and value that should be overriden.
1556 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1557 if (overrideBundle == null) {
1558 return -1;
1559 }
1560
1561 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001562 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001563
1564 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001565 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001566 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001567 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001568 return -1;
1569 }
1570
1571 // Print the original and new value.
1572 String originalValueString = ccValueToString(key, type, originalValues);
1573 String newValueString = ccValueToString(key, type, newValues);
1574 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1575 getOutPrintWriter().println("New value: \n" + newValueString);
1576
1577 return 0;
1578 }
1579
1580 // cc clear-values
1581 private int handleCcClearValues() {
1582 PrintWriter errPw = getErrPrintWriter();
1583 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1584
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001585 // Parse all options
1586 CcOptionParseResult options = parseCcOptions(tag, false);
1587 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001588 return -1;
1589 }
1590
1591 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001592 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001593 getOutPrintWriter()
1594 .println("All previously set carrier config override values has been cleared");
1595 return 0;
1596 }
1597
1598 private CcType getType(String tag, String key, PersistableBundle bundle) {
1599 // Find the type by checking the type of the current value stored in the bundle.
1600 Object value = bundle.get(key);
1601
1602 if (CC_TYPE_MAP.containsKey(key)) {
1603 return CC_TYPE_MAP.get(key);
1604 } else if (value != null) {
1605 if (value instanceof Boolean) {
1606 return CcType.BOOLEAN;
1607 } else if (value instanceof Double) {
1608 return CcType.DOUBLE;
1609 } else if (value instanceof double[]) {
1610 return CcType.DOUBLE_ARRAY;
1611 } else if (value instanceof Integer) {
1612 return CcType.INT;
1613 } else if (value instanceof int[]) {
1614 return CcType.INT_ARRAY;
1615 } else if (value instanceof Long) {
1616 return CcType.LONG;
1617 } else if (value instanceof long[]) {
1618 return CcType.LONG_ARRAY;
1619 } else if (value instanceof String) {
1620 return CcType.STRING;
1621 } else if (value instanceof String[]) {
1622 return CcType.STRING_ARRAY;
1623 }
1624 } else {
1625 // Current value was null and can therefore not be used in order to find the type.
1626 // Check the name of the key to infer the type. This check is not needed for primitive
1627 // data types (boolean, double, int and long), since they can not be null.
1628 if (key.endsWith("double_array")) {
1629 return CcType.DOUBLE_ARRAY;
1630 }
1631 if (key.endsWith("int_array")) {
1632 return CcType.INT_ARRAY;
1633 }
1634 if (key.endsWith("long_array")) {
1635 return CcType.LONG_ARRAY;
1636 }
1637 if (key.endsWith("string")) {
1638 return CcType.STRING;
1639 }
1640 if (key.endsWith("string_array") || key.endsWith("strings")) {
1641 return CcType.STRING_ARRAY;
1642 }
1643 }
1644
1645 // Not possible to infer the type by looking at the current value or the key.
1646 PrintWriter errPw = getErrPrintWriter();
1647 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1648 return CcType.UNKNOWN;
1649 }
1650
1651 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1652 String result;
1653 StringBuilder valueString = new StringBuilder();
1654 String typeString = type.toString();
1655 Object value = bundle.get(key);
1656
1657 if (value == null) {
1658 valueString.append("null");
1659 } else {
1660 switch (type) {
1661 case DOUBLE_ARRAY: {
1662 // Format the string representation of the int array as value1 value2......
1663 double[] valueArray = (double[]) value;
1664 for (int i = 0; i < valueArray.length; i++) {
1665 if (i != 0) {
1666 valueString.append(" ");
1667 }
1668 valueString.append(valueArray[i]);
1669 }
1670 break;
1671 }
1672 case INT_ARRAY: {
1673 // Format the string representation of the int array as value1 value2......
1674 int[] valueArray = (int[]) value;
1675 for (int i = 0; i < valueArray.length; i++) {
1676 if (i != 0) {
1677 valueString.append(" ");
1678 }
1679 valueString.append(valueArray[i]);
1680 }
1681 break;
1682 }
1683 case LONG_ARRAY: {
1684 // Format the string representation of the int array as value1 value2......
1685 long[] valueArray = (long[]) value;
1686 for (int i = 0; i < valueArray.length; i++) {
1687 if (i != 0) {
1688 valueString.append(" ");
1689 }
1690 valueString.append(valueArray[i]);
1691 }
1692 break;
1693 }
1694 case STRING: {
1695 valueString.append("\"" + value.toString() + "\"");
1696 break;
1697 }
1698 case STRING_ARRAY: {
1699 // Format the string representation of the string array as "value1" "value2"....
1700 String[] valueArray = (String[]) value;
1701 for (int i = 0; i < valueArray.length; i++) {
1702 if (i != 0) {
1703 valueString.append(" ");
1704 }
1705 if (valueArray[i] != null) {
1706 valueString.append("\"" + valueArray[i] + "\"");
1707 } else {
1708 valueString.append("null");
1709 }
1710 }
1711 break;
1712 }
1713 default: {
1714 valueString.append(value.toString());
1715 }
1716 }
1717 }
1718 return String.format("%-70s %-15s %s", key, typeString, valueString);
1719 }
1720
1721 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1722 ArrayList<String> valueList) {
1723 PrintWriter errPw = getErrPrintWriter();
1724 PersistableBundle bundle = new PersistableBundle();
1725
1726 // First verify that a valid number of values has been provided for the type.
1727 switch (type) {
1728 case BOOLEAN:
1729 case DOUBLE:
1730 case INT:
1731 case LONG: {
1732 if (valueList.size() != 1) {
1733 errPw.println(tag + "Expected 1 value for type " + type
1734 + ". Found: " + valueList.size());
1735 return null;
1736 }
1737 break;
1738 }
1739 case STRING: {
1740 if (valueList.size() > 1) {
1741 errPw.println(tag + "Expected 0 or 1 values for type " + type
1742 + ". Found: " + valueList.size());
1743 return null;
1744 }
1745 break;
1746 }
1747 }
1748
1749 // Parse the value according to type and add it to the Bundle.
1750 switch (type) {
1751 case BOOLEAN: {
1752 if ("true".equalsIgnoreCase(valueList.get(0))) {
1753 bundle.putBoolean(key, true);
1754 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1755 bundle.putBoolean(key, false);
1756 } else {
1757 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1758 return null;
1759 }
1760 break;
1761 }
1762 case DOUBLE: {
1763 try {
1764 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1765 } catch (NumberFormatException nfe) {
1766 // Not a valid double
1767 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1768 return null;
1769 }
1770 break;
1771 }
1772 case DOUBLE_ARRAY: {
1773 double[] valueDoubleArray = null;
1774 if (valueList.size() > 0) {
1775 valueDoubleArray = new double[valueList.size()];
1776 for (int i = 0; i < valueList.size(); i++) {
1777 try {
1778 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1779 } catch (NumberFormatException nfe) {
1780 // Not a valid double
1781 errPw.println(
1782 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1783 return null;
1784 }
1785 }
1786 }
1787 bundle.putDoubleArray(key, valueDoubleArray);
1788 break;
1789 }
1790 case INT: {
1791 try {
1792 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1793 } catch (NumberFormatException nfe) {
1794 // Not a valid integer
1795 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1796 return null;
1797 }
1798 break;
1799 }
1800 case INT_ARRAY: {
1801 int[] valueIntArray = null;
1802 if (valueList.size() > 0) {
1803 valueIntArray = new int[valueList.size()];
1804 for (int i = 0; i < valueList.size(); i++) {
1805 try {
1806 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1807 } catch (NumberFormatException nfe) {
1808 // Not a valid integer
1809 errPw.println(tag
1810 + "Unable to parse " + valueList.get(i) + " as an integer.");
1811 return null;
1812 }
1813 }
1814 }
1815 bundle.putIntArray(key, valueIntArray);
1816 break;
1817 }
1818 case LONG: {
1819 try {
1820 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1821 } catch (NumberFormatException nfe) {
1822 // Not a valid long
1823 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1824 return null;
1825 }
1826 break;
1827 }
1828 case LONG_ARRAY: {
1829 long[] valueLongArray = null;
1830 if (valueList.size() > 0) {
1831 valueLongArray = new long[valueList.size()];
1832 for (int i = 0; i < valueList.size(); i++) {
1833 try {
1834 valueLongArray[i] = Long.parseLong(valueList.get(i));
1835 } catch (NumberFormatException nfe) {
1836 // Not a valid long
1837 errPw.println(
1838 tag + "Unable to parse " + valueList.get(i) + " as a long");
1839 return null;
1840 }
1841 }
1842 }
1843 bundle.putLongArray(key, valueLongArray);
1844 break;
1845 }
1846 case STRING: {
1847 String value = null;
1848 if (valueList.size() > 0) {
1849 value = valueList.get(0);
1850 }
1851 bundle.putString(key, value);
1852 break;
1853 }
1854 case STRING_ARRAY: {
1855 String[] valueStringArray = null;
1856 if (valueList.size() > 0) {
1857 valueStringArray = new String[valueList.size()];
1858 valueList.toArray(valueStringArray);
1859 }
1860 bundle.putStringArray(key, valueStringArray);
1861 break;
1862 }
1863 }
1864 return bundle;
1865 }
Shuo Qian489d9282020-07-09 11:30:03 -07001866
1867 private int handleEndBlockSuppressionCommand() {
1868 if (!checkShellUid()) {
1869 return -1;
1870 }
1871
1872 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1873 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1874 }
1875 return 0;
1876 }
Hui Wang641e81c2020-10-12 12:14:23 -07001877
Michele Berionne54af4632020-12-28 20:23:16 +00001878 private int handleRestartModemCommand() {
1879 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1880 // non user build.
1881 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1882 getErrPrintWriter().println("RestartModem: Permission denied.");
1883 return -1;
1884 }
1885
1886 boolean result = TelephonyManager.getDefault().rebootRadio();
1887 getOutPrintWriter().println(result);
1888
1889 return result ? 0 : -1;
1890 }
1891
Michele Berionne5e411512020-11-13 02:36:59 +00001892 private int handleUnattendedReboot() {
1893 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1894 // non user build.
1895 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1896 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1897 return -1;
1898 }
1899
1900 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1901 getOutPrintWriter().println("result: " + result);
1902
1903 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1904 }
1905
Hui Wang641e81c2020-10-12 12:14:23 -07001906 private int handleGbaCommand() {
1907 String arg = getNextArg();
1908 if (arg == null) {
1909 onHelpGba();
1910 return 0;
1911 }
1912
1913 switch (arg) {
1914 case GBA_SET_SERVICE: {
1915 return handleGbaSetServiceCommand();
1916 }
1917 case GBA_GET_SERVICE: {
1918 return handleGbaGetServiceCommand();
1919 }
1920 case GBA_SET_RELEASE_TIME: {
1921 return handleGbaSetReleaseCommand();
1922 }
1923 case GBA_GET_RELEASE_TIME: {
1924 return handleGbaGetReleaseCommand();
1925 }
1926 }
1927
1928 return -1;
1929 }
1930
1931 private int getSubId(String cmd) {
1932 int slotId = getDefaultSlot();
1933 String opt = getNextOption();
1934 if (opt != null && opt.equals("-s")) {
1935 try {
1936 slotId = Integer.parseInt(getNextArgRequired());
1937 } catch (NumberFormatException e) {
1938 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1939 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1940 }
1941 }
1942 int[] subIds = SubscriptionManager.getSubId(slotId);
1943 return subIds[0];
1944 }
1945
1946 private int handleGbaSetServiceCommand() {
1947 int subId = getSubId("gba set-service");
1948 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1949 return -1;
1950 }
1951
1952 String packageName = getNextArg();
1953 try {
1954 if (packageName == null) {
1955 packageName = "";
1956 }
1957 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1958 if (VDBG) {
1959 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1960 + packageName + ", result=" + result);
1961 }
1962 getOutPrintWriter().println(result);
1963 } catch (RemoteException e) {
1964 Log.w(LOG_TAG, "gba set-service " + subId + " "
1965 + packageName + ", error" + e.getMessage());
1966 getErrPrintWriter().println("Exception: " + e.getMessage());
1967 return -1;
1968 }
1969 return 0;
1970 }
1971
1972 private int handleGbaGetServiceCommand() {
1973 String result;
1974
1975 int subId = getSubId("gba get-service");
1976 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1977 return -1;
1978 }
1979
1980 try {
1981 result = mInterface.getBoundGbaService(subId);
1982 } catch (RemoteException e) {
1983 return -1;
1984 }
1985 if (VDBG) {
1986 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1987 }
1988 getOutPrintWriter().println(result);
1989 return 0;
1990 }
1991
1992 private int handleGbaSetReleaseCommand() {
1993 //the release time value could be -1
1994 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1995 : SubscriptionManager.getDefaultSubscriptionId();
1996 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1997 return -1;
1998 }
1999
2000 String intervalStr = getNextArg();
2001 if (intervalStr == null) {
2002 return -1;
2003 }
2004
2005 try {
2006 int interval = Integer.parseInt(intervalStr);
2007 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2008 if (VDBG) {
2009 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2010 + intervalStr + ", result=" + result);
2011 }
2012 getOutPrintWriter().println(result);
2013 } catch (NumberFormatException | RemoteException e) {
2014 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2015 + intervalStr + ", error" + e.getMessage());
2016 getErrPrintWriter().println("Exception: " + e.getMessage());
2017 return -1;
2018 }
2019 return 0;
2020 }
2021
2022 private int handleGbaGetReleaseCommand() {
2023 int subId = getSubId("gba get-release");
2024 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2025 return -1;
2026 }
2027
2028 int result = 0;
2029 try {
2030 result = mInterface.getGbaReleaseTime(subId);
2031 } catch (RemoteException e) {
2032 return -1;
2033 }
2034 if (VDBG) {
2035 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2036 }
2037 getOutPrintWriter().println(result);
2038 return 0;
2039 }
Hui Wang761a6682020-10-31 05:12:53 +00002040
2041 private int handleSingleRegistrationConfigCommand() {
2042 String arg = getNextArg();
2043 if (arg == null) {
2044 onHelpSrc();
2045 return 0;
2046 }
2047
2048 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002049 case SRC_SET_TEST_ENABLED: {
2050 return handleSrcSetTestEnabledCommand();
2051 }
2052 case SRC_GET_TEST_ENABLED: {
2053 return handleSrcGetTestEnabledCommand();
2054 }
Hui Wang761a6682020-10-31 05:12:53 +00002055 case SRC_SET_DEVICE_ENABLED: {
2056 return handleSrcSetDeviceEnabledCommand();
2057 }
2058 case SRC_GET_DEVICE_ENABLED: {
2059 return handleSrcGetDeviceEnabledCommand();
2060 }
2061 case SRC_SET_CARRIER_ENABLED: {
2062 return handleSrcSetCarrierEnabledCommand();
2063 }
2064 case SRC_GET_CARRIER_ENABLED: {
2065 return handleSrcGetCarrierEnabledCommand();
2066 }
Hui Wangb647abe2021-02-26 09:33:38 -08002067 case SRC_SET_FEATURE_ENABLED: {
2068 return handleSrcSetFeatureValidationCommand();
2069 }
2070 case SRC_GET_FEATURE_ENABLED: {
2071 return handleSrcGetFeatureValidationCommand();
2072 }
Hui Wang761a6682020-10-31 05:12:53 +00002073 }
2074
2075 return -1;
2076 }
2077
James.cf Linbcdf8b32021-01-14 16:44:13 +08002078 private int handleRcsUceCommand() {
2079 String arg = getNextArg();
2080 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002081 onHelpUce();
2082 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002083 }
2084
2085 switch (arg) {
2086 case UCE_REMOVE_EAB_CONTACT:
2087 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002088 case UCE_GET_EAB_CONTACT:
2089 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002090 case UCE_GET_DEVICE_ENABLED:
2091 return handleUceGetDeviceEnabledCommand();
2092 case UCE_SET_DEVICE_ENABLED:
2093 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002094 case UCE_OVERRIDE_PUBLISH_CAPS:
2095 return handleUceOverridePublishCaps();
2096 case UCE_GET_LAST_PIDF_XML:
2097 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002098 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2099 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002100 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2101 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002102 }
2103 return -1;
2104 }
2105
2106 private int handleRemovingEabContactCommand() {
2107 int subId = getSubId("uce remove-eab-contact");
2108 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2109 return -1;
2110 }
2111
2112 String phoneNumber = getNextArgRequired();
2113 if (TextUtils.isEmpty(phoneNumber)) {
2114 return -1;
2115 }
2116 int result = 0;
2117 try {
2118 result = mInterface.removeContactFromEab(subId, phoneNumber);
2119 } catch (RemoteException e) {
2120 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2121 getErrPrintWriter().println("Exception: " + e.getMessage());
2122 return -1;
2123 }
2124
2125 if (VDBG) {
2126 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2127 }
calvinpan293ea1b2021-02-04 17:52:13 +08002128 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002129 }
2130
calvinpane4a8a1d2021-01-25 13:51:18 +08002131 private int handleGettingEabContactCommand() {
2132 String phoneNumber = getNextArgRequired();
2133 if (TextUtils.isEmpty(phoneNumber)) {
2134 return -1;
2135 }
2136 String result = "";
2137 try {
2138 result = mInterface.getContactFromEab(phoneNumber);
2139
2140 } catch (RemoteException e) {
2141 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2142 getErrPrintWriter().println("Exception: " + e.getMessage());
2143 return -1;
2144 }
2145
2146 if (VDBG) {
2147 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2148 }
calvinpan293ea1b2021-02-04 17:52:13 +08002149 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002150 return 0;
2151 }
2152
2153 private int handleUceGetDeviceEnabledCommand() {
2154 boolean result = false;
2155 try {
2156 result = mInterface.getDeviceUceEnabled();
2157 } catch (RemoteException e) {
2158 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2159 return -1;
2160 }
2161 if (VDBG) {
2162 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2163 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002164 getOutPrintWriter().println(result);
2165 return 0;
2166 }
2167
James.cf Lin4b784aa2021-01-31 03:25:15 +08002168 private int handleUceSetDeviceEnabledCommand() {
2169 String enabledStr = getNextArg();
2170 if (TextUtils.isEmpty(enabledStr)) {
2171 return -1;
2172 }
2173
2174 try {
2175 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2176 mInterface.setDeviceUceEnabled(isEnabled);
2177 if (VDBG) {
2178 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2179 }
2180 } catch (NumberFormatException | RemoteException e) {
2181 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2182 getErrPrintWriter().println("Exception: " + e.getMessage());
2183 return -1;
2184 }
2185 return 0;
2186 }
2187
James.cf Line8713a42021-04-29 16:04:26 +08002188 private int handleUceRemoveRequestDisallowedStatus() {
2189 int subId = getSubId("uce remove-request-disallowed-status");
2190 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2191 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2192 return -1;
2193 }
2194 boolean result;
2195 try {
2196 result = mInterface.removeUceRequestDisallowedStatus(subId);
2197 } catch (RemoteException e) {
2198 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2199 return -1;
2200 }
2201 if (VDBG) {
2202 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2203 }
2204 getOutPrintWriter().println(result);
2205 return 0;
2206 }
2207
James.cf Lin0fc71b02021-05-25 01:37:38 +08002208 private int handleUceSetCapRequestTimeout() {
2209 int subId = getSubId("uce set-capabilities-request-timeout");
2210 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2211 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2212 return -1;
2213 }
2214 long timeoutAfterMs = Long.valueOf(getNextArg());
2215 boolean result;
2216 try {
2217 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2218 } catch (RemoteException e) {
2219 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2220 return -1;
2221 }
2222 if (VDBG) {
2223 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2224 }
2225 getOutPrintWriter().println(result);
2226 return 0;
2227 }
2228
Hui Wangbaaee6a2021-02-19 20:45:36 -08002229 private int handleSrcSetTestEnabledCommand() {
2230 String enabledStr = getNextArg();
2231 if (enabledStr == null) {
2232 return -1;
2233 }
2234
2235 try {
2236 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2237 if (VDBG) {
2238 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2239 }
2240 getOutPrintWriter().println("Done");
2241 } catch (NumberFormatException | RemoteException e) {
2242 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2243 getErrPrintWriter().println("Exception: " + e.getMessage());
2244 return -1;
2245 }
2246 return 0;
2247 }
2248
2249 private int handleSrcGetTestEnabledCommand() {
2250 boolean result = false;
2251 try {
2252 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2253 } catch (RemoteException e) {
2254 return -1;
2255 }
2256 if (VDBG) {
2257 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2258 }
2259 getOutPrintWriter().println(result);
2260 return 0;
2261 }
2262
Brad Ebinger14d467f2021-02-12 06:18:28 +00002263 private int handleUceOverridePublishCaps() {
2264 int subId = getSubId("uce override-published-caps");
2265 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2266 return -1;
2267 }
2268 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2269 String operation = getNextArgRequired();
2270 String caps = getNextArg();
2271 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2272 && !"list".equals(operation)) {
2273 getErrPrintWriter().println("Invalid operation: " + operation);
2274 return -1;
2275 }
2276
2277 // add/remove requires capabilities to be specified.
2278 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2279 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2280 + "specified");
2281 return -1;
2282 }
2283
2284 ArraySet<String> capSet = new ArraySet<>();
2285 if (!TextUtils.isEmpty(caps)) {
2286 String[] capArray = caps.split(":");
2287 for (String cap : capArray) {
2288 // Allow unknown tags to be passed in as well.
2289 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2290 }
2291 }
2292
2293 RcsContactUceCapability result = null;
2294 try {
2295 switch (operation) {
2296 case "add":
2297 result = mInterface.addUceRegistrationOverrideShell(subId,
2298 new ArrayList<>(capSet));
2299 break;
2300 case "remove":
2301 result = mInterface.removeUceRegistrationOverrideShell(subId,
2302 new ArrayList<>(capSet));
2303 break;
2304 case "clear":
2305 result = mInterface.clearUceRegistrationOverrideShell(subId);
2306 break;
2307 case "list":
2308 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2309 break;
2310 }
2311 } catch (RemoteException e) {
2312 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2313 getErrPrintWriter().println("Exception: " + e.getMessage());
2314 return -1;
2315 } catch (ServiceSpecificException sse) {
2316 // Reconstruct ImsException
2317 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2318 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2319 getErrPrintWriter().println("Exception: " + imsException);
2320 return -1;
2321 }
2322 if (result == null) {
2323 getErrPrintWriter().println("Service not available");
2324 return -1;
2325 }
2326 getOutPrintWriter().println(result);
2327 return 0;
2328 }
2329
2330 private int handleUceGetPidfXml() {
2331 int subId = getSubId("uce get-last-publish-pidf");
2332 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2333 return -1;
2334 }
2335
2336 String result;
2337 try {
2338 result = mInterface.getLastUcePidfXmlShell(subId);
2339 } catch (RemoteException e) {
2340 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2341 getErrPrintWriter().println("Exception: " + e.getMessage());
2342 return -1;
2343 } catch (ServiceSpecificException sse) {
2344 // Reconstruct ImsException
2345 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2346 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2347 getErrPrintWriter().println("Exception: " + imsException);
2348 return -1;
2349 }
2350 if (result == null) {
2351 getErrPrintWriter().println("Service not available");
2352 return -1;
2353 }
2354 getOutPrintWriter().println(result);
2355 return 0;
2356 }
2357
Hui Wang761a6682020-10-31 05:12:53 +00002358 private int handleSrcSetDeviceEnabledCommand() {
2359 String enabledStr = getNextArg();
2360 if (enabledStr == null) {
2361 return -1;
2362 }
2363
2364 try {
2365 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2366 if (VDBG) {
2367 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2368 }
2369 getOutPrintWriter().println("Done");
2370 } catch (NumberFormatException | RemoteException e) {
2371 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2372 getErrPrintWriter().println("Exception: " + e.getMessage());
2373 return -1;
2374 }
2375 return 0;
2376 }
2377
2378 private int handleSrcGetDeviceEnabledCommand() {
2379 boolean result = false;
2380 try {
2381 result = mInterface.getDeviceSingleRegistrationEnabled();
2382 } catch (RemoteException e) {
2383 return -1;
2384 }
2385 if (VDBG) {
2386 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2387 }
2388 getOutPrintWriter().println(result);
2389 return 0;
2390 }
2391
2392 private int handleSrcSetCarrierEnabledCommand() {
2393 //the release time value could be -1
2394 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2395 : SubscriptionManager.getDefaultSubscriptionId();
2396 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2397 return -1;
2398 }
2399
2400 String enabledStr = getNextArg();
2401 if (enabledStr == null) {
2402 return -1;
2403 }
2404
2405 try {
2406 boolean result =
2407 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2408 if (VDBG) {
2409 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2410 + enabledStr + ", result=" + result);
2411 }
2412 getOutPrintWriter().println(result);
2413 } catch (NumberFormatException | RemoteException e) {
2414 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2415 + enabledStr + ", error" + e.getMessage());
2416 getErrPrintWriter().println("Exception: " + e.getMessage());
2417 return -1;
2418 }
2419 return 0;
2420 }
2421
2422 private int handleSrcGetCarrierEnabledCommand() {
2423 int subId = getSubId("src get-carrier-enabled");
2424 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2425 return -1;
2426 }
2427
2428 boolean result = false;
2429 try {
2430 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2431 } catch (RemoteException e) {
2432 return -1;
2433 }
2434 if (VDBG) {
2435 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2436 }
2437 getOutPrintWriter().println(result);
2438 return 0;
2439 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002440
Hui Wangb647abe2021-02-26 09:33:38 -08002441 private int handleSrcSetFeatureValidationCommand() {
2442 //the release time value could be -1
2443 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2444 : SubscriptionManager.getDefaultSubscriptionId();
2445 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2446 return -1;
2447 }
2448
2449 String enabledStr = getNextArg();
2450 if (enabledStr == null) {
2451 return -1;
2452 }
2453
2454 try {
2455 boolean result =
2456 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2457 if (VDBG) {
2458 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2459 + enabledStr + ", result=" + result);
2460 }
2461 getOutPrintWriter().println(result);
2462 } catch (NumberFormatException | RemoteException e) {
2463 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2464 + enabledStr + ", error" + e.getMessage());
2465 getErrPrintWriter().println("Exception: " + e.getMessage());
2466 return -1;
2467 }
2468 return 0;
2469 }
2470
2471 private int handleSrcGetFeatureValidationCommand() {
2472 int subId = getSubId("src get-feature-validation");
2473 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2474 return -1;
2475 }
2476
2477 Boolean result = false;
2478 try {
2479 result = mInterface.getImsFeatureValidationOverride(subId);
2480 } catch (RemoteException e) {
2481 return -1;
2482 }
2483 if (VDBG) {
2484 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2485 }
2486 getOutPrintWriter().println(result);
2487 return 0;
2488 }
2489
2490
Hall Liuaa4211e2021-01-20 15:43:39 -08002491 private void onHelpCallComposer() {
2492 PrintWriter pw = getOutPrintWriter();
2493 pw.println("Call composer commands");
2494 pw.println(" callcomposer test-mode enable|disable|query");
2495 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2496 pw.println(" upload/download from carrier servers is disabled, and operations are");
2497 pw.println(" performed using emulated local files instead.");
2498 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2499 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2500 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002501 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2502 pw.println(" Enables or disables the user setting for call composer, as set by");
2503 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002504 }
2505
2506 private int handleCallComposerCommand() {
2507 String arg = getNextArg();
2508 if (arg == null) {
2509 onHelpCallComposer();
2510 return 0;
2511 }
2512
2513 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2514 "MODIFY_PHONE_STATE required for call composer shell cmds");
2515 switch (arg) {
2516 case CALL_COMPOSER_TEST_MODE: {
2517 String enabledStr = getNextArg();
2518 if (ENABLE.equals(enabledStr)) {
2519 CallComposerPictureManager.sTestMode = true;
2520 } else if (DISABLE.equals(enabledStr)) {
2521 CallComposerPictureManager.sTestMode = false;
2522 } else if (QUERY.equals(enabledStr)) {
2523 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2524 } else {
2525 onHelpCallComposer();
2526 return 1;
2527 }
2528 break;
2529 }
2530 case CALL_COMPOSER_SIMULATE_CALL: {
2531 int subscriptionId = Integer.valueOf(getNextArg());
2532 String uuidString = getNextArg();
2533 UUID uuid = UUID.fromString(uuidString);
2534 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2535 Binder.withCleanCallingIdentity(() -> {
2536 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2537 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2538 });
2539 try {
2540 Uri uri = storageUriFuture.get();
2541 getOutPrintWriter().println(String.valueOf(uri));
2542 } catch (Exception e) {
2543 throw new RuntimeException(e);
2544 }
2545 break;
2546 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002547 case CALL_COMPOSER_USER_SETTING: {
2548 try {
2549 int subscriptionId = Integer.valueOf(getNextArg());
2550 String enabledStr = getNextArg();
2551 if (ENABLE.equals(enabledStr)) {
2552 mInterface.setCallComposerStatus(subscriptionId,
2553 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2554 } else if (DISABLE.equals(enabledStr)) {
2555 mInterface.setCallComposerStatus(subscriptionId,
2556 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2557 } else if (QUERY.equals(enabledStr)) {
2558 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2559 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2560 } else {
2561 onHelpCallComposer();
2562 return 1;
2563 }
2564 } catch (RemoteException e) {
2565 e.printStackTrace(getOutPrintWriter());
2566 return 1;
2567 }
2568 break;
2569 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002570 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002571 return 0;
2572 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002573
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002574 private int handleHasCarrierPrivilegesCommand() {
2575 String packageName = getNextArgRequired();
2576
2577 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002578 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002579 try {
2580 hasCarrierPrivileges =
2581 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2582 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2583 } catch (RemoteException e) {
2584 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2585 getErrPrintWriter().println("Exception: " + e.getMessage());
2586 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002587 } finally {
2588 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002589 }
2590
2591 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002592 return 0;
2593 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002594
2595 private int handleAllowedNetworkTypesCommand(String command) {
2596 if (!checkShellUid()) {
2597 return -1;
2598 }
2599
2600 PrintWriter errPw = getErrPrintWriter();
2601 String tag = command + ": ";
2602 String opt;
2603 int subId = -1;
2604 Log.v(LOG_TAG, command + " start");
2605
2606 while ((opt = getNextOption()) != null) {
2607 if (opt.equals("-s")) {
2608 try {
2609 subId = slotStringToSubId(tag, getNextArgRequired());
2610 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2611 errPw.println(tag + "No valid subscription found.");
2612 return -1;
2613 }
2614 } catch (IllegalArgumentException e) {
2615 // Missing slot id
2616 errPw.println(tag + "SLOT_ID expected after -s.");
2617 return -1;
2618 }
2619 } else {
2620 errPw.println(tag + "Unknown option " + opt);
2621 return -1;
2622 }
2623 }
2624
2625 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2626 return handleGetAllowedNetworkTypesCommand(subId);
2627 }
2628 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2629 return handleSetAllowedNetworkTypesCommand(subId);
2630 }
2631 return -1;
2632 }
2633
2634 private int handleGetAllowedNetworkTypesCommand(int subId) {
2635 PrintWriter errPw = getErrPrintWriter();
2636
2637 long result = -1;
2638 try {
2639 if (mInterface != null) {
2640 result = mInterface.getAllowedNetworkTypesForReason(subId,
2641 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2642 } else {
2643 throw new IllegalStateException("telephony service is null.");
2644 }
2645 } catch (RemoteException e) {
2646 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2647 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2648 return -1;
2649 }
2650
2651 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2652 return 0;
2653 }
2654
2655 private int handleSetAllowedNetworkTypesCommand(int subId) {
2656 PrintWriter errPw = getErrPrintWriter();
2657
2658 String bitmaskString = getNextArg();
2659 if (TextUtils.isEmpty(bitmaskString)) {
2660 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2661 return -1;
2662 }
2663 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2664 if (allowedNetworkTypes < 0) {
2665 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2666 return -1;
2667 }
2668 boolean result = false;
2669 try {
2670 if (mInterface != null) {
2671 result = mInterface.setAllowedNetworkTypesForReason(subId,
2672 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2673 } else {
2674 throw new IllegalStateException("telephony service is null.");
2675 }
2676 } catch (RemoteException e) {
2677 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2678 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2679 return -1;
2680 }
2681
2682 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2683 if (result) {
2684 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2685 }
2686 getOutPrintWriter().println(resultMessage);
2687 return 0;
2688 }
2689
2690 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2691 if (TextUtils.isEmpty(bitmaskString)) {
2692 return -1;
2693 }
2694 if (VDBG) {
2695 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2696 + ", length: " + bitmaskString.length());
2697 }
2698 try {
2699 return Long.parseLong(bitmaskString, 2);
2700 } catch (NumberFormatException e) {
2701 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2702 return -1;
2703 }
2704 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002705}