blob: 2726855c900fd4a17231770ffa99ad9c987675d5 [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;
Jack Yu4c0a5502021-12-03 23:58:26 -080033import android.provider.DeviceConfig;
Nazanin014f41e2021-05-06 17:26:31 -070034import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010035import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070036import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070037import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000038import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070039import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080040import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000041import android.telephony.ims.ImsException;
42import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080043import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080044import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000045import android.util.ArrayMap;
46import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070047import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070048import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070049
Brad Ebinger14d467f2021-02-12 06:18:28 +000050import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070051import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080052import com.android.internal.telephony.Phone;
53import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080054import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080055import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080056import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080057import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080058import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070059
60import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080061import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000062import java.util.Arrays;
63import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010064import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080065import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010066import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000067import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010068import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080069import java.util.UUID;
70import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070071
72/**
73 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
74 * permission checks have been done before onCommand was called. Make sure any commands processed
75 * here also contain the appropriate permissions checks.
76 */
77
Hall Liua1548bd2019-12-24 14:14:12 -080078public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070079
80 private static final String LOG_TAG = "TelephonyShellCommand";
81 // Don't commit with this true.
82 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070083 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070084
Hall Liuaa4211e2021-01-20 15:43:39 -080085 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070086 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080087 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080088 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080089 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070090 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000091 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000092 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010093 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080094 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080095 private static final String ENABLE = "enable";
96 private static final String DISABLE = "disable";
97 private static final String QUERY = "query";
98
Hall Liu7135e502021-02-04 16:58:17 -080099 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800100 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800101 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800102
Brad Ebinger999d3302020-11-25 14:31:39 -0800103 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
104 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
105 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700106 // Used to disable or enable processing of conference event package data from the network.
107 // This is handy for testing scenarios where CEP data does not exist on a network which does
108 // support CEP data.
109 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700110
Hall Liud892bec2018-11-30 14:51:45 -0800111 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800112 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800113
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100114 private static final String CC_GET_VALUE = "get-value";
115 private static final String CC_SET_VALUE = "set-value";
116 private static final String CC_CLEAR_VALUES = "clear-values";
117
Hui Wang641e81c2020-10-12 12:14:23 -0700118 private static final String GBA_SUBCOMMAND = "gba";
119 private static final String GBA_SET_SERVICE = "set-service";
120 private static final String GBA_GET_SERVICE = "get-service";
121 private static final String GBA_SET_RELEASE_TIME = "set-release";
122 private static final String GBA_GET_RELEASE_TIME = "get-release";
123
Hui Wang761a6682020-10-31 05:12:53 +0000124 private static final String SINGLE_REGISTATION_CONFIG = "src";
125 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
126 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
127 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
128 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800129 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
130 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800131 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
132 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000133
Tyler Gunn92479152021-01-20 16:30:10 -0800134 private static final String D2D_SUBCOMMAND = "d2d";
135 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800136 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700137 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800138
Nazanin014f41e2021-05-06 17:26:31 -0700139 private static final String BARRING_SUBCOMMAND = "barring";
140 private static final String BARRING_SEND_INFO = "send";
141
James.cf Linbcdf8b32021-01-14 16:44:13 +0800142 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800143 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800144 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800145 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800146 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
147 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000148 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
149 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800150 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
151 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800152 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
153 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800154
jimsun3b9ccac2021-10-26 15:01:23 +0800155 private static final String RADIO_SUBCOMMAND = "radio";
156 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
157 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
158
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800159 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
160 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
161
Jordan Liu0ccee222021-04-27 11:55:13 -0700162 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
163 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
164
Jack Nudelman644b91a2021-03-12 14:09:48 -0800165 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
166 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
167 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
168
SongFerngWang98dd5992021-05-13 17:50:00 +0800169 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
170 "get-allowed-network-types-for-users";
171 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
172 "set-allowed-network-types-for-users";
Jack Yu4c0a5502021-12-03 23:58:26 -0800173 // Check if telephony new data stack is enabled.
174 private static final String GET_DATA_MODE = "get-data-mode";
Ling Ma4fbab492022-01-25 22:36:16 +0000175 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000176 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700177 // Take advantage of existing methods that already contain permissions checks when possible.
178 private final ITelephony mInterface;
179
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100180 private SubscriptionManager mSubscriptionManager;
181 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700182 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700183 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100184
185 private enum CcType {
186 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
187 STRING_ARRAY, UNKNOWN
188 }
189
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100190 private class CcOptionParseResult {
191 public int mSubId;
192 public boolean mPersistent;
193 }
194
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100195 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
196 // keys by looking at the end of the string which usually tells the type.
197 // For instance: "xxxx_string", "xxxx_string_array", etc.
198 // The carrier config keys in this map does not follow this convention. It is therefore not
199 // possible to infer the type for these keys by looking at the string.
200 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
201 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
206 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
207 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
208 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
209 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
210 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
211 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
212 CcType.STRING);
213 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
214 CcType.STRING_ARRAY);
215 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
216 CcType.STRING_ARRAY);
217 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
219 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
220 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
221 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
222 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
223 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
224 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
225 }
226 };
227
Brad Ebinger14d467f2021-02-12 06:18:28 +0000228 /**
229 * Map from a shorthand string to the feature tags required in registration required in order
230 * for the RCS feature to be considered "capable".
231 */
232 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
233 static {
234 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
235 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
236 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
237 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
238 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
239 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
240 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
241 FeatureTags.FEATURE_TAG_VIDEO)));
242 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
243 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
244 map.put("call_comp",
245 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
246 map.put("call_comp_mmtel",
247 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
248 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
249 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
250 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
251 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
252 // version
253 map.put("chatbot", new ArraySet<>(Arrays.asList(
254 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
255 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
256 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
257 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000258 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000259 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
260 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
261 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
262 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
263 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000264 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000265 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
266 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
267 }
268
269
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100270 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700271 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100272 mCarrierConfigManager =
273 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
274 mSubscriptionManager = (SubscriptionManager)
275 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700276 mTelephonyRegistryManager = (TelephonyRegistryManager)
277 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700278 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700279 }
280
281 @Override
282 public int onCommand(String cmd) {
283 if (cmd == null) {
284 return handleDefaultCommands(null);
285 }
286
287 switch (cmd) {
288 case IMS_SUBCOMMAND: {
289 return handleImsCommand();
290 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800291 case RCS_UCE_COMMAND:
292 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800293 case NUMBER_VERIFICATION_SUBCOMMAND:
294 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800295 case EMERGENCY_CALLBACK_MODE:
296 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800297 case EMERGENCY_NUMBER_TEST_MODE:
298 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100299 case CARRIER_CONFIG_SUBCOMMAND: {
300 return handleCcCommand();
301 }
Shuo Qianf5125122019-12-16 17:03:07 -0800302 case DATA_TEST_MODE:
303 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700304 case END_BLOCK_SUPPRESSION:
305 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700306 case GBA_SUBCOMMAND:
307 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800308 case D2D_SUBCOMMAND:
309 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700310 case BARRING_SUBCOMMAND:
311 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000312 case SINGLE_REGISTATION_CONFIG:
313 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000314 case RESTART_MODEM:
315 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800316 case CALL_COMPOSER_SUBCOMMAND:
317 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000318 case UNATTENDED_REBOOT:
319 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800320 case HAS_CARRIER_PRIVILEGES_COMMAND:
321 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800322 case THERMAL_MITIGATION_COMMAND:
323 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700324 case DISABLE_PHYSICAL_SUBSCRIPTION:
325 return handleEnablePhysicalSubscription(false);
326 case ENABLE_PHYSICAL_SUBSCRIPTION:
327 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800328 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
329 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
330 return handleAllowedNetworkTypesCommand(cmd);
Jack Yu4c0a5502021-12-03 23:58:26 -0800331 case GET_DATA_MODE:
332 return handleGetDataMode();
Ling Ma4fbab492022-01-25 22:36:16 +0000333 case GET_IMEI:
334 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000335 case GET_SIM_SLOTS_MAPPING:
336 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800337 case RADIO_SUBCOMMAND:
338 return handleRadioCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700339 default: {
340 return handleDefaultCommands(cmd);
341 }
342 }
343 }
344
345 @Override
346 public void onHelp() {
347 PrintWriter pw = getOutPrintWriter();
348 pw.println("Telephony Commands:");
349 pw.println(" help");
350 pw.println(" Print this help text.");
351 pw.println(" ims");
352 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800353 pw.println(" uce");
354 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800355 pw.println(" emergency-number-test-mode");
356 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700357 pw.println(" end-block-suppression");
358 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800359 pw.println(" data");
360 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100361 pw.println(" cc");
362 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700363 pw.println(" gba");
364 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000365 pw.println(" src");
366 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000367 pw.println(" restart-modem");
368 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000369 pw.println(" unattended-reboot");
370 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800371 pw.println(" has-carrier-privileges [package]");
372 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800373 pw.println(" get-allowed-network-types-for-users");
374 pw.println(" Get the Allowed Network Types.");
375 pw.println(" set-allowed-network-types-for-users");
376 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800377 pw.println(" radio");
378 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700379 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800380 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800381 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700382 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800383 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100384 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700385 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000386 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800387 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700388 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800389 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800390 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000391 onHelpImei();
Tyler Gunn92479152021-01-20 16:30:10 -0800392 }
393
394 private void onHelpD2D() {
395 PrintWriter pw = getOutPrintWriter();
396 pw.println("D2D Comms Commands:");
397 pw.println(" d2d send TYPE VALUE");
398 pw.println(" Sends a D2D message of specified type and value.");
399 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
400 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
401 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
402 MESSAGE_CALL_AUDIO_CODEC));
403 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
404 + Communicator.messageToString(
405 MESSAGE_DEVICE_BATTERY_STATE));
406 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
407 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800408 pw.println(" d2d transport TYPE");
409 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
410 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700411 pw.println(" d2d set-device-support true/default");
412 pw.println(" true - forces device support to be enabled for D2D.");
413 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
414 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700415 }
416
Nazanin014f41e2021-05-06 17:26:31 -0700417 private void onHelpBarring() {
418 PrintWriter pw = getOutPrintWriter();
419 pw.println("Barring Commands:");
420 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
421 + " -t CONDITIONAL_BARRING_TIME_SECS");
422 pw.println(" Notifies of a barring info change for the specified slot id.");
423 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
424 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
425 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
426 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
427 }
428
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700429 private void onHelpIms() {
430 PrintWriter pw = getOutPrintWriter();
431 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800432 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700433 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
434 pw.println(" ImsService. Options are:");
435 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
436 pw.println(" is specified, it will choose the default voice SIM slot.");
437 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
438 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800439 pw.println(" -f: Set the feature that this override if for, if no option is");
440 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700441 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
442 pw.println(" Gets the package name of the currently defined ImsService.");
443 pw.println(" Options are:");
444 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
445 pw.println(" is specified, it will choose the default voice SIM slot.");
446 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000447 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800448 pw.println(" -f: The feature type that the query will be requested for. If none is");
449 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800450 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
451 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
452 pw.println(" configuration overrides. Options are:");
453 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
454 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700455 pw.println(" ims enable [-s SLOT_ID]");
456 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
457 pw.println(" if none is specified.");
458 pw.println(" ims disable [-s SLOT_ID]");
459 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
460 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700461 pw.println(" ims conference-event-package [enable/disable]");
462 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700463 }
464
James.cf Linbcdf8b32021-01-14 16:44:13 +0800465 private void onHelpUce() {
466 PrintWriter pw = getOutPrintWriter();
467 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800468 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
469 pw.println(" Get the EAB contacts from the EAB database.");
470 pw.println(" Options are:");
471 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
472 pw.println(" Expected output format :");
473 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800474 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
475 pw.println(" Remove the EAB contacts from the EAB database.");
476 pw.println(" Options are:");
477 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
478 pw.println(" is specified, it will choose the default voice SIM slot.");
479 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800480 pw.println(" uce get-device-enabled");
481 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
482 pw.println(" uce set-device-enabled true|false");
483 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
484 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000485 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
486 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
487 pw.println(" Options are:");
488 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
489 pw.println(" is specified, it will choose the default voice SIM slot.");
490 pw.println(" add [CAPABILITY]: add a new capability");
491 pw.println(" remove [CAPABILITY]: remove a capability");
492 pw.println(" clear: clear all capability overrides");
493 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
494 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
495 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
496 pw.println(" chatbot_sa, chatbot_role] as well as full length");
497 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
498 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
499 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
500 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800501 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
502 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800503 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
504 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800505 }
506
Hall Liud892bec2018-11-30 14:51:45 -0800507 private void onHelpNumberVerification() {
508 PrintWriter pw = getOutPrintWriter();
509 pw.println("Number verification commands");
510 pw.println(" numverify override-package PACKAGE_NAME;");
511 pw.println(" Set the authorized package for number verification.");
512 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800513 pw.println(" numverify fake-call NUMBER;");
514 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
515 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800516 }
517
Jack Nudelman644b91a2021-03-12 14:09:48 -0800518 private void onHelpThermalMitigation() {
519 PrintWriter pw = getOutPrintWriter();
520 pw.println("Thermal mitigation commands");
521 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
522 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
523 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
524 pw.println(" Remove the package from one of the authorized packages for thermal "
525 + "mitigation.");
526 }
527
Jordan Liu0ccee222021-04-27 11:55:13 -0700528 private void onHelpDisableOrEnablePhysicalSubscription() {
529 PrintWriter pw = getOutPrintWriter();
530 pw.println("Disable or enable a physical subscription");
531 pw.println(" disable-physical-subscription SUB_ID");
532 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
533 pw.println(" enable-physical-subscription SUB_ID");
534 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
535 }
536
Shuo Qianf5125122019-12-16 17:03:07 -0800537 private void onHelpDataTestMode() {
538 PrintWriter pw = getOutPrintWriter();
539 pw.println("Mobile Data Test Mode Commands:");
540 pw.println(" data enable: enable mobile data connectivity");
541 pw.println(" data disable: disable mobile data connectivity");
542 }
543
sqian9d4df8b2019-01-15 18:32:07 -0800544 private void onHelpEmergencyNumber() {
545 PrintWriter pw = getOutPrintWriter();
546 pw.println("Emergency Number Test Mode Commands:");
547 pw.println(" emergency-number-test-mode ");
548 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
549 + " the test mode");
550 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700551 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800552 pw.println(" -c: clear the emergency number list in the test mode.");
553 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700554 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800555 pw.println(" -p: get the full emergency number list in the test mode.");
556 }
557
Shuo Qian489d9282020-07-09 11:30:03 -0700558 private void onHelpEndBlockSupperssion() {
559 PrintWriter pw = getOutPrintWriter();
560 pw.println("End Block Suppression command:");
561 pw.println(" end-block-suppression: disable suppressing blocking by contact");
562 pw.println(" with emergency services.");
563 }
564
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100565 private void onHelpCc() {
566 PrintWriter pw = getOutPrintWriter();
567 pw.println("Carrier Config Commands:");
568 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
569 pw.println(" Print carrier config values.");
570 pw.println(" Options are:");
571 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
572 pw.println(" is specified, it will choose the default voice SIM slot.");
573 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
574 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100575 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100576 pw.println(" Set carrier config KEY to NEW_VALUE.");
577 pw.println(" Options are:");
578 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
579 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100580 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100581 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
582 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
583 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
584 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
585 pw.println(" cc clear-values [-s SLOT_ID]");
586 pw.println(" Clear all carrier override values that has previously been set");
587 pw.println(" with set-value");
588 pw.println(" Options are:");
589 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
590 pw.println(" is specified, it will choose the default voice SIM slot.");
591 }
592
Hui Wang641e81c2020-10-12 12:14:23 -0700593 private void onHelpGba() {
594 PrintWriter pw = getOutPrintWriter();
595 pw.println("Gba Commands:");
596 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
597 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
598 pw.println(" Options are:");
599 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
600 pw.println(" is specified, it will choose the default voice SIM slot.");
601 pw.println(" gba get-service [-s SLOT_ID]");
602 pw.println(" Gets the package name of the currently defined GbaService.");
603 pw.println(" Options are:");
604 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
605 pw.println(" is specified, it will choose the default voice SIM slot.");
606 pw.println(" gba set-release [-s SLOT_ID] n");
607 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
608 pw.println(" Do not release/unbind if n is -1.");
609 pw.println(" Options are:");
610 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
611 pw.println(" is specified, it will choose the default voice SIM slot.");
612 pw.println(" gba get-release [-s SLOT_ID]");
613 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
614 pw.println(" Options are:");
615 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
616 pw.println(" is specified, it will choose the default voice SIM slot.");
617 }
618
Hui Wang761a6682020-10-31 05:12:53 +0000619 private void onHelpSrc() {
620 PrintWriter pw = getOutPrintWriter();
621 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800622 pw.println(" src set-test-enabled true|false");
623 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
624 pw.println(" The value could be true, false, or null(undefined).");
625 pw.println(" src get-test-enabled");
626 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000627 pw.println(" src set-device-enabled true|false|null");
628 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
629 pw.println(" The value could be true, false, or null(undefined).");
630 pw.println(" src get-device-enabled");
631 pw.println(" Gets the device config for RCS VoLTE single registration.");
632 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
633 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
634 pw.println(" The value could be true, false, or null(undefined).");
635 pw.println(" Options are:");
636 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
637 pw.println(" is specified, it will choose the default voice SIM slot.");
638 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
639 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
640 pw.println(" Options are:");
641 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
642 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800643 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
644 pw.println(" Sets ims feature validation result.");
645 pw.println(" The value could be true, false, or null(undefined).");
646 pw.println(" Options are:");
647 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
648 pw.println(" is specified, it will choose the default voice SIM slot.");
649 pw.println(" src get-feature-validation [-s SLOT_ID]");
650 pw.println(" Gets ims feature validation override value.");
651 pw.println(" Options are:");
652 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
653 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000654 }
655
SongFerngWang98dd5992021-05-13 17:50:00 +0800656 private void onHelpAllowedNetworkTypes() {
657 PrintWriter pw = getOutPrintWriter();
658 pw.println("Allowed Network Types Commands:");
659 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
660 pw.println(" Print allowed network types value.");
661 pw.println(" Options are:");
662 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
663 pw.println(" option is specified, it will choose the default voice SIM slot.");
664 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
665 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
666 pw.println(" Options are:");
667 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
668 pw.println(" option is specified, it will choose the default voice SIM slot.");
669 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
670 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
671 pw.println(" at TelephonyManager.java");
672 pw.println(" For example:");
673 pw.println(" NR only : 10000000000000000000");
674 pw.println(" NR|LTE : 11000001000000000000");
675 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
676 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
677 pw.println(" LTE only : 01000001000000000000");
678 }
679
jimsun3b9ccac2021-10-26 15:01:23 +0800680 private void onHelpRadio() {
681 PrintWriter pw = getOutPrintWriter();
682 pw.println("Radio Commands:");
683 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
684 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
685 pw.println(" to be the bound. Options are:");
686 pw.println(" -s: the service name that the modem service should be bound for.");
687 pw.println(" If no option is specified, it will bind to the default.");
688 pw.println(" radio get-modem-service");
689 pw.println(" Gets the service name of the currently defined modem service.");
690 pw.println(" If it is binding to default, 'default' returns.");
691 pw.println(" If it doesn't bind to any modem service for some reasons,");
692 pw.println(" the result would be 'unknown'.");
693 }
694
Ling Ma4fbab492022-01-25 22:36:16 +0000695 private void onHelpImei() {
696 PrintWriter pw = getOutPrintWriter();
697 pw.println("IMEI Commands:");
698 pw.println(" get-imei [-s SLOT_ID]");
699 pw.println(" Gets the device IMEI. Options are:");
700 pw.println(" -s: the slot ID to get the IMEI. If no option");
701 pw.println(" is specified, it will choose the default voice SIM slot.");
702 }
703
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700704 private int handleImsCommand() {
705 String arg = getNextArg();
706 if (arg == null) {
707 onHelpIms();
708 return 0;
709 }
710
711 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800712 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700713 return handleImsSetServiceCommand();
714 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800715 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700716 return handleImsGetServiceCommand();
717 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800718 case IMS_CLEAR_SERVICE_OVERRIDE: {
719 return handleImsClearCarrierServiceCommand();
720 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800721 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700722 return handleEnableIms();
723 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800724 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700725 return handleDisableIms();
726 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700727 case IMS_CEP: {
728 return handleCepChange();
729 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700730 }
731
732 return -1;
733 }
734
Shuo Qianf5125122019-12-16 17:03:07 -0800735 private int handleDataTestModeCommand() {
736 PrintWriter errPw = getErrPrintWriter();
737 String arg = getNextArgRequired();
738 if (arg == null) {
739 onHelpDataTestMode();
740 return 0;
741 }
742 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800743 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800744 try {
745 mInterface.enableDataConnectivity();
746 } catch (RemoteException ex) {
747 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
748 errPw.println("Exception: " + ex.getMessage());
749 return -1;
750 }
751 break;
752 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800753 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800754 try {
755 mInterface.disableDataConnectivity();
756 } catch (RemoteException ex) {
757 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
758 errPw.println("Exception: " + ex.getMessage());
759 return -1;
760 }
761 break;
762 }
763 default:
764 onHelpDataTestMode();
765 break;
766 }
767 return 0;
768 }
769
Shuo Qianccbaf742021-02-22 18:32:21 -0800770 private int handleEmergencyCallbackModeCommand() {
771 PrintWriter errPw = getErrPrintWriter();
772 try {
773 mInterface.startEmergencyCallbackMode();
774 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
775 } catch (RemoteException ex) {
776 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
777 errPw.println("Exception: " + ex.getMessage());
778 return -1;
779 }
780 return 0;
781 }
782
sqian9d4df8b2019-01-15 18:32:07 -0800783 private int handleEmergencyNumberTestModeCommand() {
784 PrintWriter errPw = getErrPrintWriter();
785 String opt = getNextOption();
786 if (opt == null) {
787 onHelpEmergencyNumber();
788 return 0;
789 }
790
791 switch (opt) {
792 case "-a": {
793 String emergencyNumberCmd = getNextArgRequired();
794 if (emergencyNumberCmd == null
795 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700796 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800797 + " to be specified after -a in the command ");
798 return -1;
799 }
800 try {
801 mInterface.updateEmergencyNumberListTestMode(
802 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
803 new EmergencyNumber(emergencyNumberCmd, "", "",
804 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
805 new ArrayList<String>(),
806 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
807 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
808 } catch (RemoteException ex) {
809 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
810 + ", error " + ex.getMessage());
811 errPw.println("Exception: " + ex.getMessage());
812 return -1;
813 }
814 break;
815 }
816 case "-c": {
817 try {
818 mInterface.updateEmergencyNumberListTestMode(
819 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
820 } catch (RemoteException ex) {
821 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
822 errPw.println("Exception: " + ex.getMessage());
823 return -1;
824 }
825 break;
826 }
827 case "-r": {
828 String emergencyNumberCmd = getNextArgRequired();
829 if (emergencyNumberCmd == null
830 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700831 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800832 + " to be specified after -r in the command ");
833 return -1;
834 }
835 try {
836 mInterface.updateEmergencyNumberListTestMode(
837 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
838 new EmergencyNumber(emergencyNumberCmd, "", "",
839 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
840 new ArrayList<String>(),
841 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
842 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
843 } catch (RemoteException ex) {
844 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
845 + ", error " + ex.getMessage());
846 errPw.println("Exception: " + ex.getMessage());
847 return -1;
848 }
849 break;
850 }
851 case "-p": {
852 try {
853 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
854 } catch (RemoteException ex) {
855 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
856 errPw.println("Exception: " + ex.getMessage());
857 return -1;
858 }
859 break;
860 }
861 default:
862 onHelpEmergencyNumber();
863 break;
864 }
865 return 0;
866 }
867
Hall Liud892bec2018-11-30 14:51:45 -0800868 private int handleNumberVerificationCommand() {
869 String arg = getNextArg();
870 if (arg == null) {
871 onHelpNumberVerification();
872 return 0;
873 }
874
Hall Liuca5af3a2018-12-04 16:58:23 -0800875 if (!checkShellUid()) {
876 return -1;
877 }
878
Hall Liud892bec2018-11-30 14:51:45 -0800879 switch (arg) {
880 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800881 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
882 return 0;
883 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800884 case NUMBER_VERIFICATION_FAKE_CALL: {
885 boolean val = NumberVerificationManager.getInstance()
886 .checkIncomingCall(getNextArg());
887 getOutPrintWriter().println(val ? "1" : "0");
888 return 0;
889 }
Hall Liud892bec2018-11-30 14:51:45 -0800890 }
891
892 return -1;
893 }
894
Jordan Liu0ccee222021-04-27 11:55:13 -0700895 private boolean subIsEsim(int subId) {
896 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
897 if (info != null) {
898 return info.isEmbedded();
899 }
900 return false;
901 }
902
903 private int handleEnablePhysicalSubscription(boolean enable) {
904 PrintWriter errPw = getErrPrintWriter();
905 int subId = 0;
906 try {
907 subId = Integer.parseInt(getNextArgRequired());
908 } catch (NumberFormatException e) {
909 errPw.println((enable ? "enable" : "disable")
910 + "-physical-subscription requires an integer as a subId.");
911 return -1;
912 }
913 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
914 // non user build.
915 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
916 errPw.println("cc: Permission denied.");
917 return -1;
918 }
919 // Verify that the subId represents a physical sub
920 if (subIsEsim(subId)) {
921 errPw.println("SubId " + subId + " is not for a physical subscription");
922 return -1;
923 }
924 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
925 + " physical subscription with subId=" + subId);
926 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
927 return 0;
928 }
929
Jack Nudelman644b91a2021-03-12 14:09:48 -0800930 private int handleThermalMitigationCommand() {
931 String arg = getNextArg();
932 String packageName = getNextArg();
933 if (arg == null || packageName == null) {
934 onHelpThermalMitigation();
935 return 0;
936 }
937
938 if (!checkShellUid()) {
939 return -1;
940 }
941
942 switch (arg) {
943 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
944 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
945 return 0;
946 }
947 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
948 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
949 mContext);
950 return 0;
951 }
952 default:
953 onHelpThermalMitigation();
954 }
955
956 return -1;
957
958 }
959
Tyler Gunn92479152021-01-20 16:30:10 -0800960 private int handleD2dCommand() {
961 String arg = getNextArg();
962 if (arg == null) {
963 onHelpD2D();
964 return 0;
965 }
966
967 switch (arg) {
968 case D2D_SEND: {
969 return handleD2dSendCommand();
970 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800971 case D2D_TRANSPORT: {
972 return handleD2dTransportCommand();
973 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700974 case D2D_SET_DEVICE_SUPPORT: {
975 return handleD2dDeviceSupportedCommand();
976 }
Tyler Gunn92479152021-01-20 16:30:10 -0800977 }
978
979 return -1;
980 }
981
982 private int handleD2dSendCommand() {
983 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800984 int messageType = -1;
985 int messageValue = -1;
986
Tyler Gunn92479152021-01-20 16:30:10 -0800987 String arg = getNextArg();
988 if (arg == null) {
989 onHelpD2D();
990 return 0;
991 }
992 try {
993 messageType = Integer.parseInt(arg);
994 } catch (NumberFormatException e) {
995 errPw.println("message type must be a valid integer");
996 return -1;
997 }
998
999 arg = getNextArg();
1000 if (arg == null) {
1001 onHelpD2D();
1002 return 0;
1003 }
1004 try {
1005 messageValue = Integer.parseInt(arg);
1006 } catch (NumberFormatException e) {
1007 errPw.println("message value must be a valid integer");
1008 return -1;
1009 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001010
Tyler Gunn92479152021-01-20 16:30:10 -08001011 try {
1012 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1013 } catch (RemoteException e) {
1014 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1015 errPw.println("Exception: " + e.getMessage());
1016 return -1;
1017 }
1018
1019 return 0;
1020 }
1021
Tyler Gunnbabbda02021-02-10 11:05:02 -08001022 private int handleD2dTransportCommand() {
1023 PrintWriter errPw = getErrPrintWriter();
1024
1025 String arg = getNextArg();
1026 if (arg == null) {
1027 onHelpD2D();
1028 return 0;
1029 }
1030
1031 try {
1032 mInterface.setActiveDeviceToDeviceTransport(arg);
1033 } catch (RemoteException e) {
1034 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1035 errPw.println("Exception: " + e.getMessage());
1036 return -1;
1037 }
1038 return 0;
1039 }
Nazanin014f41e2021-05-06 17:26:31 -07001040 private int handleBarringCommand() {
1041 String arg = getNextArg();
1042 if (arg == null) {
1043 onHelpBarring();
1044 return 0;
1045 }
1046
1047 switch (arg) {
1048 case BARRING_SEND_INFO: {
1049 return handleBarringSendCommand();
1050 }
1051 }
1052 return -1;
1053 }
1054
1055 private int handleBarringSendCommand() {
1056 PrintWriter errPw = getErrPrintWriter();
1057 int slotId = getDefaultSlot();
1058 int subId = SubscriptionManager.getSubId(slotId)[0];
1059 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1060 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1061 boolean isConditionallyBarred = false;
1062 int conditionalBarringTimeSeconds = 0;
1063
1064 String opt;
1065 while ((opt = getNextOption()) != null) {
1066 switch (opt) {
1067 case "-s": {
1068 try {
1069 slotId = Integer.parseInt(getNextArgRequired());
1070 subId = SubscriptionManager.getSubId(slotId)[0];
1071 } catch (NumberFormatException e) {
1072 errPw.println("barring send requires an integer as a SLOT_ID.");
1073 return -1;
1074 }
1075 break;
1076 }
1077 case "-b": {
1078 try {
1079 barringType = Integer.parseInt(getNextArgRequired());
1080 if (barringType < -1 || barringType > 2) {
1081 throw new NumberFormatException();
1082 }
1083
1084 } catch (NumberFormatException e) {
1085 errPw.println("barring send requires an integer in range [-1,2] as "
1086 + "a BARRING_TYPE.");
1087 return -1;
1088 }
1089 break;
1090 }
1091 case "-c": {
1092 try {
1093 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1094 } catch (Exception e) {
1095 errPw.println("barring send requires a boolean after -c indicating"
1096 + " conditional barring");
1097 return -1;
1098 }
1099 break;
1100 }
1101 case "-t": {
1102 try {
1103 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1104 } catch (NumberFormatException e) {
1105 errPw.println("barring send requires an integer for time of barring"
1106 + " in seconds after -t for conditional barring");
1107 return -1;
1108 }
1109 break;
1110 }
1111 }
1112 }
1113 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1114 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1115 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1116 barringServiceInfos.append(0, bsi);
1117 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1118 try {
1119 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1120 } catch (Exception e) {
1121 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1122 errPw.println("Exception: " + e.getMessage());
1123 return -1;
1124 }
1125 return 0;
1126 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001127
Tyler Gunnd4575212021-05-03 14:46:49 -07001128 private int handleD2dDeviceSupportedCommand() {
1129 PrintWriter errPw = getErrPrintWriter();
1130
1131 String arg = getNextArg();
1132 if (arg == null) {
1133 onHelpD2D();
1134 return 0;
1135 }
1136
1137 boolean isEnabled = "true".equals(arg.toLowerCase());
1138 try {
1139 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1140 } catch (RemoteException e) {
1141 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1142 errPw.println("Exception: " + e.getMessage());
1143 return -1;
1144 }
1145 return 0;
1146 }
1147
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001148 // ims set-ims-service
1149 private int handleImsSetServiceCommand() {
1150 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001151 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001152 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001153 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001154
1155 String opt;
1156 while ((opt = getNextOption()) != null) {
1157 switch (opt) {
1158 case "-s": {
1159 try {
1160 slotId = Integer.parseInt(getNextArgRequired());
1161 } catch (NumberFormatException e) {
1162 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1163 return -1;
1164 }
1165 break;
1166 }
1167 case "-c": {
1168 isCarrierService = true;
1169 break;
1170 }
1171 case "-d": {
1172 isCarrierService = false;
1173 break;
1174 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001175 case "-f": {
1176 String featureString = getNextArgRequired();
1177 String[] features = featureString.split(",");
1178 for (int i = 0; i < features.length; i++) {
1179 try {
1180 Integer result = Integer.parseInt(features[i]);
1181 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1182 || result >= ImsFeature.FEATURE_MAX) {
1183 errPw.println("ims set-ims-service -f " + result
1184 + " is an invalid feature.");
1185 return -1;
1186 }
1187 featuresList.add(result);
1188 } catch (NumberFormatException e) {
1189 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1190 + " as an integer.");
1191 return -1;
1192 }
1193 }
1194 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001195 }
1196 }
1197 // Mandatory param, either -c or -d
1198 if (isCarrierService == null) {
1199 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1200 return -1;
1201 }
1202
1203 String packageName = getNextArg();
1204
1205 try {
1206 if (packageName == null) {
1207 packageName = "";
1208 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001209 int[] featureArray = new int[featuresList.size()];
1210 for (int i = 0; i < featuresList.size(); i++) {
1211 featureArray[i] = featuresList.get(i);
1212 }
1213 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1214 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001215 if (VDBG) {
1216 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001217 + (isCarrierService ? "-c " : "-d ")
1218 + "-f " + featuresList + " "
1219 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001220 }
1221 getOutPrintWriter().println(result);
1222 } catch (RemoteException e) {
1223 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001224 + (isCarrierService ? "-c " : "-d ")
1225 + "-f " + featuresList + " "
1226 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001227 errPw.println("Exception: " + e.getMessage());
1228 return -1;
1229 }
1230 return 0;
1231 }
1232
Brad Ebinger999d3302020-11-25 14:31:39 -08001233 // ims clear-ims-service-override
1234 private int handleImsClearCarrierServiceCommand() {
1235 PrintWriter errPw = getErrPrintWriter();
1236 int slotId = getDefaultSlot();
1237
1238 String opt;
1239 while ((opt = getNextOption()) != null) {
1240 switch (opt) {
1241 case "-s": {
1242 try {
1243 slotId = Integer.parseInt(getNextArgRequired());
1244 } catch (NumberFormatException e) {
1245 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1246 return -1;
1247 }
1248 break;
1249 }
1250 }
1251 }
1252
1253 try {
1254 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1255 if (VDBG) {
1256 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1257 + ", result=" + result);
1258 }
1259 getOutPrintWriter().println(result);
1260 } catch (RemoteException e) {
1261 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1262 + ", error" + e.getMessage());
1263 errPw.println("Exception: " + e.getMessage());
1264 return -1;
1265 }
1266 return 0;
1267 }
1268
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001269 // ims get-ims-service
1270 private int handleImsGetServiceCommand() {
1271 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001272 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001273 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001274 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001275
1276 String opt;
1277 while ((opt = getNextOption()) != null) {
1278 switch (opt) {
1279 case "-s": {
1280 try {
1281 slotId = Integer.parseInt(getNextArgRequired());
1282 } catch (NumberFormatException e) {
1283 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1284 return -1;
1285 }
1286 break;
1287 }
1288 case "-c": {
1289 isCarrierService = true;
1290 break;
1291 }
1292 case "-d": {
1293 isCarrierService = false;
1294 break;
1295 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001296 case "-f": {
1297 try {
1298 featureType = Integer.parseInt(getNextArg());
1299 } catch (NumberFormatException e) {
1300 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1301 return -1;
1302 }
1303 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1304 || featureType >= ImsFeature.FEATURE_MAX) {
1305 errPw.println("ims get-ims-service -f invalid feature.");
1306 return -1;
1307 }
1308 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001309 }
1310 }
1311 // Mandatory param, either -c or -d
1312 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001313 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001314 return -1;
1315 }
1316
1317 String result;
1318 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001319 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001320 } catch (RemoteException e) {
1321 return -1;
1322 }
1323 if (VDBG) {
1324 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001325 + (isCarrierService ? "-c " : "-d ")
1326 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1327 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001328 }
1329 getOutPrintWriter().println(result);
1330 return 0;
1331 }
1332
1333 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001334 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001335 String opt;
1336 while ((opt = getNextOption()) != null) {
1337 switch (opt) {
1338 case "-s": {
1339 try {
1340 slotId = Integer.parseInt(getNextArgRequired());
1341 } catch (NumberFormatException e) {
1342 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1343 return -1;
1344 }
1345 break;
1346 }
1347 }
1348 }
1349 try {
1350 mInterface.enableIms(slotId);
1351 } catch (RemoteException e) {
1352 return -1;
1353 }
1354 if (VDBG) {
1355 Log.v(LOG_TAG, "ims enable -s " + slotId);
1356 }
1357 return 0;
1358 }
1359
1360 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001361 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001362 String opt;
1363 while ((opt = getNextOption()) != null) {
1364 switch (opt) {
1365 case "-s": {
1366 try {
1367 slotId = Integer.parseInt(getNextArgRequired());
1368 } catch (NumberFormatException e) {
1369 getErrPrintWriter().println(
1370 "ims disable requires an integer as a SLOT_ID.");
1371 return -1;
1372 }
1373 break;
1374 }
1375 }
1376 }
1377 try {
1378 mInterface.disableIms(slotId);
1379 } catch (RemoteException e) {
1380 return -1;
1381 }
1382 if (VDBG) {
1383 Log.v(LOG_TAG, "ims disable -s " + slotId);
1384 }
1385 return 0;
1386 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001387
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001388 private int handleCepChange() {
1389 Log.i(LOG_TAG, "handleCepChange");
1390 String opt = getNextArg();
1391 if (opt == null) {
1392 return -1;
1393 }
1394 boolean isCepEnabled = opt.equals("enable");
1395
1396 try {
1397 mInterface.setCepEnabled(isCepEnabled);
1398 } catch (RemoteException e) {
1399 return -1;
1400 }
1401 return 0;
1402 }
1403
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001404 private int getDefaultSlot() {
1405 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1406 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1407 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1408 // If there is no default, default to slot 0.
1409 slotId = DEFAULT_PHONE_ID;
1410 }
1411 return slotId;
1412 }
sqian2fff4a32018-11-05 14:18:37 -08001413
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001414 // Parse options related to Carrier Config Commands.
1415 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001416 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001417 CcOptionParseResult result = new CcOptionParseResult();
1418 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1419 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001420
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001421 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001422 while ((opt = getNextOption()) != null) {
1423 switch (opt) {
1424 case "-s": {
1425 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001426 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1427 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1428 errPw.println(tag + "No valid subscription found.");
1429 return null;
1430 }
1431
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001432 } catch (IllegalArgumentException e) {
1433 // Missing slot id
1434 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001435 return null;
1436 }
1437 break;
1438 }
1439 case "-p": {
1440 if (allowOptionPersistent) {
1441 result.mPersistent = true;
1442 } else {
1443 errPw.println(tag + "Unexpected option " + opt);
1444 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001445 }
1446 break;
1447 }
1448 default: {
1449 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001450 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001451 }
1452 }
1453 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001454 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001455 }
1456
1457 private int slotStringToSubId(String tag, String slotString) {
1458 int slotId = -1;
1459 try {
1460 slotId = Integer.parseInt(slotString);
1461 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001462 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1463 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1464 }
1465
1466 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001467 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1468 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1469 }
1470
Qiong Liuf25799b2020-09-10 10:13:46 +08001471 Phone phone = PhoneFactory.getPhone(slotId);
1472 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001473 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1474 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1475 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001476 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001477 }
1478
Hall Liud892bec2018-11-30 14:51:45 -08001479 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001480 // adb can run as root or as shell, depending on whether the device is rooted.
1481 return Binder.getCallingUid() == Process.SHELL_UID
1482 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001483 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001484
1485 private int handleCcCommand() {
1486 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1487 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001488 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001489 getErrPrintWriter().println("cc: Permission denied.");
1490 return -1;
1491 }
1492
1493 String arg = getNextArg();
1494 if (arg == null) {
1495 onHelpCc();
1496 return 0;
1497 }
1498
1499 switch (arg) {
1500 case CC_GET_VALUE: {
1501 return handleCcGetValue();
1502 }
1503 case CC_SET_VALUE: {
1504 return handleCcSetValue();
1505 }
1506 case CC_CLEAR_VALUES: {
1507 return handleCcClearValues();
1508 }
1509 default: {
1510 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1511 }
1512 }
1513 return -1;
1514 }
1515
1516 // cc get-value
1517 private int handleCcGetValue() {
1518 PrintWriter errPw = getErrPrintWriter();
1519 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1520 String key = null;
1521
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001522 // Parse all options
1523 CcOptionParseResult options = parseCcOptions(tag, false);
1524 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001525 return -1;
1526 }
1527
1528 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001529 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001530 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001531 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001532 return -1;
1533 }
1534
1535 // Get the key.
1536 key = getNextArg();
1537 if (key != null) {
1538 // A key was provided. Verify if it is a valid key
1539 if (!bundle.containsKey(key)) {
1540 errPw.println(tag + key + " is not a valid key.");
1541 return -1;
1542 }
1543
1544 // Print the carrier config value for key.
1545 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1546 } else {
1547 // No key provided. Show all values.
1548 // Iterate over a sorted list of all carrier config keys and print them.
1549 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1550 for (String k : sortedSet) {
1551 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1552 }
1553 }
1554 return 0;
1555 }
1556
1557 // cc set-value
1558 private int handleCcSetValue() {
1559 PrintWriter errPw = getErrPrintWriter();
1560 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1561
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001562 // Parse all options
1563 CcOptionParseResult options = parseCcOptions(tag, true);
1564 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001565 return -1;
1566 }
1567
1568 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001569 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001570 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001571 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001572 return -1;
1573 }
1574
1575 // Get the key.
1576 String key = getNextArg();
1577 if (key == null || key.equals("")) {
1578 errPw.println(tag + "KEY is missing");
1579 return -1;
1580 }
1581
1582 // Verify if the key is valid
1583 if (!originalValues.containsKey(key)) {
1584 errPw.println(tag + key + " is not a valid key.");
1585 return -1;
1586 }
1587
1588 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1589 ArrayList<String> valueList = new ArrayList<String>();
1590 while (peekNextArg() != null) {
1591 valueList.add(getNextArg());
1592 }
1593
1594 // Find the type of the carrier config value
1595 CcType type = getType(tag, key, originalValues);
1596 if (type == CcType.UNKNOWN) {
1597 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1598 return -1;
1599 }
1600
1601 // Create an override bundle containing the key and value that should be overriden.
1602 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1603 if (overrideBundle == null) {
1604 return -1;
1605 }
1606
1607 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001608 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001609
1610 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001611 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001612 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001613 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001614 return -1;
1615 }
1616
1617 // Print the original and new value.
1618 String originalValueString = ccValueToString(key, type, originalValues);
1619 String newValueString = ccValueToString(key, type, newValues);
1620 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1621 getOutPrintWriter().println("New value: \n" + newValueString);
1622
1623 return 0;
1624 }
1625
1626 // cc clear-values
1627 private int handleCcClearValues() {
1628 PrintWriter errPw = getErrPrintWriter();
1629 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1630
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001631 // Parse all options
1632 CcOptionParseResult options = parseCcOptions(tag, false);
1633 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001634 return -1;
1635 }
1636
1637 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001638 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001639 getOutPrintWriter()
1640 .println("All previously set carrier config override values has been cleared");
1641 return 0;
1642 }
1643
1644 private CcType getType(String tag, String key, PersistableBundle bundle) {
1645 // Find the type by checking the type of the current value stored in the bundle.
1646 Object value = bundle.get(key);
1647
1648 if (CC_TYPE_MAP.containsKey(key)) {
1649 return CC_TYPE_MAP.get(key);
1650 } else if (value != null) {
1651 if (value instanceof Boolean) {
1652 return CcType.BOOLEAN;
1653 } else if (value instanceof Double) {
1654 return CcType.DOUBLE;
1655 } else if (value instanceof double[]) {
1656 return CcType.DOUBLE_ARRAY;
1657 } else if (value instanceof Integer) {
1658 return CcType.INT;
1659 } else if (value instanceof int[]) {
1660 return CcType.INT_ARRAY;
1661 } else if (value instanceof Long) {
1662 return CcType.LONG;
1663 } else if (value instanceof long[]) {
1664 return CcType.LONG_ARRAY;
1665 } else if (value instanceof String) {
1666 return CcType.STRING;
1667 } else if (value instanceof String[]) {
1668 return CcType.STRING_ARRAY;
1669 }
1670 } else {
1671 // Current value was null and can therefore not be used in order to find the type.
1672 // Check the name of the key to infer the type. This check is not needed for primitive
1673 // data types (boolean, double, int and long), since they can not be null.
1674 if (key.endsWith("double_array")) {
1675 return CcType.DOUBLE_ARRAY;
1676 }
1677 if (key.endsWith("int_array")) {
1678 return CcType.INT_ARRAY;
1679 }
1680 if (key.endsWith("long_array")) {
1681 return CcType.LONG_ARRAY;
1682 }
1683 if (key.endsWith("string")) {
1684 return CcType.STRING;
1685 }
1686 if (key.endsWith("string_array") || key.endsWith("strings")) {
1687 return CcType.STRING_ARRAY;
1688 }
1689 }
1690
1691 // Not possible to infer the type by looking at the current value or the key.
1692 PrintWriter errPw = getErrPrintWriter();
1693 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1694 return CcType.UNKNOWN;
1695 }
1696
1697 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1698 String result;
1699 StringBuilder valueString = new StringBuilder();
1700 String typeString = type.toString();
1701 Object value = bundle.get(key);
1702
1703 if (value == null) {
1704 valueString.append("null");
1705 } else {
1706 switch (type) {
1707 case DOUBLE_ARRAY: {
1708 // Format the string representation of the int array as value1 value2......
1709 double[] valueArray = (double[]) value;
1710 for (int i = 0; i < valueArray.length; i++) {
1711 if (i != 0) {
1712 valueString.append(" ");
1713 }
1714 valueString.append(valueArray[i]);
1715 }
1716 break;
1717 }
1718 case INT_ARRAY: {
1719 // Format the string representation of the int array as value1 value2......
1720 int[] valueArray = (int[]) value;
1721 for (int i = 0; i < valueArray.length; i++) {
1722 if (i != 0) {
1723 valueString.append(" ");
1724 }
1725 valueString.append(valueArray[i]);
1726 }
1727 break;
1728 }
1729 case LONG_ARRAY: {
1730 // Format the string representation of the int array as value1 value2......
1731 long[] valueArray = (long[]) value;
1732 for (int i = 0; i < valueArray.length; i++) {
1733 if (i != 0) {
1734 valueString.append(" ");
1735 }
1736 valueString.append(valueArray[i]);
1737 }
1738 break;
1739 }
1740 case STRING: {
1741 valueString.append("\"" + value.toString() + "\"");
1742 break;
1743 }
1744 case STRING_ARRAY: {
1745 // Format the string representation of the string array as "value1" "value2"....
1746 String[] valueArray = (String[]) value;
1747 for (int i = 0; i < valueArray.length; i++) {
1748 if (i != 0) {
1749 valueString.append(" ");
1750 }
1751 if (valueArray[i] != null) {
1752 valueString.append("\"" + valueArray[i] + "\"");
1753 } else {
1754 valueString.append("null");
1755 }
1756 }
1757 break;
1758 }
1759 default: {
1760 valueString.append(value.toString());
1761 }
1762 }
1763 }
1764 return String.format("%-70s %-15s %s", key, typeString, valueString);
1765 }
1766
1767 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1768 ArrayList<String> valueList) {
1769 PrintWriter errPw = getErrPrintWriter();
1770 PersistableBundle bundle = new PersistableBundle();
1771
1772 // First verify that a valid number of values has been provided for the type.
1773 switch (type) {
1774 case BOOLEAN:
1775 case DOUBLE:
1776 case INT:
1777 case LONG: {
1778 if (valueList.size() != 1) {
1779 errPw.println(tag + "Expected 1 value for type " + type
1780 + ". Found: " + valueList.size());
1781 return null;
1782 }
1783 break;
1784 }
1785 case STRING: {
1786 if (valueList.size() > 1) {
1787 errPw.println(tag + "Expected 0 or 1 values for type " + type
1788 + ". Found: " + valueList.size());
1789 return null;
1790 }
1791 break;
1792 }
1793 }
1794
1795 // Parse the value according to type and add it to the Bundle.
1796 switch (type) {
1797 case BOOLEAN: {
1798 if ("true".equalsIgnoreCase(valueList.get(0))) {
1799 bundle.putBoolean(key, true);
1800 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1801 bundle.putBoolean(key, false);
1802 } else {
1803 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1804 return null;
1805 }
1806 break;
1807 }
1808 case DOUBLE: {
1809 try {
1810 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1811 } catch (NumberFormatException nfe) {
1812 // Not a valid double
1813 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1814 return null;
1815 }
1816 break;
1817 }
1818 case DOUBLE_ARRAY: {
1819 double[] valueDoubleArray = null;
1820 if (valueList.size() > 0) {
1821 valueDoubleArray = new double[valueList.size()];
1822 for (int i = 0; i < valueList.size(); i++) {
1823 try {
1824 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1825 } catch (NumberFormatException nfe) {
1826 // Not a valid double
1827 errPw.println(
1828 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1829 return null;
1830 }
1831 }
1832 }
1833 bundle.putDoubleArray(key, valueDoubleArray);
1834 break;
1835 }
1836 case INT: {
1837 try {
1838 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1839 } catch (NumberFormatException nfe) {
1840 // Not a valid integer
1841 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1842 return null;
1843 }
1844 break;
1845 }
1846 case INT_ARRAY: {
1847 int[] valueIntArray = null;
1848 if (valueList.size() > 0) {
1849 valueIntArray = new int[valueList.size()];
1850 for (int i = 0; i < valueList.size(); i++) {
1851 try {
1852 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1853 } catch (NumberFormatException nfe) {
1854 // Not a valid integer
1855 errPw.println(tag
1856 + "Unable to parse " + valueList.get(i) + " as an integer.");
1857 return null;
1858 }
1859 }
1860 }
1861 bundle.putIntArray(key, valueIntArray);
1862 break;
1863 }
1864 case LONG: {
1865 try {
1866 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1867 } catch (NumberFormatException nfe) {
1868 // Not a valid long
1869 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1870 return null;
1871 }
1872 break;
1873 }
1874 case LONG_ARRAY: {
1875 long[] valueLongArray = null;
1876 if (valueList.size() > 0) {
1877 valueLongArray = new long[valueList.size()];
1878 for (int i = 0; i < valueList.size(); i++) {
1879 try {
1880 valueLongArray[i] = Long.parseLong(valueList.get(i));
1881 } catch (NumberFormatException nfe) {
1882 // Not a valid long
1883 errPw.println(
1884 tag + "Unable to parse " + valueList.get(i) + " as a long");
1885 return null;
1886 }
1887 }
1888 }
1889 bundle.putLongArray(key, valueLongArray);
1890 break;
1891 }
1892 case STRING: {
1893 String value = null;
1894 if (valueList.size() > 0) {
1895 value = valueList.get(0);
1896 }
1897 bundle.putString(key, value);
1898 break;
1899 }
1900 case STRING_ARRAY: {
1901 String[] valueStringArray = null;
1902 if (valueList.size() > 0) {
1903 valueStringArray = new String[valueList.size()];
1904 valueList.toArray(valueStringArray);
1905 }
1906 bundle.putStringArray(key, valueStringArray);
1907 break;
1908 }
1909 }
1910 return bundle;
1911 }
Shuo Qian489d9282020-07-09 11:30:03 -07001912
1913 private int handleEndBlockSuppressionCommand() {
1914 if (!checkShellUid()) {
1915 return -1;
1916 }
1917
1918 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1919 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1920 }
1921 return 0;
1922 }
Hui Wang641e81c2020-10-12 12:14:23 -07001923
Michele Berionne54af4632020-12-28 20:23:16 +00001924 private int handleRestartModemCommand() {
1925 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1926 // non user build.
1927 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1928 getErrPrintWriter().println("RestartModem: Permission denied.");
1929 return -1;
1930 }
1931
1932 boolean result = TelephonyManager.getDefault().rebootRadio();
1933 getOutPrintWriter().println(result);
1934
1935 return result ? 0 : -1;
1936 }
1937
Ling Ma4fbab492022-01-25 22:36:16 +00001938 private int handleGetImei() {
1939 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1940 // non user build.
1941 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1942 getErrPrintWriter().println("Device IMEI: Permission denied.");
1943 return -1;
1944 }
1945
1946 final long identity = Binder.clearCallingIdentity();
1947
1948 String imei = null;
1949 String arg = getNextArg();
1950 if (arg != null) {
1951 try {
1952 int specifiedSlotIndex = Integer.parseInt(arg);
1953 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
1954 } catch (NumberFormatException exception) {
1955 PrintWriter errPw = getErrPrintWriter();
1956 errPw.println("-s requires an integer as slot index.");
1957 return -1;
1958 }
1959
1960 } else {
1961 imei = TelephonyManager.from(mContext).getImei();
1962 }
1963 getOutPrintWriter().println("Device IMEI: " + imei);
1964
1965 Binder.restoreCallingIdentity(identity);
1966 return 0;
1967 }
1968
Michele Berionne5e411512020-11-13 02:36:59 +00001969 private int handleUnattendedReboot() {
1970 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1971 // non user build.
1972 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1973 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1974 return -1;
1975 }
1976
1977 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1978 getOutPrintWriter().println("result: " + result);
1979
1980 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1981 }
1982
Aman Gupta07124872022-02-09 08:02:14 +00001983 private int handleGetSimSlotsMapping() {
1984 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1985 // non user build.
1986 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1987 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
1988 return -1;
1989 }
1990 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
1991 String result = telephonyManager.getSimSlotMapping().toString();
1992 getOutPrintWriter().println("simSlotsMapping: " + result);
1993
1994 return 0;
1995 }
1996
Hui Wang641e81c2020-10-12 12:14:23 -07001997 private int handleGbaCommand() {
1998 String arg = getNextArg();
1999 if (arg == null) {
2000 onHelpGba();
2001 return 0;
2002 }
2003
2004 switch (arg) {
2005 case GBA_SET_SERVICE: {
2006 return handleGbaSetServiceCommand();
2007 }
2008 case GBA_GET_SERVICE: {
2009 return handleGbaGetServiceCommand();
2010 }
2011 case GBA_SET_RELEASE_TIME: {
2012 return handleGbaSetReleaseCommand();
2013 }
2014 case GBA_GET_RELEASE_TIME: {
2015 return handleGbaGetReleaseCommand();
2016 }
2017 }
2018
2019 return -1;
2020 }
2021
2022 private int getSubId(String cmd) {
2023 int slotId = getDefaultSlot();
2024 String opt = getNextOption();
2025 if (opt != null && opt.equals("-s")) {
2026 try {
2027 slotId = Integer.parseInt(getNextArgRequired());
2028 } catch (NumberFormatException e) {
2029 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2030 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2031 }
2032 }
2033 int[] subIds = SubscriptionManager.getSubId(slotId);
2034 return subIds[0];
2035 }
2036
2037 private int handleGbaSetServiceCommand() {
2038 int subId = getSubId("gba set-service");
2039 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2040 return -1;
2041 }
2042
2043 String packageName = getNextArg();
2044 try {
2045 if (packageName == null) {
2046 packageName = "";
2047 }
2048 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2049 if (VDBG) {
2050 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2051 + packageName + ", result=" + result);
2052 }
2053 getOutPrintWriter().println(result);
2054 } catch (RemoteException e) {
2055 Log.w(LOG_TAG, "gba set-service " + subId + " "
2056 + packageName + ", error" + e.getMessage());
2057 getErrPrintWriter().println("Exception: " + e.getMessage());
2058 return -1;
2059 }
2060 return 0;
2061 }
2062
2063 private int handleGbaGetServiceCommand() {
2064 String result;
2065
2066 int subId = getSubId("gba get-service");
2067 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2068 return -1;
2069 }
2070
2071 try {
2072 result = mInterface.getBoundGbaService(subId);
2073 } catch (RemoteException e) {
2074 return -1;
2075 }
2076 if (VDBG) {
2077 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2078 }
2079 getOutPrintWriter().println(result);
2080 return 0;
2081 }
2082
2083 private int handleGbaSetReleaseCommand() {
2084 //the release time value could be -1
2085 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2086 : SubscriptionManager.getDefaultSubscriptionId();
2087 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2088 return -1;
2089 }
2090
2091 String intervalStr = getNextArg();
2092 if (intervalStr == null) {
2093 return -1;
2094 }
2095
2096 try {
2097 int interval = Integer.parseInt(intervalStr);
2098 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2099 if (VDBG) {
2100 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2101 + intervalStr + ", result=" + result);
2102 }
2103 getOutPrintWriter().println(result);
2104 } catch (NumberFormatException | RemoteException e) {
2105 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2106 + intervalStr + ", error" + e.getMessage());
2107 getErrPrintWriter().println("Exception: " + e.getMessage());
2108 return -1;
2109 }
2110 return 0;
2111 }
2112
2113 private int handleGbaGetReleaseCommand() {
2114 int subId = getSubId("gba get-release");
2115 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2116 return -1;
2117 }
2118
2119 int result = 0;
2120 try {
2121 result = mInterface.getGbaReleaseTime(subId);
2122 } catch (RemoteException e) {
2123 return -1;
2124 }
2125 if (VDBG) {
2126 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2127 }
2128 getOutPrintWriter().println(result);
2129 return 0;
2130 }
Hui Wang761a6682020-10-31 05:12:53 +00002131
2132 private int handleSingleRegistrationConfigCommand() {
2133 String arg = getNextArg();
2134 if (arg == null) {
2135 onHelpSrc();
2136 return 0;
2137 }
2138
2139 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002140 case SRC_SET_TEST_ENABLED: {
2141 return handleSrcSetTestEnabledCommand();
2142 }
2143 case SRC_GET_TEST_ENABLED: {
2144 return handleSrcGetTestEnabledCommand();
2145 }
Hui Wang761a6682020-10-31 05:12:53 +00002146 case SRC_SET_DEVICE_ENABLED: {
2147 return handleSrcSetDeviceEnabledCommand();
2148 }
2149 case SRC_GET_DEVICE_ENABLED: {
2150 return handleSrcGetDeviceEnabledCommand();
2151 }
2152 case SRC_SET_CARRIER_ENABLED: {
2153 return handleSrcSetCarrierEnabledCommand();
2154 }
2155 case SRC_GET_CARRIER_ENABLED: {
2156 return handleSrcGetCarrierEnabledCommand();
2157 }
Hui Wangb647abe2021-02-26 09:33:38 -08002158 case SRC_SET_FEATURE_ENABLED: {
2159 return handleSrcSetFeatureValidationCommand();
2160 }
2161 case SRC_GET_FEATURE_ENABLED: {
2162 return handleSrcGetFeatureValidationCommand();
2163 }
Hui Wang761a6682020-10-31 05:12:53 +00002164 }
2165
2166 return -1;
2167 }
2168
James.cf Linbcdf8b32021-01-14 16:44:13 +08002169 private int handleRcsUceCommand() {
2170 String arg = getNextArg();
2171 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002172 onHelpUce();
2173 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002174 }
2175
2176 switch (arg) {
2177 case UCE_REMOVE_EAB_CONTACT:
2178 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002179 case UCE_GET_EAB_CONTACT:
2180 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002181 case UCE_GET_EAB_CAPABILITY:
2182 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002183 case UCE_GET_DEVICE_ENABLED:
2184 return handleUceGetDeviceEnabledCommand();
2185 case UCE_SET_DEVICE_ENABLED:
2186 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002187 case UCE_OVERRIDE_PUBLISH_CAPS:
2188 return handleUceOverridePublishCaps();
2189 case UCE_GET_LAST_PIDF_XML:
2190 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002191 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2192 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002193 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2194 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002195 }
2196 return -1;
2197 }
2198
2199 private int handleRemovingEabContactCommand() {
2200 int subId = getSubId("uce remove-eab-contact");
2201 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2202 return -1;
2203 }
2204
2205 String phoneNumber = getNextArgRequired();
2206 if (TextUtils.isEmpty(phoneNumber)) {
2207 return -1;
2208 }
2209 int result = 0;
2210 try {
2211 result = mInterface.removeContactFromEab(subId, phoneNumber);
2212 } catch (RemoteException e) {
2213 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2214 getErrPrintWriter().println("Exception: " + e.getMessage());
2215 return -1;
2216 }
2217
2218 if (VDBG) {
2219 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2220 }
calvinpan293ea1b2021-02-04 17:52:13 +08002221 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002222 }
2223
calvinpane4a8a1d2021-01-25 13:51:18 +08002224 private int handleGettingEabContactCommand() {
2225 String phoneNumber = getNextArgRequired();
2226 if (TextUtils.isEmpty(phoneNumber)) {
2227 return -1;
2228 }
2229 String result = "";
2230 try {
2231 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002232 } catch (RemoteException e) {
2233 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2234 getErrPrintWriter().println("Exception: " + e.getMessage());
2235 return -1;
2236 }
2237
2238 if (VDBG) {
2239 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2240 }
calvinpan293ea1b2021-02-04 17:52:13 +08002241 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002242 return 0;
2243 }
2244
Calvin Pana1434322021-07-01 19:27:01 +08002245 private int handleGettingEabCapabilityCommand() {
2246 String phoneNumber = getNextArgRequired();
2247 if (TextUtils.isEmpty(phoneNumber)) {
2248 return -1;
2249 }
2250 String result = "";
2251 try {
2252 result = mInterface.getCapabilityFromEab(phoneNumber);
2253 } catch (RemoteException e) {
2254 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2255 getErrPrintWriter().println("Exception: " + e.getMessage());
2256 return -1;
2257 }
2258
2259 if (VDBG) {
2260 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2261 }
2262 getOutPrintWriter().println(result);
2263 return 0;
2264 }
2265
James.cf Lin4b784aa2021-01-31 03:25:15 +08002266 private int handleUceGetDeviceEnabledCommand() {
2267 boolean result = false;
2268 try {
2269 result = mInterface.getDeviceUceEnabled();
2270 } catch (RemoteException e) {
2271 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2272 return -1;
2273 }
2274 if (VDBG) {
2275 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2276 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002277 getOutPrintWriter().println(result);
2278 return 0;
2279 }
2280
James.cf Lin4b784aa2021-01-31 03:25:15 +08002281 private int handleUceSetDeviceEnabledCommand() {
2282 String enabledStr = getNextArg();
2283 if (TextUtils.isEmpty(enabledStr)) {
2284 return -1;
2285 }
2286
2287 try {
2288 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2289 mInterface.setDeviceUceEnabled(isEnabled);
2290 if (VDBG) {
2291 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2292 }
2293 } catch (NumberFormatException | RemoteException e) {
2294 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2295 getErrPrintWriter().println("Exception: " + e.getMessage());
2296 return -1;
2297 }
2298 return 0;
2299 }
2300
James.cf Line8713a42021-04-29 16:04:26 +08002301 private int handleUceRemoveRequestDisallowedStatus() {
2302 int subId = getSubId("uce remove-request-disallowed-status");
2303 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2304 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2305 return -1;
2306 }
2307 boolean result;
2308 try {
2309 result = mInterface.removeUceRequestDisallowedStatus(subId);
2310 } catch (RemoteException e) {
2311 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2312 return -1;
2313 }
2314 if (VDBG) {
2315 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2316 }
2317 getOutPrintWriter().println(result);
2318 return 0;
2319 }
2320
James.cf Lin0fc71b02021-05-25 01:37:38 +08002321 private int handleUceSetCapRequestTimeout() {
2322 int subId = getSubId("uce set-capabilities-request-timeout");
2323 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2324 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2325 return -1;
2326 }
2327 long timeoutAfterMs = Long.valueOf(getNextArg());
2328 boolean result;
2329 try {
2330 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2331 } catch (RemoteException e) {
2332 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2333 return -1;
2334 }
2335 if (VDBG) {
2336 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2337 }
2338 getOutPrintWriter().println(result);
2339 return 0;
2340 }
2341
Hui Wangbaaee6a2021-02-19 20:45:36 -08002342 private int handleSrcSetTestEnabledCommand() {
2343 String enabledStr = getNextArg();
2344 if (enabledStr == null) {
2345 return -1;
2346 }
2347
2348 try {
2349 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2350 if (VDBG) {
2351 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2352 }
2353 getOutPrintWriter().println("Done");
2354 } catch (NumberFormatException | RemoteException e) {
2355 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2356 getErrPrintWriter().println("Exception: " + e.getMessage());
2357 return -1;
2358 }
2359 return 0;
2360 }
2361
2362 private int handleSrcGetTestEnabledCommand() {
2363 boolean result = false;
2364 try {
2365 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2366 } catch (RemoteException e) {
2367 return -1;
2368 }
2369 if (VDBG) {
2370 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2371 }
2372 getOutPrintWriter().println(result);
2373 return 0;
2374 }
2375
Brad Ebinger14d467f2021-02-12 06:18:28 +00002376 private int handleUceOverridePublishCaps() {
2377 int subId = getSubId("uce override-published-caps");
2378 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2379 return -1;
2380 }
2381 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2382 String operation = getNextArgRequired();
2383 String caps = getNextArg();
2384 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2385 && !"list".equals(operation)) {
2386 getErrPrintWriter().println("Invalid operation: " + operation);
2387 return -1;
2388 }
2389
2390 // add/remove requires capabilities to be specified.
2391 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2392 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2393 + "specified");
2394 return -1;
2395 }
2396
2397 ArraySet<String> capSet = new ArraySet<>();
2398 if (!TextUtils.isEmpty(caps)) {
2399 String[] capArray = caps.split(":");
2400 for (String cap : capArray) {
2401 // Allow unknown tags to be passed in as well.
2402 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2403 }
2404 }
2405
2406 RcsContactUceCapability result = null;
2407 try {
2408 switch (operation) {
2409 case "add":
2410 result = mInterface.addUceRegistrationOverrideShell(subId,
2411 new ArrayList<>(capSet));
2412 break;
2413 case "remove":
2414 result = mInterface.removeUceRegistrationOverrideShell(subId,
2415 new ArrayList<>(capSet));
2416 break;
2417 case "clear":
2418 result = mInterface.clearUceRegistrationOverrideShell(subId);
2419 break;
2420 case "list":
2421 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2422 break;
2423 }
2424 } catch (RemoteException e) {
2425 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2426 getErrPrintWriter().println("Exception: " + e.getMessage());
2427 return -1;
2428 } catch (ServiceSpecificException sse) {
2429 // Reconstruct ImsException
2430 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2431 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2432 getErrPrintWriter().println("Exception: " + imsException);
2433 return -1;
2434 }
2435 if (result == null) {
2436 getErrPrintWriter().println("Service not available");
2437 return -1;
2438 }
2439 getOutPrintWriter().println(result);
2440 return 0;
2441 }
2442
2443 private int handleUceGetPidfXml() {
2444 int subId = getSubId("uce get-last-publish-pidf");
2445 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2446 return -1;
2447 }
2448
2449 String result;
2450 try {
2451 result = mInterface.getLastUcePidfXmlShell(subId);
2452 } catch (RemoteException e) {
2453 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2454 getErrPrintWriter().println("Exception: " + e.getMessage());
2455 return -1;
2456 } catch (ServiceSpecificException sse) {
2457 // Reconstruct ImsException
2458 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2459 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2460 getErrPrintWriter().println("Exception: " + imsException);
2461 return -1;
2462 }
2463 if (result == null) {
2464 getErrPrintWriter().println("Service not available");
2465 return -1;
2466 }
2467 getOutPrintWriter().println(result);
2468 return 0;
2469 }
2470
Hui Wang761a6682020-10-31 05:12:53 +00002471 private int handleSrcSetDeviceEnabledCommand() {
2472 String enabledStr = getNextArg();
2473 if (enabledStr == null) {
2474 return -1;
2475 }
2476
2477 try {
2478 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2479 if (VDBG) {
2480 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2481 }
2482 getOutPrintWriter().println("Done");
2483 } catch (NumberFormatException | RemoteException e) {
2484 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2485 getErrPrintWriter().println("Exception: " + e.getMessage());
2486 return -1;
2487 }
2488 return 0;
2489 }
2490
2491 private int handleSrcGetDeviceEnabledCommand() {
2492 boolean result = false;
2493 try {
2494 result = mInterface.getDeviceSingleRegistrationEnabled();
2495 } catch (RemoteException e) {
2496 return -1;
2497 }
2498 if (VDBG) {
2499 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2500 }
2501 getOutPrintWriter().println(result);
2502 return 0;
2503 }
2504
2505 private int handleSrcSetCarrierEnabledCommand() {
2506 //the release time value could be -1
2507 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2508 : SubscriptionManager.getDefaultSubscriptionId();
2509 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2510 return -1;
2511 }
2512
2513 String enabledStr = getNextArg();
2514 if (enabledStr == null) {
2515 return -1;
2516 }
2517
2518 try {
2519 boolean result =
2520 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2521 if (VDBG) {
2522 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2523 + enabledStr + ", result=" + result);
2524 }
2525 getOutPrintWriter().println(result);
2526 } catch (NumberFormatException | RemoteException e) {
2527 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2528 + enabledStr + ", error" + e.getMessage());
2529 getErrPrintWriter().println("Exception: " + e.getMessage());
2530 return -1;
2531 }
2532 return 0;
2533 }
2534
2535 private int handleSrcGetCarrierEnabledCommand() {
2536 int subId = getSubId("src get-carrier-enabled");
2537 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2538 return -1;
2539 }
2540
2541 boolean result = false;
2542 try {
2543 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2544 } catch (RemoteException e) {
2545 return -1;
2546 }
2547 if (VDBG) {
2548 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2549 }
2550 getOutPrintWriter().println(result);
2551 return 0;
2552 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002553
Hui Wangb647abe2021-02-26 09:33:38 -08002554 private int handleSrcSetFeatureValidationCommand() {
2555 //the release time value could be -1
2556 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2557 : SubscriptionManager.getDefaultSubscriptionId();
2558 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2559 return -1;
2560 }
2561
2562 String enabledStr = getNextArg();
2563 if (enabledStr == null) {
2564 return -1;
2565 }
2566
2567 try {
2568 boolean result =
2569 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2570 if (VDBG) {
2571 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2572 + enabledStr + ", result=" + result);
2573 }
2574 getOutPrintWriter().println(result);
2575 } catch (NumberFormatException | RemoteException e) {
2576 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2577 + enabledStr + ", error" + e.getMessage());
2578 getErrPrintWriter().println("Exception: " + e.getMessage());
2579 return -1;
2580 }
2581 return 0;
2582 }
2583
2584 private int handleSrcGetFeatureValidationCommand() {
2585 int subId = getSubId("src get-feature-validation");
2586 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2587 return -1;
2588 }
2589
2590 Boolean result = false;
2591 try {
2592 result = mInterface.getImsFeatureValidationOverride(subId);
2593 } catch (RemoteException e) {
2594 return -1;
2595 }
2596 if (VDBG) {
2597 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2598 }
2599 getOutPrintWriter().println(result);
2600 return 0;
2601 }
2602
2603
Hall Liuaa4211e2021-01-20 15:43:39 -08002604 private void onHelpCallComposer() {
2605 PrintWriter pw = getOutPrintWriter();
2606 pw.println("Call composer commands");
2607 pw.println(" callcomposer test-mode enable|disable|query");
2608 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2609 pw.println(" upload/download from carrier servers is disabled, and operations are");
2610 pw.println(" performed using emulated local files instead.");
2611 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2612 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2613 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002614 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2615 pw.println(" Enables or disables the user setting for call composer, as set by");
2616 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002617 }
2618
2619 private int handleCallComposerCommand() {
2620 String arg = getNextArg();
2621 if (arg == null) {
2622 onHelpCallComposer();
2623 return 0;
2624 }
2625
2626 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2627 "MODIFY_PHONE_STATE required for call composer shell cmds");
2628 switch (arg) {
2629 case CALL_COMPOSER_TEST_MODE: {
2630 String enabledStr = getNextArg();
2631 if (ENABLE.equals(enabledStr)) {
2632 CallComposerPictureManager.sTestMode = true;
2633 } else if (DISABLE.equals(enabledStr)) {
2634 CallComposerPictureManager.sTestMode = false;
2635 } else if (QUERY.equals(enabledStr)) {
2636 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2637 } else {
2638 onHelpCallComposer();
2639 return 1;
2640 }
2641 break;
2642 }
2643 case CALL_COMPOSER_SIMULATE_CALL: {
2644 int subscriptionId = Integer.valueOf(getNextArg());
2645 String uuidString = getNextArg();
2646 UUID uuid = UUID.fromString(uuidString);
2647 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2648 Binder.withCleanCallingIdentity(() -> {
2649 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2650 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2651 });
2652 try {
2653 Uri uri = storageUriFuture.get();
2654 getOutPrintWriter().println(String.valueOf(uri));
2655 } catch (Exception e) {
2656 throw new RuntimeException(e);
2657 }
2658 break;
2659 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002660 case CALL_COMPOSER_USER_SETTING: {
2661 try {
2662 int subscriptionId = Integer.valueOf(getNextArg());
2663 String enabledStr = getNextArg();
2664 if (ENABLE.equals(enabledStr)) {
2665 mInterface.setCallComposerStatus(subscriptionId,
2666 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2667 } else if (DISABLE.equals(enabledStr)) {
2668 mInterface.setCallComposerStatus(subscriptionId,
2669 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2670 } else if (QUERY.equals(enabledStr)) {
2671 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2672 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2673 } else {
2674 onHelpCallComposer();
2675 return 1;
2676 }
2677 } catch (RemoteException e) {
2678 e.printStackTrace(getOutPrintWriter());
2679 return 1;
2680 }
2681 break;
2682 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002683 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002684 return 0;
2685 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002686
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002687 private int handleHasCarrierPrivilegesCommand() {
2688 String packageName = getNextArgRequired();
2689
2690 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002691 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002692 try {
2693 hasCarrierPrivileges =
2694 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2695 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2696 } catch (RemoteException e) {
2697 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2698 getErrPrintWriter().println("Exception: " + e.getMessage());
2699 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002700 } finally {
2701 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002702 }
2703
2704 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002705 return 0;
2706 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002707
2708 private int handleAllowedNetworkTypesCommand(String command) {
2709 if (!checkShellUid()) {
2710 return -1;
2711 }
2712
2713 PrintWriter errPw = getErrPrintWriter();
2714 String tag = command + ": ";
2715 String opt;
2716 int subId = -1;
2717 Log.v(LOG_TAG, command + " start");
2718
2719 while ((opt = getNextOption()) != null) {
2720 if (opt.equals("-s")) {
2721 try {
2722 subId = slotStringToSubId(tag, getNextArgRequired());
2723 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2724 errPw.println(tag + "No valid subscription found.");
2725 return -1;
2726 }
2727 } catch (IllegalArgumentException e) {
2728 // Missing slot id
2729 errPw.println(tag + "SLOT_ID expected after -s.");
2730 return -1;
2731 }
2732 } else {
2733 errPw.println(tag + "Unknown option " + opt);
2734 return -1;
2735 }
2736 }
2737
2738 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2739 return handleGetAllowedNetworkTypesCommand(subId);
2740 }
2741 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2742 return handleSetAllowedNetworkTypesCommand(subId);
2743 }
2744 return -1;
2745 }
2746
2747 private int handleGetAllowedNetworkTypesCommand(int subId) {
2748 PrintWriter errPw = getErrPrintWriter();
2749
2750 long result = -1;
2751 try {
2752 if (mInterface != null) {
2753 result = mInterface.getAllowedNetworkTypesForReason(subId,
2754 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2755 } else {
2756 throw new IllegalStateException("telephony service is null.");
2757 }
2758 } catch (RemoteException e) {
2759 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2760 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2761 return -1;
2762 }
2763
2764 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2765 return 0;
2766 }
2767
2768 private int handleSetAllowedNetworkTypesCommand(int subId) {
2769 PrintWriter errPw = getErrPrintWriter();
2770
2771 String bitmaskString = getNextArg();
2772 if (TextUtils.isEmpty(bitmaskString)) {
2773 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2774 return -1;
2775 }
2776 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2777 if (allowedNetworkTypes < 0) {
2778 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2779 return -1;
2780 }
2781 boolean result = false;
2782 try {
2783 if (mInterface != null) {
2784 result = mInterface.setAllowedNetworkTypesForReason(subId,
2785 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2786 } else {
2787 throw new IllegalStateException("telephony service is null.");
2788 }
2789 } catch (RemoteException e) {
2790 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2791 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2792 return -1;
2793 }
2794
2795 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2796 if (result) {
2797 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2798 }
2799 getOutPrintWriter().println(resultMessage);
2800 return 0;
2801 }
2802
2803 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2804 if (TextUtils.isEmpty(bitmaskString)) {
2805 return -1;
2806 }
2807 if (VDBG) {
2808 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2809 + ", length: " + bitmaskString.length());
2810 }
2811 try {
2812 return Long.parseLong(bitmaskString, 2);
2813 } catch (NumberFormatException e) {
2814 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2815 return -1;
2816 }
2817 }
Jack Yu4c0a5502021-12-03 23:58:26 -08002818
2819 private int handleGetDataMode() {
2820 if (!checkShellUid()) {
2821 return -1;
2822 }
2823
2824 boolean newDataStackEnabled = false;
2825 try {
2826 newDataStackEnabled = mInterface.isUsingNewDataStack();
2827 } catch (RemoteException e) {
2828 getOutPrintWriter().println("Something went wrong. " + e);
2829 return -1;
2830 }
2831
Jack Yu2f509862022-01-25 10:13:40 -08002832 getOutPrintWriter().println("Telephony is running with the "
2833 + (newDataStackEnabled ? "new" : "old") + " data stack.");
Jack Yu4c0a5502021-12-03 23:58:26 -08002834
2835 boolean configEnabled = Boolean.parseBoolean(DeviceConfig.getProperty(
Jack Yu31b842d2022-01-13 22:13:54 -08002836 DeviceConfig.NAMESPACE_TELEPHONY, "enable_new_data_stack"));
Jack Yu4c0a5502021-12-03 23:58:26 -08002837 if (configEnabled != newDataStackEnabled) {
Jack Yu2f509862022-01-25 10:13:40 -08002838 getOutPrintWriter().println("The new data config has been "
2839 + (configEnabled ? "enabled" : "disabled")
2840 + ". It will be effective after reboot.");
Jack Yu4c0a5502021-12-03 23:58:26 -08002841 }
2842 return 0;
2843 }
jimsun3b9ccac2021-10-26 15:01:23 +08002844
2845 private int handleRadioSetModemServiceCommand() {
2846 PrintWriter errPw = getErrPrintWriter();
2847 String serviceName = null;
2848
2849 String opt;
2850 while ((opt = getNextOption()) != null) {
2851 switch (opt) {
2852 case "-s": {
2853 serviceName = getNextArgRequired();
2854 break;
2855 }
2856 }
2857 }
2858
2859 try {
2860 boolean result = mInterface.setModemService(serviceName);
2861 if (VDBG) {
2862 Log.v(LOG_TAG,
2863 "RadioSetModemService " + serviceName + ", result = " + result);
2864 }
2865 getOutPrintWriter().println(result);
2866 } catch (RemoteException e) {
2867 Log.w(LOG_TAG,
2868 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2869 errPw.println("Exception: " + e.getMessage());
2870 return -1;
2871 }
2872 return 0;
2873 }
2874
2875 private int handleRadioGetModemServiceCommand() {
2876 PrintWriter errPw = getErrPrintWriter();
2877 String result;
2878
2879 try {
2880 result = mInterface.getModemService();
2881 getOutPrintWriter().println(result);
2882 } catch (RemoteException e) {
2883 errPw.println("Exception: " + e.getMessage());
2884 return -1;
2885 }
2886 if (VDBG) {
2887 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2888 }
2889 return 0;
2890 }
2891
2892 private int handleRadioCommand() {
2893 String arg = getNextArg();
2894 if (arg == null) {
2895 onHelpRadio();
2896 return 0;
2897 }
2898
2899 switch (arg) {
2900 case RADIO_SET_MODEM_SERVICE:
2901 return handleRadioSetModemServiceCommand();
2902
2903 case RADIO_GET_MODEM_SERVICE:
2904 return handleRadioGetModemServiceCommand();
2905 }
2906
2907 return -1;
2908 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002909}