blob: b158588c126b642e178cef2a5ae6d13dcefdab89 [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";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700176 // Take advantage of existing methods that already contain permissions checks when possible.
177 private final ITelephony mInterface;
178
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100179 private SubscriptionManager mSubscriptionManager;
180 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700181 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700182 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100183
184 private enum CcType {
185 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
186 STRING_ARRAY, UNKNOWN
187 }
188
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100189 private class CcOptionParseResult {
190 public int mSubId;
191 public boolean mPersistent;
192 }
193
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100194 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
195 // keys by looking at the end of the string which usually tells the type.
196 // For instance: "xxxx_string", "xxxx_string_array", etc.
197 // The carrier config keys in this map does not follow this convention. It is therefore not
198 // possible to infer the type for these keys by looking at the string.
199 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
200 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
206 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
207 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
208 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
209 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
210 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
211 CcType.STRING);
212 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
213 CcType.STRING_ARRAY);
214 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
215 CcType.STRING_ARRAY);
216 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
217 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
219 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
220 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
221 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
222 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
223 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
224 }
225 };
226
Brad Ebinger14d467f2021-02-12 06:18:28 +0000227 /**
228 * Map from a shorthand string to the feature tags required in registration required in order
229 * for the RCS feature to be considered "capable".
230 */
231 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
232 static {
233 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
234 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
235 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
236 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
237 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
238 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
239 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
240 FeatureTags.FEATURE_TAG_VIDEO)));
241 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
242 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
243 map.put("call_comp",
244 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
245 map.put("call_comp_mmtel",
246 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
247 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
248 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
249 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
250 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
251 // version
252 map.put("chatbot", new ArraySet<>(Arrays.asList(
253 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
254 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
255 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
256 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000257 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000258 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
259 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
260 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
261 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
262 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000263 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000264 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
265 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
266 }
267
268
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100269 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700270 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100271 mCarrierConfigManager =
272 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
273 mSubscriptionManager = (SubscriptionManager)
274 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700275 mTelephonyRegistryManager = (TelephonyRegistryManager)
276 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700277 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700278 }
279
280 @Override
281 public int onCommand(String cmd) {
282 if (cmd == null) {
283 return handleDefaultCommands(null);
284 }
285
286 switch (cmd) {
287 case IMS_SUBCOMMAND: {
288 return handleImsCommand();
289 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800290 case RCS_UCE_COMMAND:
291 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800292 case NUMBER_VERIFICATION_SUBCOMMAND:
293 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800294 case EMERGENCY_CALLBACK_MODE:
295 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800296 case EMERGENCY_NUMBER_TEST_MODE:
297 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100298 case CARRIER_CONFIG_SUBCOMMAND: {
299 return handleCcCommand();
300 }
Shuo Qianf5125122019-12-16 17:03:07 -0800301 case DATA_TEST_MODE:
302 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700303 case END_BLOCK_SUPPRESSION:
304 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700305 case GBA_SUBCOMMAND:
306 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800307 case D2D_SUBCOMMAND:
308 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700309 case BARRING_SUBCOMMAND:
310 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000311 case SINGLE_REGISTATION_CONFIG:
312 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000313 case RESTART_MODEM:
314 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800315 case CALL_COMPOSER_SUBCOMMAND:
316 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000317 case UNATTENDED_REBOOT:
318 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800319 case HAS_CARRIER_PRIVILEGES_COMMAND:
320 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800321 case THERMAL_MITIGATION_COMMAND:
322 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700323 case DISABLE_PHYSICAL_SUBSCRIPTION:
324 return handleEnablePhysicalSubscription(false);
325 case ENABLE_PHYSICAL_SUBSCRIPTION:
326 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800327 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
328 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
329 return handleAllowedNetworkTypesCommand(cmd);
Jack Yu4c0a5502021-12-03 23:58:26 -0800330 case GET_DATA_MODE:
331 return handleGetDataMode();
Ling Ma4fbab492022-01-25 22:36:16 +0000332 case GET_IMEI:
333 return handleGetImei();
jimsun3b9ccac2021-10-26 15:01:23 +0800334 case RADIO_SUBCOMMAND:
335 return handleRadioCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700336 default: {
337 return handleDefaultCommands(cmd);
338 }
339 }
340 }
341
342 @Override
343 public void onHelp() {
344 PrintWriter pw = getOutPrintWriter();
345 pw.println("Telephony Commands:");
346 pw.println(" help");
347 pw.println(" Print this help text.");
348 pw.println(" ims");
349 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800350 pw.println(" uce");
351 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800352 pw.println(" emergency-number-test-mode");
353 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700354 pw.println(" end-block-suppression");
355 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800356 pw.println(" data");
357 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100358 pw.println(" cc");
359 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700360 pw.println(" gba");
361 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000362 pw.println(" src");
363 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000364 pw.println(" restart-modem");
365 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000366 pw.println(" unattended-reboot");
367 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800368 pw.println(" has-carrier-privileges [package]");
369 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800370 pw.println(" get-allowed-network-types-for-users");
371 pw.println(" Get the Allowed Network Types.");
372 pw.println(" set-allowed-network-types-for-users");
373 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800374 pw.println(" radio");
375 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700376 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800377 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800378 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700379 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800380 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100381 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700382 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000383 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800384 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700385 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800386 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800387 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000388 onHelpImei();
Tyler Gunn92479152021-01-20 16:30:10 -0800389 }
390
391 private void onHelpD2D() {
392 PrintWriter pw = getOutPrintWriter();
393 pw.println("D2D Comms Commands:");
394 pw.println(" d2d send TYPE VALUE");
395 pw.println(" Sends a D2D message of specified type and value.");
396 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
397 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
398 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
399 MESSAGE_CALL_AUDIO_CODEC));
400 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
401 + Communicator.messageToString(
402 MESSAGE_DEVICE_BATTERY_STATE));
403 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
404 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800405 pw.println(" d2d transport TYPE");
406 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
407 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700408 pw.println(" d2d set-device-support true/default");
409 pw.println(" true - forces device support to be enabled for D2D.");
410 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
411 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700412 }
413
Nazanin014f41e2021-05-06 17:26:31 -0700414 private void onHelpBarring() {
415 PrintWriter pw = getOutPrintWriter();
416 pw.println("Barring Commands:");
417 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
418 + " -t CONDITIONAL_BARRING_TIME_SECS");
419 pw.println(" Notifies of a barring info change for the specified slot id.");
420 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
421 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
422 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
423 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
424 }
425
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700426 private void onHelpIms() {
427 PrintWriter pw = getOutPrintWriter();
428 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800429 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700430 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
431 pw.println(" ImsService. Options are:");
432 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
433 pw.println(" is specified, it will choose the default voice SIM slot.");
434 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
435 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800436 pw.println(" -f: Set the feature that this override if for, if no option is");
437 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700438 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
439 pw.println(" Gets the package name of the currently defined ImsService.");
440 pw.println(" Options are:");
441 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
442 pw.println(" is specified, it will choose the default voice SIM slot.");
443 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000444 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800445 pw.println(" -f: The feature type that the query will be requested for. If none is");
446 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800447 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
448 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
449 pw.println(" configuration overrides. Options are:");
450 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
451 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700452 pw.println(" ims enable [-s SLOT_ID]");
453 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
454 pw.println(" if none is specified.");
455 pw.println(" ims disable [-s SLOT_ID]");
456 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
457 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700458 pw.println(" ims conference-event-package [enable/disable]");
459 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700460 }
461
James.cf Linbcdf8b32021-01-14 16:44:13 +0800462 private void onHelpUce() {
463 PrintWriter pw = getOutPrintWriter();
464 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800465 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
466 pw.println(" Get the EAB contacts from the EAB database.");
467 pw.println(" Options are:");
468 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
469 pw.println(" Expected output format :");
470 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800471 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
472 pw.println(" Remove the EAB contacts from the EAB database.");
473 pw.println(" Options are:");
474 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
475 pw.println(" is specified, it will choose the default voice SIM slot.");
476 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800477 pw.println(" uce get-device-enabled");
478 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
479 pw.println(" uce set-device-enabled true|false");
480 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
481 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000482 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
483 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
484 pw.println(" Options are:");
485 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
486 pw.println(" is specified, it will choose the default voice SIM slot.");
487 pw.println(" add [CAPABILITY]: add a new capability");
488 pw.println(" remove [CAPABILITY]: remove a capability");
489 pw.println(" clear: clear all capability overrides");
490 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
491 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
492 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
493 pw.println(" chatbot_sa, chatbot_role] as well as full length");
494 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
495 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
496 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
497 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800498 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
499 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800500 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
501 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800502 }
503
Hall Liud892bec2018-11-30 14:51:45 -0800504 private void onHelpNumberVerification() {
505 PrintWriter pw = getOutPrintWriter();
506 pw.println("Number verification commands");
507 pw.println(" numverify override-package PACKAGE_NAME;");
508 pw.println(" Set the authorized package for number verification.");
509 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800510 pw.println(" numverify fake-call NUMBER;");
511 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
512 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800513 }
514
Jack Nudelman644b91a2021-03-12 14:09:48 -0800515 private void onHelpThermalMitigation() {
516 PrintWriter pw = getOutPrintWriter();
517 pw.println("Thermal mitigation commands");
518 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
519 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
520 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
521 pw.println(" Remove the package from one of the authorized packages for thermal "
522 + "mitigation.");
523 }
524
Jordan Liu0ccee222021-04-27 11:55:13 -0700525 private void onHelpDisableOrEnablePhysicalSubscription() {
526 PrintWriter pw = getOutPrintWriter();
527 pw.println("Disable or enable a physical subscription");
528 pw.println(" disable-physical-subscription SUB_ID");
529 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
530 pw.println(" enable-physical-subscription SUB_ID");
531 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
532 }
533
Shuo Qianf5125122019-12-16 17:03:07 -0800534 private void onHelpDataTestMode() {
535 PrintWriter pw = getOutPrintWriter();
536 pw.println("Mobile Data Test Mode Commands:");
537 pw.println(" data enable: enable mobile data connectivity");
538 pw.println(" data disable: disable mobile data connectivity");
539 }
540
sqian9d4df8b2019-01-15 18:32:07 -0800541 private void onHelpEmergencyNumber() {
542 PrintWriter pw = getOutPrintWriter();
543 pw.println("Emergency Number Test Mode Commands:");
544 pw.println(" emergency-number-test-mode ");
545 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
546 + " the test mode");
547 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700548 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800549 pw.println(" -c: clear the emergency number list in the test mode.");
550 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700551 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800552 pw.println(" -p: get the full emergency number list in the test mode.");
553 }
554
Shuo Qian489d9282020-07-09 11:30:03 -0700555 private void onHelpEndBlockSupperssion() {
556 PrintWriter pw = getOutPrintWriter();
557 pw.println("End Block Suppression command:");
558 pw.println(" end-block-suppression: disable suppressing blocking by contact");
559 pw.println(" with emergency services.");
560 }
561
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100562 private void onHelpCc() {
563 PrintWriter pw = getOutPrintWriter();
564 pw.println("Carrier Config Commands:");
565 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
566 pw.println(" Print carrier config values.");
567 pw.println(" Options are:");
568 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
569 pw.println(" is specified, it will choose the default voice SIM slot.");
570 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
571 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100572 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100573 pw.println(" Set carrier config KEY to NEW_VALUE.");
574 pw.println(" Options are:");
575 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
576 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100577 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100578 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
579 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
580 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
581 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
582 pw.println(" cc clear-values [-s SLOT_ID]");
583 pw.println(" Clear all carrier override values that has previously been set");
584 pw.println(" with set-value");
585 pw.println(" Options are:");
586 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
587 pw.println(" is specified, it will choose the default voice SIM slot.");
588 }
589
Hui Wang641e81c2020-10-12 12:14:23 -0700590 private void onHelpGba() {
591 PrintWriter pw = getOutPrintWriter();
592 pw.println("Gba Commands:");
593 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
594 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
595 pw.println(" Options are:");
596 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
597 pw.println(" is specified, it will choose the default voice SIM slot.");
598 pw.println(" gba get-service [-s SLOT_ID]");
599 pw.println(" Gets the package name of the currently defined GbaService.");
600 pw.println(" Options are:");
601 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
602 pw.println(" is specified, it will choose the default voice SIM slot.");
603 pw.println(" gba set-release [-s SLOT_ID] n");
604 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
605 pw.println(" Do not release/unbind if n is -1.");
606 pw.println(" Options are:");
607 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
608 pw.println(" is specified, it will choose the default voice SIM slot.");
609 pw.println(" gba get-release [-s SLOT_ID]");
610 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
611 pw.println(" Options are:");
612 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
613 pw.println(" is specified, it will choose the default voice SIM slot.");
614 }
615
Hui Wang761a6682020-10-31 05:12:53 +0000616 private void onHelpSrc() {
617 PrintWriter pw = getOutPrintWriter();
618 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800619 pw.println(" src set-test-enabled true|false");
620 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
621 pw.println(" The value could be true, false, or null(undefined).");
622 pw.println(" src get-test-enabled");
623 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000624 pw.println(" src set-device-enabled true|false|null");
625 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
626 pw.println(" The value could be true, false, or null(undefined).");
627 pw.println(" src get-device-enabled");
628 pw.println(" Gets the device config for RCS VoLTE single registration.");
629 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
630 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
631 pw.println(" The value could be true, false, or null(undefined).");
632 pw.println(" Options are:");
633 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
634 pw.println(" is specified, it will choose the default voice SIM slot.");
635 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
636 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
637 pw.println(" Options are:");
638 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
639 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800640 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
641 pw.println(" Sets ims feature validation result.");
642 pw.println(" The value could be true, false, or null(undefined).");
643 pw.println(" Options are:");
644 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
645 pw.println(" is specified, it will choose the default voice SIM slot.");
646 pw.println(" src get-feature-validation [-s SLOT_ID]");
647 pw.println(" Gets ims feature validation override value.");
648 pw.println(" Options are:");
649 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
650 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000651 }
652
SongFerngWang98dd5992021-05-13 17:50:00 +0800653 private void onHelpAllowedNetworkTypes() {
654 PrintWriter pw = getOutPrintWriter();
655 pw.println("Allowed Network Types Commands:");
656 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
657 pw.println(" Print allowed network types value.");
658 pw.println(" Options are:");
659 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
660 pw.println(" option is specified, it will choose the default voice SIM slot.");
661 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
662 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
663 pw.println(" Options are:");
664 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
665 pw.println(" option is specified, it will choose the default voice SIM slot.");
666 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
667 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
668 pw.println(" at TelephonyManager.java");
669 pw.println(" For example:");
670 pw.println(" NR only : 10000000000000000000");
671 pw.println(" NR|LTE : 11000001000000000000");
672 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
673 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
674 pw.println(" LTE only : 01000001000000000000");
675 }
676
jimsun3b9ccac2021-10-26 15:01:23 +0800677 private void onHelpRadio() {
678 PrintWriter pw = getOutPrintWriter();
679 pw.println("Radio Commands:");
680 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
681 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
682 pw.println(" to be the bound. Options are:");
683 pw.println(" -s: the service name that the modem service should be bound for.");
684 pw.println(" If no option is specified, it will bind to the default.");
685 pw.println(" radio get-modem-service");
686 pw.println(" Gets the service name of the currently defined modem service.");
687 pw.println(" If it is binding to default, 'default' returns.");
688 pw.println(" If it doesn't bind to any modem service for some reasons,");
689 pw.println(" the result would be 'unknown'.");
690 }
691
Ling Ma4fbab492022-01-25 22:36:16 +0000692 private void onHelpImei() {
693 PrintWriter pw = getOutPrintWriter();
694 pw.println("IMEI Commands:");
695 pw.println(" get-imei [-s SLOT_ID]");
696 pw.println(" Gets the device IMEI. Options are:");
697 pw.println(" -s: the slot ID to get the IMEI. If no option");
698 pw.println(" is specified, it will choose the default voice SIM slot.");
699 }
700
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700701 private int handleImsCommand() {
702 String arg = getNextArg();
703 if (arg == null) {
704 onHelpIms();
705 return 0;
706 }
707
708 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800709 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700710 return handleImsSetServiceCommand();
711 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800712 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700713 return handleImsGetServiceCommand();
714 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800715 case IMS_CLEAR_SERVICE_OVERRIDE: {
716 return handleImsClearCarrierServiceCommand();
717 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800718 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700719 return handleEnableIms();
720 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800721 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700722 return handleDisableIms();
723 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700724 case IMS_CEP: {
725 return handleCepChange();
726 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700727 }
728
729 return -1;
730 }
731
Shuo Qianf5125122019-12-16 17:03:07 -0800732 private int handleDataTestModeCommand() {
733 PrintWriter errPw = getErrPrintWriter();
734 String arg = getNextArgRequired();
735 if (arg == null) {
736 onHelpDataTestMode();
737 return 0;
738 }
739 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800740 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800741 try {
742 mInterface.enableDataConnectivity();
743 } catch (RemoteException ex) {
744 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
745 errPw.println("Exception: " + ex.getMessage());
746 return -1;
747 }
748 break;
749 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800750 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800751 try {
752 mInterface.disableDataConnectivity();
753 } catch (RemoteException ex) {
754 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
755 errPw.println("Exception: " + ex.getMessage());
756 return -1;
757 }
758 break;
759 }
760 default:
761 onHelpDataTestMode();
762 break;
763 }
764 return 0;
765 }
766
Shuo Qianccbaf742021-02-22 18:32:21 -0800767 private int handleEmergencyCallbackModeCommand() {
768 PrintWriter errPw = getErrPrintWriter();
769 try {
770 mInterface.startEmergencyCallbackMode();
771 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
772 } catch (RemoteException ex) {
773 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
774 errPw.println("Exception: " + ex.getMessage());
775 return -1;
776 }
777 return 0;
778 }
779
sqian9d4df8b2019-01-15 18:32:07 -0800780 private int handleEmergencyNumberTestModeCommand() {
781 PrintWriter errPw = getErrPrintWriter();
782 String opt = getNextOption();
783 if (opt == null) {
784 onHelpEmergencyNumber();
785 return 0;
786 }
787
788 switch (opt) {
789 case "-a": {
790 String emergencyNumberCmd = getNextArgRequired();
791 if (emergencyNumberCmd == null
792 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700793 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800794 + " to be specified after -a in the command ");
795 return -1;
796 }
797 try {
798 mInterface.updateEmergencyNumberListTestMode(
799 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
800 new EmergencyNumber(emergencyNumberCmd, "", "",
801 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
802 new ArrayList<String>(),
803 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
804 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
805 } catch (RemoteException ex) {
806 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
807 + ", error " + ex.getMessage());
808 errPw.println("Exception: " + ex.getMessage());
809 return -1;
810 }
811 break;
812 }
813 case "-c": {
814 try {
815 mInterface.updateEmergencyNumberListTestMode(
816 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
817 } catch (RemoteException ex) {
818 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
819 errPw.println("Exception: " + ex.getMessage());
820 return -1;
821 }
822 break;
823 }
824 case "-r": {
825 String emergencyNumberCmd = getNextArgRequired();
826 if (emergencyNumberCmd == null
827 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700828 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800829 + " to be specified after -r in the command ");
830 return -1;
831 }
832 try {
833 mInterface.updateEmergencyNumberListTestMode(
834 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
835 new EmergencyNumber(emergencyNumberCmd, "", "",
836 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
837 new ArrayList<String>(),
838 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
839 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
840 } catch (RemoteException ex) {
841 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
842 + ", error " + ex.getMessage());
843 errPw.println("Exception: " + ex.getMessage());
844 return -1;
845 }
846 break;
847 }
848 case "-p": {
849 try {
850 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
851 } catch (RemoteException ex) {
852 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
853 errPw.println("Exception: " + ex.getMessage());
854 return -1;
855 }
856 break;
857 }
858 default:
859 onHelpEmergencyNumber();
860 break;
861 }
862 return 0;
863 }
864
Hall Liud892bec2018-11-30 14:51:45 -0800865 private int handleNumberVerificationCommand() {
866 String arg = getNextArg();
867 if (arg == null) {
868 onHelpNumberVerification();
869 return 0;
870 }
871
Hall Liuca5af3a2018-12-04 16:58:23 -0800872 if (!checkShellUid()) {
873 return -1;
874 }
875
Hall Liud892bec2018-11-30 14:51:45 -0800876 switch (arg) {
877 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800878 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
879 return 0;
880 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800881 case NUMBER_VERIFICATION_FAKE_CALL: {
882 boolean val = NumberVerificationManager.getInstance()
883 .checkIncomingCall(getNextArg());
884 getOutPrintWriter().println(val ? "1" : "0");
885 return 0;
886 }
Hall Liud892bec2018-11-30 14:51:45 -0800887 }
888
889 return -1;
890 }
891
Jordan Liu0ccee222021-04-27 11:55:13 -0700892 private boolean subIsEsim(int subId) {
893 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
894 if (info != null) {
895 return info.isEmbedded();
896 }
897 return false;
898 }
899
900 private int handleEnablePhysicalSubscription(boolean enable) {
901 PrintWriter errPw = getErrPrintWriter();
902 int subId = 0;
903 try {
904 subId = Integer.parseInt(getNextArgRequired());
905 } catch (NumberFormatException e) {
906 errPw.println((enable ? "enable" : "disable")
907 + "-physical-subscription requires an integer as a subId.");
908 return -1;
909 }
910 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
911 // non user build.
912 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
913 errPw.println("cc: Permission denied.");
914 return -1;
915 }
916 // Verify that the subId represents a physical sub
917 if (subIsEsim(subId)) {
918 errPw.println("SubId " + subId + " is not for a physical subscription");
919 return -1;
920 }
921 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
922 + " physical subscription with subId=" + subId);
923 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
924 return 0;
925 }
926
Jack Nudelman644b91a2021-03-12 14:09:48 -0800927 private int handleThermalMitigationCommand() {
928 String arg = getNextArg();
929 String packageName = getNextArg();
930 if (arg == null || packageName == null) {
931 onHelpThermalMitigation();
932 return 0;
933 }
934
935 if (!checkShellUid()) {
936 return -1;
937 }
938
939 switch (arg) {
940 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
941 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
942 return 0;
943 }
944 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
945 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
946 mContext);
947 return 0;
948 }
949 default:
950 onHelpThermalMitigation();
951 }
952
953 return -1;
954
955 }
956
Tyler Gunn92479152021-01-20 16:30:10 -0800957 private int handleD2dCommand() {
958 String arg = getNextArg();
959 if (arg == null) {
960 onHelpD2D();
961 return 0;
962 }
963
964 switch (arg) {
965 case D2D_SEND: {
966 return handleD2dSendCommand();
967 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800968 case D2D_TRANSPORT: {
969 return handleD2dTransportCommand();
970 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700971 case D2D_SET_DEVICE_SUPPORT: {
972 return handleD2dDeviceSupportedCommand();
973 }
Tyler Gunn92479152021-01-20 16:30:10 -0800974 }
975
976 return -1;
977 }
978
979 private int handleD2dSendCommand() {
980 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800981 int messageType = -1;
982 int messageValue = -1;
983
Tyler Gunn92479152021-01-20 16:30:10 -0800984 String arg = getNextArg();
985 if (arg == null) {
986 onHelpD2D();
987 return 0;
988 }
989 try {
990 messageType = Integer.parseInt(arg);
991 } catch (NumberFormatException e) {
992 errPw.println("message type must be a valid integer");
993 return -1;
994 }
995
996 arg = getNextArg();
997 if (arg == null) {
998 onHelpD2D();
999 return 0;
1000 }
1001 try {
1002 messageValue = Integer.parseInt(arg);
1003 } catch (NumberFormatException e) {
1004 errPw.println("message value must be a valid integer");
1005 return -1;
1006 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001007
Tyler Gunn92479152021-01-20 16:30:10 -08001008 try {
1009 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1010 } catch (RemoteException e) {
1011 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1012 errPw.println("Exception: " + e.getMessage());
1013 return -1;
1014 }
1015
1016 return 0;
1017 }
1018
Tyler Gunnbabbda02021-02-10 11:05:02 -08001019 private int handleD2dTransportCommand() {
1020 PrintWriter errPw = getErrPrintWriter();
1021
1022 String arg = getNextArg();
1023 if (arg == null) {
1024 onHelpD2D();
1025 return 0;
1026 }
1027
1028 try {
1029 mInterface.setActiveDeviceToDeviceTransport(arg);
1030 } catch (RemoteException e) {
1031 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1032 errPw.println("Exception: " + e.getMessage());
1033 return -1;
1034 }
1035 return 0;
1036 }
Nazanin014f41e2021-05-06 17:26:31 -07001037 private int handleBarringCommand() {
1038 String arg = getNextArg();
1039 if (arg == null) {
1040 onHelpBarring();
1041 return 0;
1042 }
1043
1044 switch (arg) {
1045 case BARRING_SEND_INFO: {
1046 return handleBarringSendCommand();
1047 }
1048 }
1049 return -1;
1050 }
1051
1052 private int handleBarringSendCommand() {
1053 PrintWriter errPw = getErrPrintWriter();
1054 int slotId = getDefaultSlot();
1055 int subId = SubscriptionManager.getSubId(slotId)[0];
1056 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1057 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1058 boolean isConditionallyBarred = false;
1059 int conditionalBarringTimeSeconds = 0;
1060
1061 String opt;
1062 while ((opt = getNextOption()) != null) {
1063 switch (opt) {
1064 case "-s": {
1065 try {
1066 slotId = Integer.parseInt(getNextArgRequired());
1067 subId = SubscriptionManager.getSubId(slotId)[0];
1068 } catch (NumberFormatException e) {
1069 errPw.println("barring send requires an integer as a SLOT_ID.");
1070 return -1;
1071 }
1072 break;
1073 }
1074 case "-b": {
1075 try {
1076 barringType = Integer.parseInt(getNextArgRequired());
1077 if (barringType < -1 || barringType > 2) {
1078 throw new NumberFormatException();
1079 }
1080
1081 } catch (NumberFormatException e) {
1082 errPw.println("barring send requires an integer in range [-1,2] as "
1083 + "a BARRING_TYPE.");
1084 return -1;
1085 }
1086 break;
1087 }
1088 case "-c": {
1089 try {
1090 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1091 } catch (Exception e) {
1092 errPw.println("barring send requires a boolean after -c indicating"
1093 + " conditional barring");
1094 return -1;
1095 }
1096 break;
1097 }
1098 case "-t": {
1099 try {
1100 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1101 } catch (NumberFormatException e) {
1102 errPw.println("barring send requires an integer for time of barring"
1103 + " in seconds after -t for conditional barring");
1104 return -1;
1105 }
1106 break;
1107 }
1108 }
1109 }
1110 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1111 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1112 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1113 barringServiceInfos.append(0, bsi);
1114 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1115 try {
1116 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1117 } catch (Exception e) {
1118 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1119 errPw.println("Exception: " + e.getMessage());
1120 return -1;
1121 }
1122 return 0;
1123 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001124
Tyler Gunnd4575212021-05-03 14:46:49 -07001125 private int handleD2dDeviceSupportedCommand() {
1126 PrintWriter errPw = getErrPrintWriter();
1127
1128 String arg = getNextArg();
1129 if (arg == null) {
1130 onHelpD2D();
1131 return 0;
1132 }
1133
1134 boolean isEnabled = "true".equals(arg.toLowerCase());
1135 try {
1136 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1137 } catch (RemoteException e) {
1138 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1139 errPw.println("Exception: " + e.getMessage());
1140 return -1;
1141 }
1142 return 0;
1143 }
1144
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001145 // ims set-ims-service
1146 private int handleImsSetServiceCommand() {
1147 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001148 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001149 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001150 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001151
1152 String opt;
1153 while ((opt = getNextOption()) != null) {
1154 switch (opt) {
1155 case "-s": {
1156 try {
1157 slotId = Integer.parseInt(getNextArgRequired());
1158 } catch (NumberFormatException e) {
1159 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1160 return -1;
1161 }
1162 break;
1163 }
1164 case "-c": {
1165 isCarrierService = true;
1166 break;
1167 }
1168 case "-d": {
1169 isCarrierService = false;
1170 break;
1171 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001172 case "-f": {
1173 String featureString = getNextArgRequired();
1174 String[] features = featureString.split(",");
1175 for (int i = 0; i < features.length; i++) {
1176 try {
1177 Integer result = Integer.parseInt(features[i]);
1178 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1179 || result >= ImsFeature.FEATURE_MAX) {
1180 errPw.println("ims set-ims-service -f " + result
1181 + " is an invalid feature.");
1182 return -1;
1183 }
1184 featuresList.add(result);
1185 } catch (NumberFormatException e) {
1186 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1187 + " as an integer.");
1188 return -1;
1189 }
1190 }
1191 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001192 }
1193 }
1194 // Mandatory param, either -c or -d
1195 if (isCarrierService == null) {
1196 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1197 return -1;
1198 }
1199
1200 String packageName = getNextArg();
1201
1202 try {
1203 if (packageName == null) {
1204 packageName = "";
1205 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001206 int[] featureArray = new int[featuresList.size()];
1207 for (int i = 0; i < featuresList.size(); i++) {
1208 featureArray[i] = featuresList.get(i);
1209 }
1210 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1211 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001212 if (VDBG) {
1213 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001214 + (isCarrierService ? "-c " : "-d ")
1215 + "-f " + featuresList + " "
1216 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001217 }
1218 getOutPrintWriter().println(result);
1219 } catch (RemoteException e) {
1220 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001221 + (isCarrierService ? "-c " : "-d ")
1222 + "-f " + featuresList + " "
1223 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001224 errPw.println("Exception: " + e.getMessage());
1225 return -1;
1226 }
1227 return 0;
1228 }
1229
Brad Ebinger999d3302020-11-25 14:31:39 -08001230 // ims clear-ims-service-override
1231 private int handleImsClearCarrierServiceCommand() {
1232 PrintWriter errPw = getErrPrintWriter();
1233 int slotId = getDefaultSlot();
1234
1235 String opt;
1236 while ((opt = getNextOption()) != null) {
1237 switch (opt) {
1238 case "-s": {
1239 try {
1240 slotId = Integer.parseInt(getNextArgRequired());
1241 } catch (NumberFormatException e) {
1242 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1243 return -1;
1244 }
1245 break;
1246 }
1247 }
1248 }
1249
1250 try {
1251 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1252 if (VDBG) {
1253 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1254 + ", result=" + result);
1255 }
1256 getOutPrintWriter().println(result);
1257 } catch (RemoteException e) {
1258 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1259 + ", error" + e.getMessage());
1260 errPw.println("Exception: " + e.getMessage());
1261 return -1;
1262 }
1263 return 0;
1264 }
1265
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001266 // ims get-ims-service
1267 private int handleImsGetServiceCommand() {
1268 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001269 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001270 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001271 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001272
1273 String opt;
1274 while ((opt = getNextOption()) != null) {
1275 switch (opt) {
1276 case "-s": {
1277 try {
1278 slotId = Integer.parseInt(getNextArgRequired());
1279 } catch (NumberFormatException e) {
1280 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1281 return -1;
1282 }
1283 break;
1284 }
1285 case "-c": {
1286 isCarrierService = true;
1287 break;
1288 }
1289 case "-d": {
1290 isCarrierService = false;
1291 break;
1292 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001293 case "-f": {
1294 try {
1295 featureType = Integer.parseInt(getNextArg());
1296 } catch (NumberFormatException e) {
1297 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1298 return -1;
1299 }
1300 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1301 || featureType >= ImsFeature.FEATURE_MAX) {
1302 errPw.println("ims get-ims-service -f invalid feature.");
1303 return -1;
1304 }
1305 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001306 }
1307 }
1308 // Mandatory param, either -c or -d
1309 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001310 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001311 return -1;
1312 }
1313
1314 String result;
1315 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001316 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001317 } catch (RemoteException e) {
1318 return -1;
1319 }
1320 if (VDBG) {
1321 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001322 + (isCarrierService ? "-c " : "-d ")
1323 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1324 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001325 }
1326 getOutPrintWriter().println(result);
1327 return 0;
1328 }
1329
1330 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001331 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001332 String opt;
1333 while ((opt = getNextOption()) != null) {
1334 switch (opt) {
1335 case "-s": {
1336 try {
1337 slotId = Integer.parseInt(getNextArgRequired());
1338 } catch (NumberFormatException e) {
1339 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1340 return -1;
1341 }
1342 break;
1343 }
1344 }
1345 }
1346 try {
1347 mInterface.enableIms(slotId);
1348 } catch (RemoteException e) {
1349 return -1;
1350 }
1351 if (VDBG) {
1352 Log.v(LOG_TAG, "ims enable -s " + slotId);
1353 }
1354 return 0;
1355 }
1356
1357 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001358 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001359 String opt;
1360 while ((opt = getNextOption()) != null) {
1361 switch (opt) {
1362 case "-s": {
1363 try {
1364 slotId = Integer.parseInt(getNextArgRequired());
1365 } catch (NumberFormatException e) {
1366 getErrPrintWriter().println(
1367 "ims disable requires an integer as a SLOT_ID.");
1368 return -1;
1369 }
1370 break;
1371 }
1372 }
1373 }
1374 try {
1375 mInterface.disableIms(slotId);
1376 } catch (RemoteException e) {
1377 return -1;
1378 }
1379 if (VDBG) {
1380 Log.v(LOG_TAG, "ims disable -s " + slotId);
1381 }
1382 return 0;
1383 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001384
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001385 private int handleCepChange() {
1386 Log.i(LOG_TAG, "handleCepChange");
1387 String opt = getNextArg();
1388 if (opt == null) {
1389 return -1;
1390 }
1391 boolean isCepEnabled = opt.equals("enable");
1392
1393 try {
1394 mInterface.setCepEnabled(isCepEnabled);
1395 } catch (RemoteException e) {
1396 return -1;
1397 }
1398 return 0;
1399 }
1400
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001401 private int getDefaultSlot() {
1402 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1403 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1404 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1405 // If there is no default, default to slot 0.
1406 slotId = DEFAULT_PHONE_ID;
1407 }
1408 return slotId;
1409 }
sqian2fff4a32018-11-05 14:18:37 -08001410
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001411 // Parse options related to Carrier Config Commands.
1412 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001413 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001414 CcOptionParseResult result = new CcOptionParseResult();
1415 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1416 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001417
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001418 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001419 while ((opt = getNextOption()) != null) {
1420 switch (opt) {
1421 case "-s": {
1422 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001423 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1424 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1425 errPw.println(tag + "No valid subscription found.");
1426 return null;
1427 }
1428
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001429 } catch (IllegalArgumentException e) {
1430 // Missing slot id
1431 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001432 return null;
1433 }
1434 break;
1435 }
1436 case "-p": {
1437 if (allowOptionPersistent) {
1438 result.mPersistent = true;
1439 } else {
1440 errPw.println(tag + "Unexpected option " + opt);
1441 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001442 }
1443 break;
1444 }
1445 default: {
1446 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001447 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001448 }
1449 }
1450 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001451 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001452 }
1453
1454 private int slotStringToSubId(String tag, String slotString) {
1455 int slotId = -1;
1456 try {
1457 slotId = Integer.parseInt(slotString);
1458 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001459 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1460 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1461 }
1462
1463 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001464 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1465 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1466 }
1467
Qiong Liuf25799b2020-09-10 10:13:46 +08001468 Phone phone = PhoneFactory.getPhone(slotId);
1469 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001470 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1471 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1472 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001473 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001474 }
1475
Hall Liud892bec2018-11-30 14:51:45 -08001476 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001477 // adb can run as root or as shell, depending on whether the device is rooted.
1478 return Binder.getCallingUid() == Process.SHELL_UID
1479 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001480 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001481
1482 private int handleCcCommand() {
1483 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1484 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001485 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001486 getErrPrintWriter().println("cc: Permission denied.");
1487 return -1;
1488 }
1489
1490 String arg = getNextArg();
1491 if (arg == null) {
1492 onHelpCc();
1493 return 0;
1494 }
1495
1496 switch (arg) {
1497 case CC_GET_VALUE: {
1498 return handleCcGetValue();
1499 }
1500 case CC_SET_VALUE: {
1501 return handleCcSetValue();
1502 }
1503 case CC_CLEAR_VALUES: {
1504 return handleCcClearValues();
1505 }
1506 default: {
1507 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1508 }
1509 }
1510 return -1;
1511 }
1512
1513 // cc get-value
1514 private int handleCcGetValue() {
1515 PrintWriter errPw = getErrPrintWriter();
1516 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1517 String key = null;
1518
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001519 // Parse all options
1520 CcOptionParseResult options = parseCcOptions(tag, false);
1521 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001522 return -1;
1523 }
1524
1525 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001526 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001527 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001528 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001529 return -1;
1530 }
1531
1532 // Get the key.
1533 key = getNextArg();
1534 if (key != null) {
1535 // A key was provided. Verify if it is a valid key
1536 if (!bundle.containsKey(key)) {
1537 errPw.println(tag + key + " is not a valid key.");
1538 return -1;
1539 }
1540
1541 // Print the carrier config value for key.
1542 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1543 } else {
1544 // No key provided. Show all values.
1545 // Iterate over a sorted list of all carrier config keys and print them.
1546 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1547 for (String k : sortedSet) {
1548 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1549 }
1550 }
1551 return 0;
1552 }
1553
1554 // cc set-value
1555 private int handleCcSetValue() {
1556 PrintWriter errPw = getErrPrintWriter();
1557 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1558
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001559 // Parse all options
1560 CcOptionParseResult options = parseCcOptions(tag, true);
1561 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001562 return -1;
1563 }
1564
1565 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001566 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001567 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001568 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001569 return -1;
1570 }
1571
1572 // Get the key.
1573 String key = getNextArg();
1574 if (key == null || key.equals("")) {
1575 errPw.println(tag + "KEY is missing");
1576 return -1;
1577 }
1578
1579 // Verify if the key is valid
1580 if (!originalValues.containsKey(key)) {
1581 errPw.println(tag + key + " is not a valid key.");
1582 return -1;
1583 }
1584
1585 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1586 ArrayList<String> valueList = new ArrayList<String>();
1587 while (peekNextArg() != null) {
1588 valueList.add(getNextArg());
1589 }
1590
1591 // Find the type of the carrier config value
1592 CcType type = getType(tag, key, originalValues);
1593 if (type == CcType.UNKNOWN) {
1594 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1595 return -1;
1596 }
1597
1598 // Create an override bundle containing the key and value that should be overriden.
1599 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1600 if (overrideBundle == null) {
1601 return -1;
1602 }
1603
1604 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001605 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001606
1607 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001608 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001609 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001610 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001611 return -1;
1612 }
1613
1614 // Print the original and new value.
1615 String originalValueString = ccValueToString(key, type, originalValues);
1616 String newValueString = ccValueToString(key, type, newValues);
1617 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1618 getOutPrintWriter().println("New value: \n" + newValueString);
1619
1620 return 0;
1621 }
1622
1623 // cc clear-values
1624 private int handleCcClearValues() {
1625 PrintWriter errPw = getErrPrintWriter();
1626 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1627
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001628 // Parse all options
1629 CcOptionParseResult options = parseCcOptions(tag, false);
1630 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001631 return -1;
1632 }
1633
1634 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001635 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001636 getOutPrintWriter()
1637 .println("All previously set carrier config override values has been cleared");
1638 return 0;
1639 }
1640
1641 private CcType getType(String tag, String key, PersistableBundle bundle) {
1642 // Find the type by checking the type of the current value stored in the bundle.
1643 Object value = bundle.get(key);
1644
1645 if (CC_TYPE_MAP.containsKey(key)) {
1646 return CC_TYPE_MAP.get(key);
1647 } else if (value != null) {
1648 if (value instanceof Boolean) {
1649 return CcType.BOOLEAN;
1650 } else if (value instanceof Double) {
1651 return CcType.DOUBLE;
1652 } else if (value instanceof double[]) {
1653 return CcType.DOUBLE_ARRAY;
1654 } else if (value instanceof Integer) {
1655 return CcType.INT;
1656 } else if (value instanceof int[]) {
1657 return CcType.INT_ARRAY;
1658 } else if (value instanceof Long) {
1659 return CcType.LONG;
1660 } else if (value instanceof long[]) {
1661 return CcType.LONG_ARRAY;
1662 } else if (value instanceof String) {
1663 return CcType.STRING;
1664 } else if (value instanceof String[]) {
1665 return CcType.STRING_ARRAY;
1666 }
1667 } else {
1668 // Current value was null and can therefore not be used in order to find the type.
1669 // Check the name of the key to infer the type. This check is not needed for primitive
1670 // data types (boolean, double, int and long), since they can not be null.
1671 if (key.endsWith("double_array")) {
1672 return CcType.DOUBLE_ARRAY;
1673 }
1674 if (key.endsWith("int_array")) {
1675 return CcType.INT_ARRAY;
1676 }
1677 if (key.endsWith("long_array")) {
1678 return CcType.LONG_ARRAY;
1679 }
1680 if (key.endsWith("string")) {
1681 return CcType.STRING;
1682 }
1683 if (key.endsWith("string_array") || key.endsWith("strings")) {
1684 return CcType.STRING_ARRAY;
1685 }
1686 }
1687
1688 // Not possible to infer the type by looking at the current value or the key.
1689 PrintWriter errPw = getErrPrintWriter();
1690 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1691 return CcType.UNKNOWN;
1692 }
1693
1694 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1695 String result;
1696 StringBuilder valueString = new StringBuilder();
1697 String typeString = type.toString();
1698 Object value = bundle.get(key);
1699
1700 if (value == null) {
1701 valueString.append("null");
1702 } else {
1703 switch (type) {
1704 case DOUBLE_ARRAY: {
1705 // Format the string representation of the int array as value1 value2......
1706 double[] valueArray = (double[]) value;
1707 for (int i = 0; i < valueArray.length; i++) {
1708 if (i != 0) {
1709 valueString.append(" ");
1710 }
1711 valueString.append(valueArray[i]);
1712 }
1713 break;
1714 }
1715 case INT_ARRAY: {
1716 // Format the string representation of the int array as value1 value2......
1717 int[] valueArray = (int[]) value;
1718 for (int i = 0; i < valueArray.length; i++) {
1719 if (i != 0) {
1720 valueString.append(" ");
1721 }
1722 valueString.append(valueArray[i]);
1723 }
1724 break;
1725 }
1726 case LONG_ARRAY: {
1727 // Format the string representation of the int array as value1 value2......
1728 long[] valueArray = (long[]) value;
1729 for (int i = 0; i < valueArray.length; i++) {
1730 if (i != 0) {
1731 valueString.append(" ");
1732 }
1733 valueString.append(valueArray[i]);
1734 }
1735 break;
1736 }
1737 case STRING: {
1738 valueString.append("\"" + value.toString() + "\"");
1739 break;
1740 }
1741 case STRING_ARRAY: {
1742 // Format the string representation of the string array as "value1" "value2"....
1743 String[] valueArray = (String[]) value;
1744 for (int i = 0; i < valueArray.length; i++) {
1745 if (i != 0) {
1746 valueString.append(" ");
1747 }
1748 if (valueArray[i] != null) {
1749 valueString.append("\"" + valueArray[i] + "\"");
1750 } else {
1751 valueString.append("null");
1752 }
1753 }
1754 break;
1755 }
1756 default: {
1757 valueString.append(value.toString());
1758 }
1759 }
1760 }
1761 return String.format("%-70s %-15s %s", key, typeString, valueString);
1762 }
1763
1764 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1765 ArrayList<String> valueList) {
1766 PrintWriter errPw = getErrPrintWriter();
1767 PersistableBundle bundle = new PersistableBundle();
1768
1769 // First verify that a valid number of values has been provided for the type.
1770 switch (type) {
1771 case BOOLEAN:
1772 case DOUBLE:
1773 case INT:
1774 case LONG: {
1775 if (valueList.size() != 1) {
1776 errPw.println(tag + "Expected 1 value for type " + type
1777 + ". Found: " + valueList.size());
1778 return null;
1779 }
1780 break;
1781 }
1782 case STRING: {
1783 if (valueList.size() > 1) {
1784 errPw.println(tag + "Expected 0 or 1 values for type " + type
1785 + ". Found: " + valueList.size());
1786 return null;
1787 }
1788 break;
1789 }
1790 }
1791
1792 // Parse the value according to type and add it to the Bundle.
1793 switch (type) {
1794 case BOOLEAN: {
1795 if ("true".equalsIgnoreCase(valueList.get(0))) {
1796 bundle.putBoolean(key, true);
1797 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1798 bundle.putBoolean(key, false);
1799 } else {
1800 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1801 return null;
1802 }
1803 break;
1804 }
1805 case DOUBLE: {
1806 try {
1807 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1808 } catch (NumberFormatException nfe) {
1809 // Not a valid double
1810 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1811 return null;
1812 }
1813 break;
1814 }
1815 case DOUBLE_ARRAY: {
1816 double[] valueDoubleArray = null;
1817 if (valueList.size() > 0) {
1818 valueDoubleArray = new double[valueList.size()];
1819 for (int i = 0; i < valueList.size(); i++) {
1820 try {
1821 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1822 } catch (NumberFormatException nfe) {
1823 // Not a valid double
1824 errPw.println(
1825 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1826 return null;
1827 }
1828 }
1829 }
1830 bundle.putDoubleArray(key, valueDoubleArray);
1831 break;
1832 }
1833 case INT: {
1834 try {
1835 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1836 } catch (NumberFormatException nfe) {
1837 // Not a valid integer
1838 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1839 return null;
1840 }
1841 break;
1842 }
1843 case INT_ARRAY: {
1844 int[] valueIntArray = null;
1845 if (valueList.size() > 0) {
1846 valueIntArray = new int[valueList.size()];
1847 for (int i = 0; i < valueList.size(); i++) {
1848 try {
1849 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1850 } catch (NumberFormatException nfe) {
1851 // Not a valid integer
1852 errPw.println(tag
1853 + "Unable to parse " + valueList.get(i) + " as an integer.");
1854 return null;
1855 }
1856 }
1857 }
1858 bundle.putIntArray(key, valueIntArray);
1859 break;
1860 }
1861 case LONG: {
1862 try {
1863 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1864 } catch (NumberFormatException nfe) {
1865 // Not a valid long
1866 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1867 return null;
1868 }
1869 break;
1870 }
1871 case LONG_ARRAY: {
1872 long[] valueLongArray = null;
1873 if (valueList.size() > 0) {
1874 valueLongArray = new long[valueList.size()];
1875 for (int i = 0; i < valueList.size(); i++) {
1876 try {
1877 valueLongArray[i] = Long.parseLong(valueList.get(i));
1878 } catch (NumberFormatException nfe) {
1879 // Not a valid long
1880 errPw.println(
1881 tag + "Unable to parse " + valueList.get(i) + " as a long");
1882 return null;
1883 }
1884 }
1885 }
1886 bundle.putLongArray(key, valueLongArray);
1887 break;
1888 }
1889 case STRING: {
1890 String value = null;
1891 if (valueList.size() > 0) {
1892 value = valueList.get(0);
1893 }
1894 bundle.putString(key, value);
1895 break;
1896 }
1897 case STRING_ARRAY: {
1898 String[] valueStringArray = null;
1899 if (valueList.size() > 0) {
1900 valueStringArray = new String[valueList.size()];
1901 valueList.toArray(valueStringArray);
1902 }
1903 bundle.putStringArray(key, valueStringArray);
1904 break;
1905 }
1906 }
1907 return bundle;
1908 }
Shuo Qian489d9282020-07-09 11:30:03 -07001909
1910 private int handleEndBlockSuppressionCommand() {
1911 if (!checkShellUid()) {
1912 return -1;
1913 }
1914
1915 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1916 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1917 }
1918 return 0;
1919 }
Hui Wang641e81c2020-10-12 12:14:23 -07001920
Michele Berionne54af4632020-12-28 20:23:16 +00001921 private int handleRestartModemCommand() {
1922 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1923 // non user build.
1924 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1925 getErrPrintWriter().println("RestartModem: Permission denied.");
1926 return -1;
1927 }
1928
1929 boolean result = TelephonyManager.getDefault().rebootRadio();
1930 getOutPrintWriter().println(result);
1931
1932 return result ? 0 : -1;
1933 }
1934
Ling Ma4fbab492022-01-25 22:36:16 +00001935 private int handleGetImei() {
1936 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1937 // non user build.
1938 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1939 getErrPrintWriter().println("Device IMEI: Permission denied.");
1940 return -1;
1941 }
1942
1943 final long identity = Binder.clearCallingIdentity();
1944
1945 String imei = null;
1946 String arg = getNextArg();
1947 if (arg != null) {
1948 try {
1949 int specifiedSlotIndex = Integer.parseInt(arg);
1950 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
1951 } catch (NumberFormatException exception) {
1952 PrintWriter errPw = getErrPrintWriter();
1953 errPw.println("-s requires an integer as slot index.");
1954 return -1;
1955 }
1956
1957 } else {
1958 imei = TelephonyManager.from(mContext).getImei();
1959 }
1960 getOutPrintWriter().println("Device IMEI: " + imei);
1961
1962 Binder.restoreCallingIdentity(identity);
1963 return 0;
1964 }
1965
Michele Berionne5e411512020-11-13 02:36:59 +00001966 private int handleUnattendedReboot() {
1967 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1968 // non user build.
1969 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1970 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1971 return -1;
1972 }
1973
1974 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1975 getOutPrintWriter().println("result: " + result);
1976
1977 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1978 }
1979
Hui Wang641e81c2020-10-12 12:14:23 -07001980 private int handleGbaCommand() {
1981 String arg = getNextArg();
1982 if (arg == null) {
1983 onHelpGba();
1984 return 0;
1985 }
1986
1987 switch (arg) {
1988 case GBA_SET_SERVICE: {
1989 return handleGbaSetServiceCommand();
1990 }
1991 case GBA_GET_SERVICE: {
1992 return handleGbaGetServiceCommand();
1993 }
1994 case GBA_SET_RELEASE_TIME: {
1995 return handleGbaSetReleaseCommand();
1996 }
1997 case GBA_GET_RELEASE_TIME: {
1998 return handleGbaGetReleaseCommand();
1999 }
2000 }
2001
2002 return -1;
2003 }
2004
2005 private int getSubId(String cmd) {
2006 int slotId = getDefaultSlot();
2007 String opt = getNextOption();
2008 if (opt != null && opt.equals("-s")) {
2009 try {
2010 slotId = Integer.parseInt(getNextArgRequired());
2011 } catch (NumberFormatException e) {
2012 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2013 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2014 }
2015 }
2016 int[] subIds = SubscriptionManager.getSubId(slotId);
2017 return subIds[0];
2018 }
2019
2020 private int handleGbaSetServiceCommand() {
2021 int subId = getSubId("gba set-service");
2022 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2023 return -1;
2024 }
2025
2026 String packageName = getNextArg();
2027 try {
2028 if (packageName == null) {
2029 packageName = "";
2030 }
2031 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2032 if (VDBG) {
2033 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2034 + packageName + ", result=" + result);
2035 }
2036 getOutPrintWriter().println(result);
2037 } catch (RemoteException e) {
2038 Log.w(LOG_TAG, "gba set-service " + subId + " "
2039 + packageName + ", error" + e.getMessage());
2040 getErrPrintWriter().println("Exception: " + e.getMessage());
2041 return -1;
2042 }
2043 return 0;
2044 }
2045
2046 private int handleGbaGetServiceCommand() {
2047 String result;
2048
2049 int subId = getSubId("gba get-service");
2050 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2051 return -1;
2052 }
2053
2054 try {
2055 result = mInterface.getBoundGbaService(subId);
2056 } catch (RemoteException e) {
2057 return -1;
2058 }
2059 if (VDBG) {
2060 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2061 }
2062 getOutPrintWriter().println(result);
2063 return 0;
2064 }
2065
2066 private int handleGbaSetReleaseCommand() {
2067 //the release time value could be -1
2068 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2069 : SubscriptionManager.getDefaultSubscriptionId();
2070 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2071 return -1;
2072 }
2073
2074 String intervalStr = getNextArg();
2075 if (intervalStr == null) {
2076 return -1;
2077 }
2078
2079 try {
2080 int interval = Integer.parseInt(intervalStr);
2081 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2082 if (VDBG) {
2083 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2084 + intervalStr + ", result=" + result);
2085 }
2086 getOutPrintWriter().println(result);
2087 } catch (NumberFormatException | RemoteException e) {
2088 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2089 + intervalStr + ", error" + e.getMessage());
2090 getErrPrintWriter().println("Exception: " + e.getMessage());
2091 return -1;
2092 }
2093 return 0;
2094 }
2095
2096 private int handleGbaGetReleaseCommand() {
2097 int subId = getSubId("gba get-release");
2098 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2099 return -1;
2100 }
2101
2102 int result = 0;
2103 try {
2104 result = mInterface.getGbaReleaseTime(subId);
2105 } catch (RemoteException e) {
2106 return -1;
2107 }
2108 if (VDBG) {
2109 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2110 }
2111 getOutPrintWriter().println(result);
2112 return 0;
2113 }
Hui Wang761a6682020-10-31 05:12:53 +00002114
2115 private int handleSingleRegistrationConfigCommand() {
2116 String arg = getNextArg();
2117 if (arg == null) {
2118 onHelpSrc();
2119 return 0;
2120 }
2121
2122 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002123 case SRC_SET_TEST_ENABLED: {
2124 return handleSrcSetTestEnabledCommand();
2125 }
2126 case SRC_GET_TEST_ENABLED: {
2127 return handleSrcGetTestEnabledCommand();
2128 }
Hui Wang761a6682020-10-31 05:12:53 +00002129 case SRC_SET_DEVICE_ENABLED: {
2130 return handleSrcSetDeviceEnabledCommand();
2131 }
2132 case SRC_GET_DEVICE_ENABLED: {
2133 return handleSrcGetDeviceEnabledCommand();
2134 }
2135 case SRC_SET_CARRIER_ENABLED: {
2136 return handleSrcSetCarrierEnabledCommand();
2137 }
2138 case SRC_GET_CARRIER_ENABLED: {
2139 return handleSrcGetCarrierEnabledCommand();
2140 }
Hui Wangb647abe2021-02-26 09:33:38 -08002141 case SRC_SET_FEATURE_ENABLED: {
2142 return handleSrcSetFeatureValidationCommand();
2143 }
2144 case SRC_GET_FEATURE_ENABLED: {
2145 return handleSrcGetFeatureValidationCommand();
2146 }
Hui Wang761a6682020-10-31 05:12:53 +00002147 }
2148
2149 return -1;
2150 }
2151
James.cf Linbcdf8b32021-01-14 16:44:13 +08002152 private int handleRcsUceCommand() {
2153 String arg = getNextArg();
2154 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002155 onHelpUce();
2156 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002157 }
2158
2159 switch (arg) {
2160 case UCE_REMOVE_EAB_CONTACT:
2161 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002162 case UCE_GET_EAB_CONTACT:
2163 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002164 case UCE_GET_EAB_CAPABILITY:
2165 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002166 case UCE_GET_DEVICE_ENABLED:
2167 return handleUceGetDeviceEnabledCommand();
2168 case UCE_SET_DEVICE_ENABLED:
2169 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002170 case UCE_OVERRIDE_PUBLISH_CAPS:
2171 return handleUceOverridePublishCaps();
2172 case UCE_GET_LAST_PIDF_XML:
2173 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002174 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2175 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002176 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2177 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002178 }
2179 return -1;
2180 }
2181
2182 private int handleRemovingEabContactCommand() {
2183 int subId = getSubId("uce remove-eab-contact");
2184 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2185 return -1;
2186 }
2187
2188 String phoneNumber = getNextArgRequired();
2189 if (TextUtils.isEmpty(phoneNumber)) {
2190 return -1;
2191 }
2192 int result = 0;
2193 try {
2194 result = mInterface.removeContactFromEab(subId, phoneNumber);
2195 } catch (RemoteException e) {
2196 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2197 getErrPrintWriter().println("Exception: " + e.getMessage());
2198 return -1;
2199 }
2200
2201 if (VDBG) {
2202 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2203 }
calvinpan293ea1b2021-02-04 17:52:13 +08002204 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002205 }
2206
calvinpane4a8a1d2021-01-25 13:51:18 +08002207 private int handleGettingEabContactCommand() {
2208 String phoneNumber = getNextArgRequired();
2209 if (TextUtils.isEmpty(phoneNumber)) {
2210 return -1;
2211 }
2212 String result = "";
2213 try {
2214 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002215 } catch (RemoteException e) {
2216 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2217 getErrPrintWriter().println("Exception: " + e.getMessage());
2218 return -1;
2219 }
2220
2221 if (VDBG) {
2222 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2223 }
calvinpan293ea1b2021-02-04 17:52:13 +08002224 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002225 return 0;
2226 }
2227
Calvin Pana1434322021-07-01 19:27:01 +08002228 private int handleGettingEabCapabilityCommand() {
2229 String phoneNumber = getNextArgRequired();
2230 if (TextUtils.isEmpty(phoneNumber)) {
2231 return -1;
2232 }
2233 String result = "";
2234 try {
2235 result = mInterface.getCapabilityFromEab(phoneNumber);
2236 } catch (RemoteException e) {
2237 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2238 getErrPrintWriter().println("Exception: " + e.getMessage());
2239 return -1;
2240 }
2241
2242 if (VDBG) {
2243 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2244 }
2245 getOutPrintWriter().println(result);
2246 return 0;
2247 }
2248
James.cf Lin4b784aa2021-01-31 03:25:15 +08002249 private int handleUceGetDeviceEnabledCommand() {
2250 boolean result = false;
2251 try {
2252 result = mInterface.getDeviceUceEnabled();
2253 } catch (RemoteException e) {
2254 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2255 return -1;
2256 }
2257 if (VDBG) {
2258 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2259 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002260 getOutPrintWriter().println(result);
2261 return 0;
2262 }
2263
James.cf Lin4b784aa2021-01-31 03:25:15 +08002264 private int handleUceSetDeviceEnabledCommand() {
2265 String enabledStr = getNextArg();
2266 if (TextUtils.isEmpty(enabledStr)) {
2267 return -1;
2268 }
2269
2270 try {
2271 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2272 mInterface.setDeviceUceEnabled(isEnabled);
2273 if (VDBG) {
2274 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2275 }
2276 } catch (NumberFormatException | RemoteException e) {
2277 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2278 getErrPrintWriter().println("Exception: " + e.getMessage());
2279 return -1;
2280 }
2281 return 0;
2282 }
2283
James.cf Line8713a42021-04-29 16:04:26 +08002284 private int handleUceRemoveRequestDisallowedStatus() {
2285 int subId = getSubId("uce remove-request-disallowed-status");
2286 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2287 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2288 return -1;
2289 }
2290 boolean result;
2291 try {
2292 result = mInterface.removeUceRequestDisallowedStatus(subId);
2293 } catch (RemoteException e) {
2294 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2295 return -1;
2296 }
2297 if (VDBG) {
2298 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2299 }
2300 getOutPrintWriter().println(result);
2301 return 0;
2302 }
2303
James.cf Lin0fc71b02021-05-25 01:37:38 +08002304 private int handleUceSetCapRequestTimeout() {
2305 int subId = getSubId("uce set-capabilities-request-timeout");
2306 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2307 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2308 return -1;
2309 }
2310 long timeoutAfterMs = Long.valueOf(getNextArg());
2311 boolean result;
2312 try {
2313 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2314 } catch (RemoteException e) {
2315 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2316 return -1;
2317 }
2318 if (VDBG) {
2319 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2320 }
2321 getOutPrintWriter().println(result);
2322 return 0;
2323 }
2324
Hui Wangbaaee6a2021-02-19 20:45:36 -08002325 private int handleSrcSetTestEnabledCommand() {
2326 String enabledStr = getNextArg();
2327 if (enabledStr == null) {
2328 return -1;
2329 }
2330
2331 try {
2332 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2333 if (VDBG) {
2334 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2335 }
2336 getOutPrintWriter().println("Done");
2337 } catch (NumberFormatException | RemoteException e) {
2338 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2339 getErrPrintWriter().println("Exception: " + e.getMessage());
2340 return -1;
2341 }
2342 return 0;
2343 }
2344
2345 private int handleSrcGetTestEnabledCommand() {
2346 boolean result = false;
2347 try {
2348 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2349 } catch (RemoteException e) {
2350 return -1;
2351 }
2352 if (VDBG) {
2353 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2354 }
2355 getOutPrintWriter().println(result);
2356 return 0;
2357 }
2358
Brad Ebinger14d467f2021-02-12 06:18:28 +00002359 private int handleUceOverridePublishCaps() {
2360 int subId = getSubId("uce override-published-caps");
2361 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2362 return -1;
2363 }
2364 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2365 String operation = getNextArgRequired();
2366 String caps = getNextArg();
2367 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2368 && !"list".equals(operation)) {
2369 getErrPrintWriter().println("Invalid operation: " + operation);
2370 return -1;
2371 }
2372
2373 // add/remove requires capabilities to be specified.
2374 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2375 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2376 + "specified");
2377 return -1;
2378 }
2379
2380 ArraySet<String> capSet = new ArraySet<>();
2381 if (!TextUtils.isEmpty(caps)) {
2382 String[] capArray = caps.split(":");
2383 for (String cap : capArray) {
2384 // Allow unknown tags to be passed in as well.
2385 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2386 }
2387 }
2388
2389 RcsContactUceCapability result = null;
2390 try {
2391 switch (operation) {
2392 case "add":
2393 result = mInterface.addUceRegistrationOverrideShell(subId,
2394 new ArrayList<>(capSet));
2395 break;
2396 case "remove":
2397 result = mInterface.removeUceRegistrationOverrideShell(subId,
2398 new ArrayList<>(capSet));
2399 break;
2400 case "clear":
2401 result = mInterface.clearUceRegistrationOverrideShell(subId);
2402 break;
2403 case "list":
2404 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2405 break;
2406 }
2407 } catch (RemoteException e) {
2408 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2409 getErrPrintWriter().println("Exception: " + e.getMessage());
2410 return -1;
2411 } catch (ServiceSpecificException sse) {
2412 // Reconstruct ImsException
2413 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2414 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2415 getErrPrintWriter().println("Exception: " + imsException);
2416 return -1;
2417 }
2418 if (result == null) {
2419 getErrPrintWriter().println("Service not available");
2420 return -1;
2421 }
2422 getOutPrintWriter().println(result);
2423 return 0;
2424 }
2425
2426 private int handleUceGetPidfXml() {
2427 int subId = getSubId("uce get-last-publish-pidf");
2428 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2429 return -1;
2430 }
2431
2432 String result;
2433 try {
2434 result = mInterface.getLastUcePidfXmlShell(subId);
2435 } catch (RemoteException e) {
2436 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2437 getErrPrintWriter().println("Exception: " + e.getMessage());
2438 return -1;
2439 } catch (ServiceSpecificException sse) {
2440 // Reconstruct ImsException
2441 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2442 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2443 getErrPrintWriter().println("Exception: " + imsException);
2444 return -1;
2445 }
2446 if (result == null) {
2447 getErrPrintWriter().println("Service not available");
2448 return -1;
2449 }
2450 getOutPrintWriter().println(result);
2451 return 0;
2452 }
2453
Hui Wang761a6682020-10-31 05:12:53 +00002454 private int handleSrcSetDeviceEnabledCommand() {
2455 String enabledStr = getNextArg();
2456 if (enabledStr == null) {
2457 return -1;
2458 }
2459
2460 try {
2461 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2462 if (VDBG) {
2463 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2464 }
2465 getOutPrintWriter().println("Done");
2466 } catch (NumberFormatException | RemoteException e) {
2467 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2468 getErrPrintWriter().println("Exception: " + e.getMessage());
2469 return -1;
2470 }
2471 return 0;
2472 }
2473
2474 private int handleSrcGetDeviceEnabledCommand() {
2475 boolean result = false;
2476 try {
2477 result = mInterface.getDeviceSingleRegistrationEnabled();
2478 } catch (RemoteException e) {
2479 return -1;
2480 }
2481 if (VDBG) {
2482 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2483 }
2484 getOutPrintWriter().println(result);
2485 return 0;
2486 }
2487
2488 private int handleSrcSetCarrierEnabledCommand() {
2489 //the release time value could be -1
2490 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2491 : SubscriptionManager.getDefaultSubscriptionId();
2492 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2493 return -1;
2494 }
2495
2496 String enabledStr = getNextArg();
2497 if (enabledStr == null) {
2498 return -1;
2499 }
2500
2501 try {
2502 boolean result =
2503 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2504 if (VDBG) {
2505 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2506 + enabledStr + ", result=" + result);
2507 }
2508 getOutPrintWriter().println(result);
2509 } catch (NumberFormatException | RemoteException e) {
2510 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2511 + enabledStr + ", error" + e.getMessage());
2512 getErrPrintWriter().println("Exception: " + e.getMessage());
2513 return -1;
2514 }
2515 return 0;
2516 }
2517
2518 private int handleSrcGetCarrierEnabledCommand() {
2519 int subId = getSubId("src get-carrier-enabled");
2520 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2521 return -1;
2522 }
2523
2524 boolean result = false;
2525 try {
2526 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2527 } catch (RemoteException e) {
2528 return -1;
2529 }
2530 if (VDBG) {
2531 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2532 }
2533 getOutPrintWriter().println(result);
2534 return 0;
2535 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002536
Hui Wangb647abe2021-02-26 09:33:38 -08002537 private int handleSrcSetFeatureValidationCommand() {
2538 //the release time value could be -1
2539 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2540 : SubscriptionManager.getDefaultSubscriptionId();
2541 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2542 return -1;
2543 }
2544
2545 String enabledStr = getNextArg();
2546 if (enabledStr == null) {
2547 return -1;
2548 }
2549
2550 try {
2551 boolean result =
2552 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2553 if (VDBG) {
2554 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2555 + enabledStr + ", result=" + result);
2556 }
2557 getOutPrintWriter().println(result);
2558 } catch (NumberFormatException | RemoteException e) {
2559 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2560 + enabledStr + ", error" + e.getMessage());
2561 getErrPrintWriter().println("Exception: " + e.getMessage());
2562 return -1;
2563 }
2564 return 0;
2565 }
2566
2567 private int handleSrcGetFeatureValidationCommand() {
2568 int subId = getSubId("src get-feature-validation");
2569 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2570 return -1;
2571 }
2572
2573 Boolean result = false;
2574 try {
2575 result = mInterface.getImsFeatureValidationOverride(subId);
2576 } catch (RemoteException e) {
2577 return -1;
2578 }
2579 if (VDBG) {
2580 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2581 }
2582 getOutPrintWriter().println(result);
2583 return 0;
2584 }
2585
2586
Hall Liuaa4211e2021-01-20 15:43:39 -08002587 private void onHelpCallComposer() {
2588 PrintWriter pw = getOutPrintWriter();
2589 pw.println("Call composer commands");
2590 pw.println(" callcomposer test-mode enable|disable|query");
2591 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2592 pw.println(" upload/download from carrier servers is disabled, and operations are");
2593 pw.println(" performed using emulated local files instead.");
2594 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2595 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2596 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002597 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2598 pw.println(" Enables or disables the user setting for call composer, as set by");
2599 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002600 }
2601
2602 private int handleCallComposerCommand() {
2603 String arg = getNextArg();
2604 if (arg == null) {
2605 onHelpCallComposer();
2606 return 0;
2607 }
2608
2609 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2610 "MODIFY_PHONE_STATE required for call composer shell cmds");
2611 switch (arg) {
2612 case CALL_COMPOSER_TEST_MODE: {
2613 String enabledStr = getNextArg();
2614 if (ENABLE.equals(enabledStr)) {
2615 CallComposerPictureManager.sTestMode = true;
2616 } else if (DISABLE.equals(enabledStr)) {
2617 CallComposerPictureManager.sTestMode = false;
2618 } else if (QUERY.equals(enabledStr)) {
2619 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2620 } else {
2621 onHelpCallComposer();
2622 return 1;
2623 }
2624 break;
2625 }
2626 case CALL_COMPOSER_SIMULATE_CALL: {
2627 int subscriptionId = Integer.valueOf(getNextArg());
2628 String uuidString = getNextArg();
2629 UUID uuid = UUID.fromString(uuidString);
2630 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2631 Binder.withCleanCallingIdentity(() -> {
2632 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2633 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2634 });
2635 try {
2636 Uri uri = storageUriFuture.get();
2637 getOutPrintWriter().println(String.valueOf(uri));
2638 } catch (Exception e) {
2639 throw new RuntimeException(e);
2640 }
2641 break;
2642 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002643 case CALL_COMPOSER_USER_SETTING: {
2644 try {
2645 int subscriptionId = Integer.valueOf(getNextArg());
2646 String enabledStr = getNextArg();
2647 if (ENABLE.equals(enabledStr)) {
2648 mInterface.setCallComposerStatus(subscriptionId,
2649 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2650 } else if (DISABLE.equals(enabledStr)) {
2651 mInterface.setCallComposerStatus(subscriptionId,
2652 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2653 } else if (QUERY.equals(enabledStr)) {
2654 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2655 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2656 } else {
2657 onHelpCallComposer();
2658 return 1;
2659 }
2660 } catch (RemoteException e) {
2661 e.printStackTrace(getOutPrintWriter());
2662 return 1;
2663 }
2664 break;
2665 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002666 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002667 return 0;
2668 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002669
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002670 private int handleHasCarrierPrivilegesCommand() {
2671 String packageName = getNextArgRequired();
2672
2673 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002674 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002675 try {
2676 hasCarrierPrivileges =
2677 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2678 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2679 } catch (RemoteException e) {
2680 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2681 getErrPrintWriter().println("Exception: " + e.getMessage());
2682 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002683 } finally {
2684 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002685 }
2686
2687 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002688 return 0;
2689 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002690
2691 private int handleAllowedNetworkTypesCommand(String command) {
2692 if (!checkShellUid()) {
2693 return -1;
2694 }
2695
2696 PrintWriter errPw = getErrPrintWriter();
2697 String tag = command + ": ";
2698 String opt;
2699 int subId = -1;
2700 Log.v(LOG_TAG, command + " start");
2701
2702 while ((opt = getNextOption()) != null) {
2703 if (opt.equals("-s")) {
2704 try {
2705 subId = slotStringToSubId(tag, getNextArgRequired());
2706 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2707 errPw.println(tag + "No valid subscription found.");
2708 return -1;
2709 }
2710 } catch (IllegalArgumentException e) {
2711 // Missing slot id
2712 errPw.println(tag + "SLOT_ID expected after -s.");
2713 return -1;
2714 }
2715 } else {
2716 errPw.println(tag + "Unknown option " + opt);
2717 return -1;
2718 }
2719 }
2720
2721 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2722 return handleGetAllowedNetworkTypesCommand(subId);
2723 }
2724 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2725 return handleSetAllowedNetworkTypesCommand(subId);
2726 }
2727 return -1;
2728 }
2729
2730 private int handleGetAllowedNetworkTypesCommand(int subId) {
2731 PrintWriter errPw = getErrPrintWriter();
2732
2733 long result = -1;
2734 try {
2735 if (mInterface != null) {
2736 result = mInterface.getAllowedNetworkTypesForReason(subId,
2737 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2738 } else {
2739 throw new IllegalStateException("telephony service is null.");
2740 }
2741 } catch (RemoteException e) {
2742 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2743 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2744 return -1;
2745 }
2746
2747 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2748 return 0;
2749 }
2750
2751 private int handleSetAllowedNetworkTypesCommand(int subId) {
2752 PrintWriter errPw = getErrPrintWriter();
2753
2754 String bitmaskString = getNextArg();
2755 if (TextUtils.isEmpty(bitmaskString)) {
2756 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2757 return -1;
2758 }
2759 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2760 if (allowedNetworkTypes < 0) {
2761 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2762 return -1;
2763 }
2764 boolean result = false;
2765 try {
2766 if (mInterface != null) {
2767 result = mInterface.setAllowedNetworkTypesForReason(subId,
2768 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2769 } else {
2770 throw new IllegalStateException("telephony service is null.");
2771 }
2772 } catch (RemoteException e) {
2773 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2774 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2775 return -1;
2776 }
2777
2778 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2779 if (result) {
2780 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2781 }
2782 getOutPrintWriter().println(resultMessage);
2783 return 0;
2784 }
2785
2786 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2787 if (TextUtils.isEmpty(bitmaskString)) {
2788 return -1;
2789 }
2790 if (VDBG) {
2791 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2792 + ", length: " + bitmaskString.length());
2793 }
2794 try {
2795 return Long.parseLong(bitmaskString, 2);
2796 } catch (NumberFormatException e) {
2797 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2798 return -1;
2799 }
2800 }
Jack Yu4c0a5502021-12-03 23:58:26 -08002801
2802 private int handleGetDataMode() {
2803 if (!checkShellUid()) {
2804 return -1;
2805 }
2806
2807 boolean newDataStackEnabled = false;
2808 try {
2809 newDataStackEnabled = mInterface.isUsingNewDataStack();
2810 } catch (RemoteException e) {
2811 getOutPrintWriter().println("Something went wrong. " + e);
2812 return -1;
2813 }
2814
Jack Yu2f509862022-01-25 10:13:40 -08002815 getOutPrintWriter().println("Telephony is running with the "
2816 + (newDataStackEnabled ? "new" : "old") + " data stack.");
Jack Yu4c0a5502021-12-03 23:58:26 -08002817
2818 boolean configEnabled = Boolean.parseBoolean(DeviceConfig.getProperty(
Jack Yu31b842d2022-01-13 22:13:54 -08002819 DeviceConfig.NAMESPACE_TELEPHONY, "enable_new_data_stack"));
Jack Yu4c0a5502021-12-03 23:58:26 -08002820 if (configEnabled != newDataStackEnabled) {
Jack Yu2f509862022-01-25 10:13:40 -08002821 getOutPrintWriter().println("The new data config has been "
2822 + (configEnabled ? "enabled" : "disabled")
2823 + ". It will be effective after reboot.");
Jack Yu4c0a5502021-12-03 23:58:26 -08002824 }
2825 return 0;
2826 }
jimsun3b9ccac2021-10-26 15:01:23 +08002827
2828 private int handleRadioSetModemServiceCommand() {
2829 PrintWriter errPw = getErrPrintWriter();
2830 String serviceName = null;
2831
2832 String opt;
2833 while ((opt = getNextOption()) != null) {
2834 switch (opt) {
2835 case "-s": {
2836 serviceName = getNextArgRequired();
2837 break;
2838 }
2839 }
2840 }
2841
2842 try {
2843 boolean result = mInterface.setModemService(serviceName);
2844 if (VDBG) {
2845 Log.v(LOG_TAG,
2846 "RadioSetModemService " + serviceName + ", result = " + result);
2847 }
2848 getOutPrintWriter().println(result);
2849 } catch (RemoteException e) {
2850 Log.w(LOG_TAG,
2851 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2852 errPw.println("Exception: " + e.getMessage());
2853 return -1;
2854 }
2855 return 0;
2856 }
2857
2858 private int handleRadioGetModemServiceCommand() {
2859 PrintWriter errPw = getErrPrintWriter();
2860 String result;
2861
2862 try {
2863 result = mInterface.getModemService();
2864 getOutPrintWriter().println(result);
2865 } catch (RemoteException e) {
2866 errPw.println("Exception: " + e.getMessage());
2867 return -1;
2868 }
2869 if (VDBG) {
2870 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2871 }
2872 return 0;
2873 }
2874
2875 private int handleRadioCommand() {
2876 String arg = getNextArg();
2877 if (arg == null) {
2878 onHelpRadio();
2879 return 0;
2880 }
2881
2882 switch (arg) {
2883 case RADIO_SET_MODEM_SERVICE:
2884 return handleRadioSetModemServiceCommand();
2885
2886 case RADIO_GET_MODEM_SERVICE:
2887 return handleRadioGetModemServiceCommand();
2888 }
2889
2890 return -1;
2891 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002892}