blob: 56854cf34d622a06a762b84012b2ef3a63312ff6 [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";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700175 // Take advantage of existing methods that already contain permissions checks when possible.
176 private final ITelephony mInterface;
177
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100178 private SubscriptionManager mSubscriptionManager;
179 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700180 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700181 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100182
183 private enum CcType {
184 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
185 STRING_ARRAY, UNKNOWN
186 }
187
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100188 private class CcOptionParseResult {
189 public int mSubId;
190 public boolean mPersistent;
191 }
192
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100193 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
194 // keys by looking at the end of the string which usually tells the type.
195 // For instance: "xxxx_string", "xxxx_string_array", etc.
196 // The carrier config keys in this map does not follow this convention. It is therefore not
197 // possible to infer the type for these keys by looking at the string.
198 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
199 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
200 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
206 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
207 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
208 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
209 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
210 CcType.STRING);
211 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
212 CcType.STRING_ARRAY);
213 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
214 CcType.STRING_ARRAY);
215 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
216 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
217 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
219 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
220 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
221 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
222 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
223 }
224 };
225
Brad Ebinger14d467f2021-02-12 06:18:28 +0000226 /**
227 * Map from a shorthand string to the feature tags required in registration required in order
228 * for the RCS feature to be considered "capable".
229 */
230 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
231 static {
232 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
233 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
234 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
235 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
236 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
237 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
238 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
239 FeatureTags.FEATURE_TAG_VIDEO)));
240 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
241 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
242 map.put("call_comp",
243 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
244 map.put("call_comp_mmtel",
245 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
246 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
247 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
248 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
249 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
250 // version
251 map.put("chatbot", new ArraySet<>(Arrays.asList(
252 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
253 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
254 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
255 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
256 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
257 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
258 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
259 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
260 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
261 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
262 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
263 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
264 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
265 }
266
267
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100268 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700269 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100270 mCarrierConfigManager =
271 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
272 mSubscriptionManager = (SubscriptionManager)
273 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700274 mTelephonyRegistryManager = (TelephonyRegistryManager)
275 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700276 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700277 }
278
279 @Override
280 public int onCommand(String cmd) {
281 if (cmd == null) {
282 return handleDefaultCommands(null);
283 }
284
285 switch (cmd) {
286 case IMS_SUBCOMMAND: {
287 return handleImsCommand();
288 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800289 case RCS_UCE_COMMAND:
290 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800291 case NUMBER_VERIFICATION_SUBCOMMAND:
292 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800293 case EMERGENCY_CALLBACK_MODE:
294 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800295 case EMERGENCY_NUMBER_TEST_MODE:
296 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100297 case CARRIER_CONFIG_SUBCOMMAND: {
298 return handleCcCommand();
299 }
Shuo Qianf5125122019-12-16 17:03:07 -0800300 case DATA_TEST_MODE:
301 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700302 case END_BLOCK_SUPPRESSION:
303 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700304 case GBA_SUBCOMMAND:
305 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800306 case D2D_SUBCOMMAND:
307 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700308 case BARRING_SUBCOMMAND:
309 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000310 case SINGLE_REGISTATION_CONFIG:
311 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000312 case RESTART_MODEM:
313 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800314 case CALL_COMPOSER_SUBCOMMAND:
315 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000316 case UNATTENDED_REBOOT:
317 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800318 case HAS_CARRIER_PRIVILEGES_COMMAND:
319 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800320 case THERMAL_MITIGATION_COMMAND:
321 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700322 case DISABLE_PHYSICAL_SUBSCRIPTION:
323 return handleEnablePhysicalSubscription(false);
324 case ENABLE_PHYSICAL_SUBSCRIPTION:
325 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800326 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
327 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
328 return handleAllowedNetworkTypesCommand(cmd);
Jack Yu4c0a5502021-12-03 23:58:26 -0800329 case GET_DATA_MODE:
330 return handleGetDataMode();
jimsun3b9ccac2021-10-26 15:01:23 +0800331 case RADIO_SUBCOMMAND:
332 return handleRadioCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700333 default: {
334 return handleDefaultCommands(cmd);
335 }
336 }
337 }
338
339 @Override
340 public void onHelp() {
341 PrintWriter pw = getOutPrintWriter();
342 pw.println("Telephony Commands:");
343 pw.println(" help");
344 pw.println(" Print this help text.");
345 pw.println(" ims");
346 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800347 pw.println(" uce");
348 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800349 pw.println(" emergency-number-test-mode");
350 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700351 pw.println(" end-block-suppression");
352 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800353 pw.println(" data");
354 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100355 pw.println(" cc");
356 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700357 pw.println(" gba");
358 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000359 pw.println(" src");
360 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000361 pw.println(" restart-modem");
362 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000363 pw.println(" unattended-reboot");
364 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800365 pw.println(" has-carrier-privileges [package]");
366 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800367 pw.println(" get-allowed-network-types-for-users");
368 pw.println(" Get the Allowed Network Types.");
369 pw.println(" set-allowed-network-types-for-users");
370 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800371 pw.println(" radio");
372 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700373 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800374 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800375 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700376 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800377 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100378 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700379 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000380 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800381 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700382 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800383 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800384 onHelpRadio();
Tyler Gunn92479152021-01-20 16:30:10 -0800385 }
386
387 private void onHelpD2D() {
388 PrintWriter pw = getOutPrintWriter();
389 pw.println("D2D Comms Commands:");
390 pw.println(" d2d send TYPE VALUE");
391 pw.println(" Sends a D2D message of specified type and value.");
392 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
393 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
394 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
395 MESSAGE_CALL_AUDIO_CODEC));
396 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
397 + Communicator.messageToString(
398 MESSAGE_DEVICE_BATTERY_STATE));
399 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
400 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800401 pw.println(" d2d transport TYPE");
402 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
403 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700404 pw.println(" d2d set-device-support true/default");
405 pw.println(" true - forces device support to be enabled for D2D.");
406 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
407 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700408 }
409
Nazanin014f41e2021-05-06 17:26:31 -0700410 private void onHelpBarring() {
411 PrintWriter pw = getOutPrintWriter();
412 pw.println("Barring Commands:");
413 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
414 + " -t CONDITIONAL_BARRING_TIME_SECS");
415 pw.println(" Notifies of a barring info change for the specified slot id.");
416 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
417 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
418 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
419 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
420 }
421
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700422 private void onHelpIms() {
423 PrintWriter pw = getOutPrintWriter();
424 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800425 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700426 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
427 pw.println(" ImsService. Options are:");
428 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
429 pw.println(" is specified, it will choose the default voice SIM slot.");
430 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
431 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800432 pw.println(" -f: Set the feature that this override if for, if no option is");
433 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700434 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
435 pw.println(" Gets the package name of the currently defined ImsService.");
436 pw.println(" Options are:");
437 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
438 pw.println(" is specified, it will choose the default voice SIM slot.");
439 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000440 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800441 pw.println(" -f: The feature type that the query will be requested for. If none is");
442 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800443 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
444 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
445 pw.println(" configuration overrides. Options are:");
446 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
447 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700448 pw.println(" ims enable [-s SLOT_ID]");
449 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
450 pw.println(" if none is specified.");
451 pw.println(" ims disable [-s SLOT_ID]");
452 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
453 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700454 pw.println(" ims conference-event-package [enable/disable]");
455 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700456 }
457
James.cf Linbcdf8b32021-01-14 16:44:13 +0800458 private void onHelpUce() {
459 PrintWriter pw = getOutPrintWriter();
460 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800461 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
462 pw.println(" Get the EAB contacts from the EAB database.");
463 pw.println(" Options are:");
464 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
465 pw.println(" Expected output format :");
466 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800467 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
468 pw.println(" Remove the EAB contacts from the EAB database.");
469 pw.println(" Options are:");
470 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
471 pw.println(" is specified, it will choose the default voice SIM slot.");
472 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800473 pw.println(" uce get-device-enabled");
474 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
475 pw.println(" uce set-device-enabled true|false");
476 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
477 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000478 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
479 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
480 pw.println(" Options are:");
481 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
482 pw.println(" is specified, it will choose the default voice SIM slot.");
483 pw.println(" add [CAPABILITY]: add a new capability");
484 pw.println(" remove [CAPABILITY]: remove a capability");
485 pw.println(" clear: clear all capability overrides");
486 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
487 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
488 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
489 pw.println(" chatbot_sa, chatbot_role] as well as full length");
490 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
491 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
492 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
493 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800494 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
495 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800496 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
497 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800498 }
499
Hall Liud892bec2018-11-30 14:51:45 -0800500 private void onHelpNumberVerification() {
501 PrintWriter pw = getOutPrintWriter();
502 pw.println("Number verification commands");
503 pw.println(" numverify override-package PACKAGE_NAME;");
504 pw.println(" Set the authorized package for number verification.");
505 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800506 pw.println(" numverify fake-call NUMBER;");
507 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
508 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800509 }
510
Jack Nudelman644b91a2021-03-12 14:09:48 -0800511 private void onHelpThermalMitigation() {
512 PrintWriter pw = getOutPrintWriter();
513 pw.println("Thermal mitigation commands");
514 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
515 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
516 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
517 pw.println(" Remove the package from one of the authorized packages for thermal "
518 + "mitigation.");
519 }
520
Jordan Liu0ccee222021-04-27 11:55:13 -0700521 private void onHelpDisableOrEnablePhysicalSubscription() {
522 PrintWriter pw = getOutPrintWriter();
523 pw.println("Disable or enable a physical subscription");
524 pw.println(" disable-physical-subscription SUB_ID");
525 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
526 pw.println(" enable-physical-subscription SUB_ID");
527 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
528 }
529
Shuo Qianf5125122019-12-16 17:03:07 -0800530 private void onHelpDataTestMode() {
531 PrintWriter pw = getOutPrintWriter();
532 pw.println("Mobile Data Test Mode Commands:");
533 pw.println(" data enable: enable mobile data connectivity");
534 pw.println(" data disable: disable mobile data connectivity");
535 }
536
sqian9d4df8b2019-01-15 18:32:07 -0800537 private void onHelpEmergencyNumber() {
538 PrintWriter pw = getOutPrintWriter();
539 pw.println("Emergency Number Test Mode Commands:");
540 pw.println(" emergency-number-test-mode ");
541 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
542 + " the test mode");
543 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700544 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800545 pw.println(" -c: clear the emergency number list in the test mode.");
546 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700547 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800548 pw.println(" -p: get the full emergency number list in the test mode.");
549 }
550
Shuo Qian489d9282020-07-09 11:30:03 -0700551 private void onHelpEndBlockSupperssion() {
552 PrintWriter pw = getOutPrintWriter();
553 pw.println("End Block Suppression command:");
554 pw.println(" end-block-suppression: disable suppressing blocking by contact");
555 pw.println(" with emergency services.");
556 }
557
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100558 private void onHelpCc() {
559 PrintWriter pw = getOutPrintWriter();
560 pw.println("Carrier Config Commands:");
561 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
562 pw.println(" Print carrier config values.");
563 pw.println(" Options are:");
564 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
565 pw.println(" is specified, it will choose the default voice SIM slot.");
566 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
567 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100568 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100569 pw.println(" Set carrier config KEY to NEW_VALUE.");
570 pw.println(" Options are:");
571 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
572 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100573 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100574 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
575 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
576 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
577 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
578 pw.println(" cc clear-values [-s SLOT_ID]");
579 pw.println(" Clear all carrier override values that has previously been set");
580 pw.println(" with set-value");
581 pw.println(" Options are:");
582 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
583 pw.println(" is specified, it will choose the default voice SIM slot.");
584 }
585
Hui Wang641e81c2020-10-12 12:14:23 -0700586 private void onHelpGba() {
587 PrintWriter pw = getOutPrintWriter();
588 pw.println("Gba Commands:");
589 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
590 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
591 pw.println(" Options are:");
592 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
593 pw.println(" is specified, it will choose the default voice SIM slot.");
594 pw.println(" gba get-service [-s SLOT_ID]");
595 pw.println(" Gets the package name of the currently defined GbaService.");
596 pw.println(" Options are:");
597 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
598 pw.println(" is specified, it will choose the default voice SIM slot.");
599 pw.println(" gba set-release [-s SLOT_ID] n");
600 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
601 pw.println(" Do not release/unbind if n is -1.");
602 pw.println(" Options are:");
603 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
604 pw.println(" is specified, it will choose the default voice SIM slot.");
605 pw.println(" gba get-release [-s SLOT_ID]");
606 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
607 pw.println(" Options are:");
608 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
609 pw.println(" is specified, it will choose the default voice SIM slot.");
610 }
611
Hui Wang761a6682020-10-31 05:12:53 +0000612 private void onHelpSrc() {
613 PrintWriter pw = getOutPrintWriter();
614 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800615 pw.println(" src set-test-enabled true|false");
616 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
617 pw.println(" The value could be true, false, or null(undefined).");
618 pw.println(" src get-test-enabled");
619 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000620 pw.println(" src set-device-enabled true|false|null");
621 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
622 pw.println(" The value could be true, false, or null(undefined).");
623 pw.println(" src get-device-enabled");
624 pw.println(" Gets the device config for RCS VoLTE single registration.");
625 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
626 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
627 pw.println(" The value could be true, false, or null(undefined).");
628 pw.println(" Options are:");
629 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
630 pw.println(" is specified, it will choose the default voice SIM slot.");
631 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
632 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
633 pw.println(" Options are:");
634 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
635 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800636 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
637 pw.println(" Sets ims feature validation result.");
638 pw.println(" The value could be true, false, or null(undefined).");
639 pw.println(" Options are:");
640 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
641 pw.println(" is specified, it will choose the default voice SIM slot.");
642 pw.println(" src get-feature-validation [-s SLOT_ID]");
643 pw.println(" Gets ims feature validation override value.");
644 pw.println(" Options are:");
645 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
646 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000647 }
648
SongFerngWang98dd5992021-05-13 17:50:00 +0800649 private void onHelpAllowedNetworkTypes() {
650 PrintWriter pw = getOutPrintWriter();
651 pw.println("Allowed Network Types Commands:");
652 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
653 pw.println(" Print allowed network types value.");
654 pw.println(" Options are:");
655 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
656 pw.println(" option is specified, it will choose the default voice SIM slot.");
657 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
658 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
659 pw.println(" Options are:");
660 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
661 pw.println(" option is specified, it will choose the default voice SIM slot.");
662 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
663 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
664 pw.println(" at TelephonyManager.java");
665 pw.println(" For example:");
666 pw.println(" NR only : 10000000000000000000");
667 pw.println(" NR|LTE : 11000001000000000000");
668 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
669 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
670 pw.println(" LTE only : 01000001000000000000");
671 }
672
jimsun3b9ccac2021-10-26 15:01:23 +0800673 private void onHelpRadio() {
674 PrintWriter pw = getOutPrintWriter();
675 pw.println("Radio Commands:");
676 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
677 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
678 pw.println(" to be the bound. Options are:");
679 pw.println(" -s: the service name that the modem service should be bound for.");
680 pw.println(" If no option is specified, it will bind to the default.");
681 pw.println(" radio get-modem-service");
682 pw.println(" Gets the service name of the currently defined modem service.");
683 pw.println(" If it is binding to default, 'default' returns.");
684 pw.println(" If it doesn't bind to any modem service for some reasons,");
685 pw.println(" the result would be 'unknown'.");
686 }
687
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700688 private int handleImsCommand() {
689 String arg = getNextArg();
690 if (arg == null) {
691 onHelpIms();
692 return 0;
693 }
694
695 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800696 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700697 return handleImsSetServiceCommand();
698 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800699 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700700 return handleImsGetServiceCommand();
701 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800702 case IMS_CLEAR_SERVICE_OVERRIDE: {
703 return handleImsClearCarrierServiceCommand();
704 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800705 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700706 return handleEnableIms();
707 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800708 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700709 return handleDisableIms();
710 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700711 case IMS_CEP: {
712 return handleCepChange();
713 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700714 }
715
716 return -1;
717 }
718
Shuo Qianf5125122019-12-16 17:03:07 -0800719 private int handleDataTestModeCommand() {
720 PrintWriter errPw = getErrPrintWriter();
721 String arg = getNextArgRequired();
722 if (arg == null) {
723 onHelpDataTestMode();
724 return 0;
725 }
726 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800727 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800728 try {
729 mInterface.enableDataConnectivity();
730 } catch (RemoteException ex) {
731 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
732 errPw.println("Exception: " + ex.getMessage());
733 return -1;
734 }
735 break;
736 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800737 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800738 try {
739 mInterface.disableDataConnectivity();
740 } catch (RemoteException ex) {
741 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
742 errPw.println("Exception: " + ex.getMessage());
743 return -1;
744 }
745 break;
746 }
747 default:
748 onHelpDataTestMode();
749 break;
750 }
751 return 0;
752 }
753
Shuo Qianccbaf742021-02-22 18:32:21 -0800754 private int handleEmergencyCallbackModeCommand() {
755 PrintWriter errPw = getErrPrintWriter();
756 try {
757 mInterface.startEmergencyCallbackMode();
758 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
759 } catch (RemoteException ex) {
760 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
761 errPw.println("Exception: " + ex.getMessage());
762 return -1;
763 }
764 return 0;
765 }
766
sqian9d4df8b2019-01-15 18:32:07 -0800767 private int handleEmergencyNumberTestModeCommand() {
768 PrintWriter errPw = getErrPrintWriter();
769 String opt = getNextOption();
770 if (opt == null) {
771 onHelpEmergencyNumber();
772 return 0;
773 }
774
775 switch (opt) {
776 case "-a": {
777 String emergencyNumberCmd = getNextArgRequired();
778 if (emergencyNumberCmd == null
779 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700780 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800781 + " to be specified after -a in the command ");
782 return -1;
783 }
784 try {
785 mInterface.updateEmergencyNumberListTestMode(
786 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
787 new EmergencyNumber(emergencyNumberCmd, "", "",
788 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
789 new ArrayList<String>(),
790 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
791 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
792 } catch (RemoteException ex) {
793 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
794 + ", error " + ex.getMessage());
795 errPw.println("Exception: " + ex.getMessage());
796 return -1;
797 }
798 break;
799 }
800 case "-c": {
801 try {
802 mInterface.updateEmergencyNumberListTestMode(
803 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
804 } catch (RemoteException ex) {
805 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
806 errPw.println("Exception: " + ex.getMessage());
807 return -1;
808 }
809 break;
810 }
811 case "-r": {
812 String emergencyNumberCmd = getNextArgRequired();
813 if (emergencyNumberCmd == null
814 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700815 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800816 + " to be specified after -r in the command ");
817 return -1;
818 }
819 try {
820 mInterface.updateEmergencyNumberListTestMode(
821 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
822 new EmergencyNumber(emergencyNumberCmd, "", "",
823 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
824 new ArrayList<String>(),
825 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
826 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
827 } catch (RemoteException ex) {
828 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
829 + ", error " + ex.getMessage());
830 errPw.println("Exception: " + ex.getMessage());
831 return -1;
832 }
833 break;
834 }
835 case "-p": {
836 try {
837 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
838 } catch (RemoteException ex) {
839 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
840 errPw.println("Exception: " + ex.getMessage());
841 return -1;
842 }
843 break;
844 }
845 default:
846 onHelpEmergencyNumber();
847 break;
848 }
849 return 0;
850 }
851
Hall Liud892bec2018-11-30 14:51:45 -0800852 private int handleNumberVerificationCommand() {
853 String arg = getNextArg();
854 if (arg == null) {
855 onHelpNumberVerification();
856 return 0;
857 }
858
Hall Liuca5af3a2018-12-04 16:58:23 -0800859 if (!checkShellUid()) {
860 return -1;
861 }
862
Hall Liud892bec2018-11-30 14:51:45 -0800863 switch (arg) {
864 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800865 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
866 return 0;
867 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800868 case NUMBER_VERIFICATION_FAKE_CALL: {
869 boolean val = NumberVerificationManager.getInstance()
870 .checkIncomingCall(getNextArg());
871 getOutPrintWriter().println(val ? "1" : "0");
872 return 0;
873 }
Hall Liud892bec2018-11-30 14:51:45 -0800874 }
875
876 return -1;
877 }
878
Jordan Liu0ccee222021-04-27 11:55:13 -0700879 private boolean subIsEsim(int subId) {
880 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
881 if (info != null) {
882 return info.isEmbedded();
883 }
884 return false;
885 }
886
887 private int handleEnablePhysicalSubscription(boolean enable) {
888 PrintWriter errPw = getErrPrintWriter();
889 int subId = 0;
890 try {
891 subId = Integer.parseInt(getNextArgRequired());
892 } catch (NumberFormatException e) {
893 errPw.println((enable ? "enable" : "disable")
894 + "-physical-subscription requires an integer as a subId.");
895 return -1;
896 }
897 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
898 // non user build.
899 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
900 errPw.println("cc: Permission denied.");
901 return -1;
902 }
903 // Verify that the subId represents a physical sub
904 if (subIsEsim(subId)) {
905 errPw.println("SubId " + subId + " is not for a physical subscription");
906 return -1;
907 }
908 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
909 + " physical subscription with subId=" + subId);
910 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
911 return 0;
912 }
913
Jack Nudelman644b91a2021-03-12 14:09:48 -0800914 private int handleThermalMitigationCommand() {
915 String arg = getNextArg();
916 String packageName = getNextArg();
917 if (arg == null || packageName == null) {
918 onHelpThermalMitigation();
919 return 0;
920 }
921
922 if (!checkShellUid()) {
923 return -1;
924 }
925
926 switch (arg) {
927 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
928 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
929 return 0;
930 }
931 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
932 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
933 mContext);
934 return 0;
935 }
936 default:
937 onHelpThermalMitigation();
938 }
939
940 return -1;
941
942 }
943
Tyler Gunn92479152021-01-20 16:30:10 -0800944 private int handleD2dCommand() {
945 String arg = getNextArg();
946 if (arg == null) {
947 onHelpD2D();
948 return 0;
949 }
950
951 switch (arg) {
952 case D2D_SEND: {
953 return handleD2dSendCommand();
954 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800955 case D2D_TRANSPORT: {
956 return handleD2dTransportCommand();
957 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700958 case D2D_SET_DEVICE_SUPPORT: {
959 return handleD2dDeviceSupportedCommand();
960 }
Tyler Gunn92479152021-01-20 16:30:10 -0800961 }
962
963 return -1;
964 }
965
966 private int handleD2dSendCommand() {
967 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800968 int messageType = -1;
969 int messageValue = -1;
970
Tyler Gunn92479152021-01-20 16:30:10 -0800971 String arg = getNextArg();
972 if (arg == null) {
973 onHelpD2D();
974 return 0;
975 }
976 try {
977 messageType = Integer.parseInt(arg);
978 } catch (NumberFormatException e) {
979 errPw.println("message type must be a valid integer");
980 return -1;
981 }
982
983 arg = getNextArg();
984 if (arg == null) {
985 onHelpD2D();
986 return 0;
987 }
988 try {
989 messageValue = Integer.parseInt(arg);
990 } catch (NumberFormatException e) {
991 errPw.println("message value must be a valid integer");
992 return -1;
993 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800994
Tyler Gunn92479152021-01-20 16:30:10 -0800995 try {
996 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
997 } catch (RemoteException e) {
998 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
999 errPw.println("Exception: " + e.getMessage());
1000 return -1;
1001 }
1002
1003 return 0;
1004 }
1005
Tyler Gunnbabbda02021-02-10 11:05:02 -08001006 private int handleD2dTransportCommand() {
1007 PrintWriter errPw = getErrPrintWriter();
1008
1009 String arg = getNextArg();
1010 if (arg == null) {
1011 onHelpD2D();
1012 return 0;
1013 }
1014
1015 try {
1016 mInterface.setActiveDeviceToDeviceTransport(arg);
1017 } catch (RemoteException e) {
1018 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1019 errPw.println("Exception: " + e.getMessage());
1020 return -1;
1021 }
1022 return 0;
1023 }
Nazanin014f41e2021-05-06 17:26:31 -07001024 private int handleBarringCommand() {
1025 String arg = getNextArg();
1026 if (arg == null) {
1027 onHelpBarring();
1028 return 0;
1029 }
1030
1031 switch (arg) {
1032 case BARRING_SEND_INFO: {
1033 return handleBarringSendCommand();
1034 }
1035 }
1036 return -1;
1037 }
1038
1039 private int handleBarringSendCommand() {
1040 PrintWriter errPw = getErrPrintWriter();
1041 int slotId = getDefaultSlot();
1042 int subId = SubscriptionManager.getSubId(slotId)[0];
1043 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1044 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1045 boolean isConditionallyBarred = false;
1046 int conditionalBarringTimeSeconds = 0;
1047
1048 String opt;
1049 while ((opt = getNextOption()) != null) {
1050 switch (opt) {
1051 case "-s": {
1052 try {
1053 slotId = Integer.parseInt(getNextArgRequired());
1054 subId = SubscriptionManager.getSubId(slotId)[0];
1055 } catch (NumberFormatException e) {
1056 errPw.println("barring send requires an integer as a SLOT_ID.");
1057 return -1;
1058 }
1059 break;
1060 }
1061 case "-b": {
1062 try {
1063 barringType = Integer.parseInt(getNextArgRequired());
1064 if (barringType < -1 || barringType > 2) {
1065 throw new NumberFormatException();
1066 }
1067
1068 } catch (NumberFormatException e) {
1069 errPw.println("barring send requires an integer in range [-1,2] as "
1070 + "a BARRING_TYPE.");
1071 return -1;
1072 }
1073 break;
1074 }
1075 case "-c": {
1076 try {
1077 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1078 } catch (Exception e) {
1079 errPw.println("barring send requires a boolean after -c indicating"
1080 + " conditional barring");
1081 return -1;
1082 }
1083 break;
1084 }
1085 case "-t": {
1086 try {
1087 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1088 } catch (NumberFormatException e) {
1089 errPw.println("barring send requires an integer for time of barring"
1090 + " in seconds after -t for conditional barring");
1091 return -1;
1092 }
1093 break;
1094 }
1095 }
1096 }
1097 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1098 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1099 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1100 barringServiceInfos.append(0, bsi);
1101 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1102 try {
1103 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1104 } catch (Exception e) {
1105 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1106 errPw.println("Exception: " + e.getMessage());
1107 return -1;
1108 }
1109 return 0;
1110 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001111
Tyler Gunnd4575212021-05-03 14:46:49 -07001112 private int handleD2dDeviceSupportedCommand() {
1113 PrintWriter errPw = getErrPrintWriter();
1114
1115 String arg = getNextArg();
1116 if (arg == null) {
1117 onHelpD2D();
1118 return 0;
1119 }
1120
1121 boolean isEnabled = "true".equals(arg.toLowerCase());
1122 try {
1123 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1124 } catch (RemoteException e) {
1125 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1126 errPw.println("Exception: " + e.getMessage());
1127 return -1;
1128 }
1129 return 0;
1130 }
1131
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001132 // ims set-ims-service
1133 private int handleImsSetServiceCommand() {
1134 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001135 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001136 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001137 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001138
1139 String opt;
1140 while ((opt = getNextOption()) != null) {
1141 switch (opt) {
1142 case "-s": {
1143 try {
1144 slotId = Integer.parseInt(getNextArgRequired());
1145 } catch (NumberFormatException e) {
1146 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1147 return -1;
1148 }
1149 break;
1150 }
1151 case "-c": {
1152 isCarrierService = true;
1153 break;
1154 }
1155 case "-d": {
1156 isCarrierService = false;
1157 break;
1158 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001159 case "-f": {
1160 String featureString = getNextArgRequired();
1161 String[] features = featureString.split(",");
1162 for (int i = 0; i < features.length; i++) {
1163 try {
1164 Integer result = Integer.parseInt(features[i]);
1165 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1166 || result >= ImsFeature.FEATURE_MAX) {
1167 errPw.println("ims set-ims-service -f " + result
1168 + " is an invalid feature.");
1169 return -1;
1170 }
1171 featuresList.add(result);
1172 } catch (NumberFormatException e) {
1173 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1174 + " as an integer.");
1175 return -1;
1176 }
1177 }
1178 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001179 }
1180 }
1181 // Mandatory param, either -c or -d
1182 if (isCarrierService == null) {
1183 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1184 return -1;
1185 }
1186
1187 String packageName = getNextArg();
1188
1189 try {
1190 if (packageName == null) {
1191 packageName = "";
1192 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001193 int[] featureArray = new int[featuresList.size()];
1194 for (int i = 0; i < featuresList.size(); i++) {
1195 featureArray[i] = featuresList.get(i);
1196 }
1197 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1198 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001199 if (VDBG) {
1200 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001201 + (isCarrierService ? "-c " : "-d ")
1202 + "-f " + featuresList + " "
1203 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001204 }
1205 getOutPrintWriter().println(result);
1206 } catch (RemoteException e) {
1207 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001208 + (isCarrierService ? "-c " : "-d ")
1209 + "-f " + featuresList + " "
1210 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001211 errPw.println("Exception: " + e.getMessage());
1212 return -1;
1213 }
1214 return 0;
1215 }
1216
Brad Ebinger999d3302020-11-25 14:31:39 -08001217 // ims clear-ims-service-override
1218 private int handleImsClearCarrierServiceCommand() {
1219 PrintWriter errPw = getErrPrintWriter();
1220 int slotId = getDefaultSlot();
1221
1222 String opt;
1223 while ((opt = getNextOption()) != null) {
1224 switch (opt) {
1225 case "-s": {
1226 try {
1227 slotId = Integer.parseInt(getNextArgRequired());
1228 } catch (NumberFormatException e) {
1229 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1230 return -1;
1231 }
1232 break;
1233 }
1234 }
1235 }
1236
1237 try {
1238 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1239 if (VDBG) {
1240 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1241 + ", result=" + result);
1242 }
1243 getOutPrintWriter().println(result);
1244 } catch (RemoteException e) {
1245 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1246 + ", error" + e.getMessage());
1247 errPw.println("Exception: " + e.getMessage());
1248 return -1;
1249 }
1250 return 0;
1251 }
1252
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001253 // ims get-ims-service
1254 private int handleImsGetServiceCommand() {
1255 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001256 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001257 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001258 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001259
1260 String opt;
1261 while ((opt = getNextOption()) != null) {
1262 switch (opt) {
1263 case "-s": {
1264 try {
1265 slotId = Integer.parseInt(getNextArgRequired());
1266 } catch (NumberFormatException e) {
1267 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1268 return -1;
1269 }
1270 break;
1271 }
1272 case "-c": {
1273 isCarrierService = true;
1274 break;
1275 }
1276 case "-d": {
1277 isCarrierService = false;
1278 break;
1279 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001280 case "-f": {
1281 try {
1282 featureType = Integer.parseInt(getNextArg());
1283 } catch (NumberFormatException e) {
1284 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1285 return -1;
1286 }
1287 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1288 || featureType >= ImsFeature.FEATURE_MAX) {
1289 errPw.println("ims get-ims-service -f invalid feature.");
1290 return -1;
1291 }
1292 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001293 }
1294 }
1295 // Mandatory param, either -c or -d
1296 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001297 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001298 return -1;
1299 }
1300
1301 String result;
1302 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001303 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001304 } catch (RemoteException e) {
1305 return -1;
1306 }
1307 if (VDBG) {
1308 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001309 + (isCarrierService ? "-c " : "-d ")
1310 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1311 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001312 }
1313 getOutPrintWriter().println(result);
1314 return 0;
1315 }
1316
1317 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001318 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001319 String opt;
1320 while ((opt = getNextOption()) != null) {
1321 switch (opt) {
1322 case "-s": {
1323 try {
1324 slotId = Integer.parseInt(getNextArgRequired());
1325 } catch (NumberFormatException e) {
1326 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1327 return -1;
1328 }
1329 break;
1330 }
1331 }
1332 }
1333 try {
1334 mInterface.enableIms(slotId);
1335 } catch (RemoteException e) {
1336 return -1;
1337 }
1338 if (VDBG) {
1339 Log.v(LOG_TAG, "ims enable -s " + slotId);
1340 }
1341 return 0;
1342 }
1343
1344 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001345 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001346 String opt;
1347 while ((opt = getNextOption()) != null) {
1348 switch (opt) {
1349 case "-s": {
1350 try {
1351 slotId = Integer.parseInt(getNextArgRequired());
1352 } catch (NumberFormatException e) {
1353 getErrPrintWriter().println(
1354 "ims disable requires an integer as a SLOT_ID.");
1355 return -1;
1356 }
1357 break;
1358 }
1359 }
1360 }
1361 try {
1362 mInterface.disableIms(slotId);
1363 } catch (RemoteException e) {
1364 return -1;
1365 }
1366 if (VDBG) {
1367 Log.v(LOG_TAG, "ims disable -s " + slotId);
1368 }
1369 return 0;
1370 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001371
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001372 private int handleCepChange() {
1373 Log.i(LOG_TAG, "handleCepChange");
1374 String opt = getNextArg();
1375 if (opt == null) {
1376 return -1;
1377 }
1378 boolean isCepEnabled = opt.equals("enable");
1379
1380 try {
1381 mInterface.setCepEnabled(isCepEnabled);
1382 } catch (RemoteException e) {
1383 return -1;
1384 }
1385 return 0;
1386 }
1387
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001388 private int getDefaultSlot() {
1389 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1390 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1391 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1392 // If there is no default, default to slot 0.
1393 slotId = DEFAULT_PHONE_ID;
1394 }
1395 return slotId;
1396 }
sqian2fff4a32018-11-05 14:18:37 -08001397
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001398 // Parse options related to Carrier Config Commands.
1399 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001400 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001401 CcOptionParseResult result = new CcOptionParseResult();
1402 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1403 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001404
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001405 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001406 while ((opt = getNextOption()) != null) {
1407 switch (opt) {
1408 case "-s": {
1409 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001410 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1411 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1412 errPw.println(tag + "No valid subscription found.");
1413 return null;
1414 }
1415
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001416 } catch (IllegalArgumentException e) {
1417 // Missing slot id
1418 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001419 return null;
1420 }
1421 break;
1422 }
1423 case "-p": {
1424 if (allowOptionPersistent) {
1425 result.mPersistent = true;
1426 } else {
1427 errPw.println(tag + "Unexpected option " + opt);
1428 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001429 }
1430 break;
1431 }
1432 default: {
1433 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001434 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001435 }
1436 }
1437 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001438 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001439 }
1440
1441 private int slotStringToSubId(String tag, String slotString) {
1442 int slotId = -1;
1443 try {
1444 slotId = Integer.parseInt(slotString);
1445 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001446 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1447 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1448 }
1449
1450 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001451 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1452 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1453 }
1454
Qiong Liuf25799b2020-09-10 10:13:46 +08001455 Phone phone = PhoneFactory.getPhone(slotId);
1456 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001457 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1458 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1459 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001460 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001461 }
1462
Hall Liud892bec2018-11-30 14:51:45 -08001463 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001464 // adb can run as root or as shell, depending on whether the device is rooted.
1465 return Binder.getCallingUid() == Process.SHELL_UID
1466 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001467 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001468
1469 private int handleCcCommand() {
1470 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1471 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001472 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001473 getErrPrintWriter().println("cc: Permission denied.");
1474 return -1;
1475 }
1476
1477 String arg = getNextArg();
1478 if (arg == null) {
1479 onHelpCc();
1480 return 0;
1481 }
1482
1483 switch (arg) {
1484 case CC_GET_VALUE: {
1485 return handleCcGetValue();
1486 }
1487 case CC_SET_VALUE: {
1488 return handleCcSetValue();
1489 }
1490 case CC_CLEAR_VALUES: {
1491 return handleCcClearValues();
1492 }
1493 default: {
1494 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1495 }
1496 }
1497 return -1;
1498 }
1499
1500 // cc get-value
1501 private int handleCcGetValue() {
1502 PrintWriter errPw = getErrPrintWriter();
1503 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1504 String key = null;
1505
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001506 // Parse all options
1507 CcOptionParseResult options = parseCcOptions(tag, false);
1508 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001509 return -1;
1510 }
1511
1512 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001513 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001514 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001515 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001516 return -1;
1517 }
1518
1519 // Get the key.
1520 key = getNextArg();
1521 if (key != null) {
1522 // A key was provided. Verify if it is a valid key
1523 if (!bundle.containsKey(key)) {
1524 errPw.println(tag + key + " is not a valid key.");
1525 return -1;
1526 }
1527
1528 // Print the carrier config value for key.
1529 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1530 } else {
1531 // No key provided. Show all values.
1532 // Iterate over a sorted list of all carrier config keys and print them.
1533 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1534 for (String k : sortedSet) {
1535 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1536 }
1537 }
1538 return 0;
1539 }
1540
1541 // cc set-value
1542 private int handleCcSetValue() {
1543 PrintWriter errPw = getErrPrintWriter();
1544 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1545
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001546 // Parse all options
1547 CcOptionParseResult options = parseCcOptions(tag, true);
1548 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001549 return -1;
1550 }
1551
1552 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001553 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001554 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001555 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001556 return -1;
1557 }
1558
1559 // Get the key.
1560 String key = getNextArg();
1561 if (key == null || key.equals("")) {
1562 errPw.println(tag + "KEY is missing");
1563 return -1;
1564 }
1565
1566 // Verify if the key is valid
1567 if (!originalValues.containsKey(key)) {
1568 errPw.println(tag + key + " is not a valid key.");
1569 return -1;
1570 }
1571
1572 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1573 ArrayList<String> valueList = new ArrayList<String>();
1574 while (peekNextArg() != null) {
1575 valueList.add(getNextArg());
1576 }
1577
1578 // Find the type of the carrier config value
1579 CcType type = getType(tag, key, originalValues);
1580 if (type == CcType.UNKNOWN) {
1581 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1582 return -1;
1583 }
1584
1585 // Create an override bundle containing the key and value that should be overriden.
1586 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1587 if (overrideBundle == null) {
1588 return -1;
1589 }
1590
1591 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001592 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001593
1594 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001595 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001596 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001597 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001598 return -1;
1599 }
1600
1601 // Print the original and new value.
1602 String originalValueString = ccValueToString(key, type, originalValues);
1603 String newValueString = ccValueToString(key, type, newValues);
1604 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1605 getOutPrintWriter().println("New value: \n" + newValueString);
1606
1607 return 0;
1608 }
1609
1610 // cc clear-values
1611 private int handleCcClearValues() {
1612 PrintWriter errPw = getErrPrintWriter();
1613 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1614
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001615 // Parse all options
1616 CcOptionParseResult options = parseCcOptions(tag, false);
1617 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001618 return -1;
1619 }
1620
1621 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001622 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001623 getOutPrintWriter()
1624 .println("All previously set carrier config override values has been cleared");
1625 return 0;
1626 }
1627
1628 private CcType getType(String tag, String key, PersistableBundle bundle) {
1629 // Find the type by checking the type of the current value stored in the bundle.
1630 Object value = bundle.get(key);
1631
1632 if (CC_TYPE_MAP.containsKey(key)) {
1633 return CC_TYPE_MAP.get(key);
1634 } else if (value != null) {
1635 if (value instanceof Boolean) {
1636 return CcType.BOOLEAN;
1637 } else if (value instanceof Double) {
1638 return CcType.DOUBLE;
1639 } else if (value instanceof double[]) {
1640 return CcType.DOUBLE_ARRAY;
1641 } else if (value instanceof Integer) {
1642 return CcType.INT;
1643 } else if (value instanceof int[]) {
1644 return CcType.INT_ARRAY;
1645 } else if (value instanceof Long) {
1646 return CcType.LONG;
1647 } else if (value instanceof long[]) {
1648 return CcType.LONG_ARRAY;
1649 } else if (value instanceof String) {
1650 return CcType.STRING;
1651 } else if (value instanceof String[]) {
1652 return CcType.STRING_ARRAY;
1653 }
1654 } else {
1655 // Current value was null and can therefore not be used in order to find the type.
1656 // Check the name of the key to infer the type. This check is not needed for primitive
1657 // data types (boolean, double, int and long), since they can not be null.
1658 if (key.endsWith("double_array")) {
1659 return CcType.DOUBLE_ARRAY;
1660 }
1661 if (key.endsWith("int_array")) {
1662 return CcType.INT_ARRAY;
1663 }
1664 if (key.endsWith("long_array")) {
1665 return CcType.LONG_ARRAY;
1666 }
1667 if (key.endsWith("string")) {
1668 return CcType.STRING;
1669 }
1670 if (key.endsWith("string_array") || key.endsWith("strings")) {
1671 return CcType.STRING_ARRAY;
1672 }
1673 }
1674
1675 // Not possible to infer the type by looking at the current value or the key.
1676 PrintWriter errPw = getErrPrintWriter();
1677 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1678 return CcType.UNKNOWN;
1679 }
1680
1681 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1682 String result;
1683 StringBuilder valueString = new StringBuilder();
1684 String typeString = type.toString();
1685 Object value = bundle.get(key);
1686
1687 if (value == null) {
1688 valueString.append("null");
1689 } else {
1690 switch (type) {
1691 case DOUBLE_ARRAY: {
1692 // Format the string representation of the int array as value1 value2......
1693 double[] valueArray = (double[]) value;
1694 for (int i = 0; i < valueArray.length; i++) {
1695 if (i != 0) {
1696 valueString.append(" ");
1697 }
1698 valueString.append(valueArray[i]);
1699 }
1700 break;
1701 }
1702 case INT_ARRAY: {
1703 // Format the string representation of the int array as value1 value2......
1704 int[] valueArray = (int[]) value;
1705 for (int i = 0; i < valueArray.length; i++) {
1706 if (i != 0) {
1707 valueString.append(" ");
1708 }
1709 valueString.append(valueArray[i]);
1710 }
1711 break;
1712 }
1713 case LONG_ARRAY: {
1714 // Format the string representation of the int array as value1 value2......
1715 long[] valueArray = (long[]) value;
1716 for (int i = 0; i < valueArray.length; i++) {
1717 if (i != 0) {
1718 valueString.append(" ");
1719 }
1720 valueString.append(valueArray[i]);
1721 }
1722 break;
1723 }
1724 case STRING: {
1725 valueString.append("\"" + value.toString() + "\"");
1726 break;
1727 }
1728 case STRING_ARRAY: {
1729 // Format the string representation of the string array as "value1" "value2"....
1730 String[] valueArray = (String[]) value;
1731 for (int i = 0; i < valueArray.length; i++) {
1732 if (i != 0) {
1733 valueString.append(" ");
1734 }
1735 if (valueArray[i] != null) {
1736 valueString.append("\"" + valueArray[i] + "\"");
1737 } else {
1738 valueString.append("null");
1739 }
1740 }
1741 break;
1742 }
1743 default: {
1744 valueString.append(value.toString());
1745 }
1746 }
1747 }
1748 return String.format("%-70s %-15s %s", key, typeString, valueString);
1749 }
1750
1751 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1752 ArrayList<String> valueList) {
1753 PrintWriter errPw = getErrPrintWriter();
1754 PersistableBundle bundle = new PersistableBundle();
1755
1756 // First verify that a valid number of values has been provided for the type.
1757 switch (type) {
1758 case BOOLEAN:
1759 case DOUBLE:
1760 case INT:
1761 case LONG: {
1762 if (valueList.size() != 1) {
1763 errPw.println(tag + "Expected 1 value for type " + type
1764 + ". Found: " + valueList.size());
1765 return null;
1766 }
1767 break;
1768 }
1769 case STRING: {
1770 if (valueList.size() > 1) {
1771 errPw.println(tag + "Expected 0 or 1 values for type " + type
1772 + ". Found: " + valueList.size());
1773 return null;
1774 }
1775 break;
1776 }
1777 }
1778
1779 // Parse the value according to type and add it to the Bundle.
1780 switch (type) {
1781 case BOOLEAN: {
1782 if ("true".equalsIgnoreCase(valueList.get(0))) {
1783 bundle.putBoolean(key, true);
1784 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1785 bundle.putBoolean(key, false);
1786 } else {
1787 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1788 return null;
1789 }
1790 break;
1791 }
1792 case DOUBLE: {
1793 try {
1794 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1795 } catch (NumberFormatException nfe) {
1796 // Not a valid double
1797 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1798 return null;
1799 }
1800 break;
1801 }
1802 case DOUBLE_ARRAY: {
1803 double[] valueDoubleArray = null;
1804 if (valueList.size() > 0) {
1805 valueDoubleArray = new double[valueList.size()];
1806 for (int i = 0; i < valueList.size(); i++) {
1807 try {
1808 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1809 } catch (NumberFormatException nfe) {
1810 // Not a valid double
1811 errPw.println(
1812 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1813 return null;
1814 }
1815 }
1816 }
1817 bundle.putDoubleArray(key, valueDoubleArray);
1818 break;
1819 }
1820 case INT: {
1821 try {
1822 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1823 } catch (NumberFormatException nfe) {
1824 // Not a valid integer
1825 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1826 return null;
1827 }
1828 break;
1829 }
1830 case INT_ARRAY: {
1831 int[] valueIntArray = null;
1832 if (valueList.size() > 0) {
1833 valueIntArray = new int[valueList.size()];
1834 for (int i = 0; i < valueList.size(); i++) {
1835 try {
1836 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1837 } catch (NumberFormatException nfe) {
1838 // Not a valid integer
1839 errPw.println(tag
1840 + "Unable to parse " + valueList.get(i) + " as an integer.");
1841 return null;
1842 }
1843 }
1844 }
1845 bundle.putIntArray(key, valueIntArray);
1846 break;
1847 }
1848 case LONG: {
1849 try {
1850 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1851 } catch (NumberFormatException nfe) {
1852 // Not a valid long
1853 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1854 return null;
1855 }
1856 break;
1857 }
1858 case LONG_ARRAY: {
1859 long[] valueLongArray = null;
1860 if (valueList.size() > 0) {
1861 valueLongArray = new long[valueList.size()];
1862 for (int i = 0; i < valueList.size(); i++) {
1863 try {
1864 valueLongArray[i] = Long.parseLong(valueList.get(i));
1865 } catch (NumberFormatException nfe) {
1866 // Not a valid long
1867 errPw.println(
1868 tag + "Unable to parse " + valueList.get(i) + " as a long");
1869 return null;
1870 }
1871 }
1872 }
1873 bundle.putLongArray(key, valueLongArray);
1874 break;
1875 }
1876 case STRING: {
1877 String value = null;
1878 if (valueList.size() > 0) {
1879 value = valueList.get(0);
1880 }
1881 bundle.putString(key, value);
1882 break;
1883 }
1884 case STRING_ARRAY: {
1885 String[] valueStringArray = null;
1886 if (valueList.size() > 0) {
1887 valueStringArray = new String[valueList.size()];
1888 valueList.toArray(valueStringArray);
1889 }
1890 bundle.putStringArray(key, valueStringArray);
1891 break;
1892 }
1893 }
1894 return bundle;
1895 }
Shuo Qian489d9282020-07-09 11:30:03 -07001896
1897 private int handleEndBlockSuppressionCommand() {
1898 if (!checkShellUid()) {
1899 return -1;
1900 }
1901
1902 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1903 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1904 }
1905 return 0;
1906 }
Hui Wang641e81c2020-10-12 12:14:23 -07001907
Michele Berionne54af4632020-12-28 20:23:16 +00001908 private int handleRestartModemCommand() {
1909 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1910 // non user build.
1911 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1912 getErrPrintWriter().println("RestartModem: Permission denied.");
1913 return -1;
1914 }
1915
1916 boolean result = TelephonyManager.getDefault().rebootRadio();
1917 getOutPrintWriter().println(result);
1918
1919 return result ? 0 : -1;
1920 }
1921
Michele Berionne5e411512020-11-13 02:36:59 +00001922 private int handleUnattendedReboot() {
1923 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1924 // non user build.
1925 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1926 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1927 return -1;
1928 }
1929
1930 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1931 getOutPrintWriter().println("result: " + result);
1932
1933 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1934 }
1935
Hui Wang641e81c2020-10-12 12:14:23 -07001936 private int handleGbaCommand() {
1937 String arg = getNextArg();
1938 if (arg == null) {
1939 onHelpGba();
1940 return 0;
1941 }
1942
1943 switch (arg) {
1944 case GBA_SET_SERVICE: {
1945 return handleGbaSetServiceCommand();
1946 }
1947 case GBA_GET_SERVICE: {
1948 return handleGbaGetServiceCommand();
1949 }
1950 case GBA_SET_RELEASE_TIME: {
1951 return handleGbaSetReleaseCommand();
1952 }
1953 case GBA_GET_RELEASE_TIME: {
1954 return handleGbaGetReleaseCommand();
1955 }
1956 }
1957
1958 return -1;
1959 }
1960
1961 private int getSubId(String cmd) {
1962 int slotId = getDefaultSlot();
1963 String opt = getNextOption();
1964 if (opt != null && opt.equals("-s")) {
1965 try {
1966 slotId = Integer.parseInt(getNextArgRequired());
1967 } catch (NumberFormatException e) {
1968 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1969 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1970 }
1971 }
1972 int[] subIds = SubscriptionManager.getSubId(slotId);
1973 return subIds[0];
1974 }
1975
1976 private int handleGbaSetServiceCommand() {
1977 int subId = getSubId("gba set-service");
1978 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1979 return -1;
1980 }
1981
1982 String packageName = getNextArg();
1983 try {
1984 if (packageName == null) {
1985 packageName = "";
1986 }
1987 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1988 if (VDBG) {
1989 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1990 + packageName + ", result=" + result);
1991 }
1992 getOutPrintWriter().println(result);
1993 } catch (RemoteException e) {
1994 Log.w(LOG_TAG, "gba set-service " + subId + " "
1995 + packageName + ", error" + e.getMessage());
1996 getErrPrintWriter().println("Exception: " + e.getMessage());
1997 return -1;
1998 }
1999 return 0;
2000 }
2001
2002 private int handleGbaGetServiceCommand() {
2003 String result;
2004
2005 int subId = getSubId("gba get-service");
2006 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2007 return -1;
2008 }
2009
2010 try {
2011 result = mInterface.getBoundGbaService(subId);
2012 } catch (RemoteException e) {
2013 return -1;
2014 }
2015 if (VDBG) {
2016 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2017 }
2018 getOutPrintWriter().println(result);
2019 return 0;
2020 }
2021
2022 private int handleGbaSetReleaseCommand() {
2023 //the release time value could be -1
2024 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2025 : SubscriptionManager.getDefaultSubscriptionId();
2026 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2027 return -1;
2028 }
2029
2030 String intervalStr = getNextArg();
2031 if (intervalStr == null) {
2032 return -1;
2033 }
2034
2035 try {
2036 int interval = Integer.parseInt(intervalStr);
2037 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2038 if (VDBG) {
2039 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2040 + intervalStr + ", result=" + result);
2041 }
2042 getOutPrintWriter().println(result);
2043 } catch (NumberFormatException | RemoteException e) {
2044 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2045 + intervalStr + ", error" + e.getMessage());
2046 getErrPrintWriter().println("Exception: " + e.getMessage());
2047 return -1;
2048 }
2049 return 0;
2050 }
2051
2052 private int handleGbaGetReleaseCommand() {
2053 int subId = getSubId("gba get-release");
2054 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2055 return -1;
2056 }
2057
2058 int result = 0;
2059 try {
2060 result = mInterface.getGbaReleaseTime(subId);
2061 } catch (RemoteException e) {
2062 return -1;
2063 }
2064 if (VDBG) {
2065 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2066 }
2067 getOutPrintWriter().println(result);
2068 return 0;
2069 }
Hui Wang761a6682020-10-31 05:12:53 +00002070
2071 private int handleSingleRegistrationConfigCommand() {
2072 String arg = getNextArg();
2073 if (arg == null) {
2074 onHelpSrc();
2075 return 0;
2076 }
2077
2078 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002079 case SRC_SET_TEST_ENABLED: {
2080 return handleSrcSetTestEnabledCommand();
2081 }
2082 case SRC_GET_TEST_ENABLED: {
2083 return handleSrcGetTestEnabledCommand();
2084 }
Hui Wang761a6682020-10-31 05:12:53 +00002085 case SRC_SET_DEVICE_ENABLED: {
2086 return handleSrcSetDeviceEnabledCommand();
2087 }
2088 case SRC_GET_DEVICE_ENABLED: {
2089 return handleSrcGetDeviceEnabledCommand();
2090 }
2091 case SRC_SET_CARRIER_ENABLED: {
2092 return handleSrcSetCarrierEnabledCommand();
2093 }
2094 case SRC_GET_CARRIER_ENABLED: {
2095 return handleSrcGetCarrierEnabledCommand();
2096 }
Hui Wangb647abe2021-02-26 09:33:38 -08002097 case SRC_SET_FEATURE_ENABLED: {
2098 return handleSrcSetFeatureValidationCommand();
2099 }
2100 case SRC_GET_FEATURE_ENABLED: {
2101 return handleSrcGetFeatureValidationCommand();
2102 }
Hui Wang761a6682020-10-31 05:12:53 +00002103 }
2104
2105 return -1;
2106 }
2107
James.cf Linbcdf8b32021-01-14 16:44:13 +08002108 private int handleRcsUceCommand() {
2109 String arg = getNextArg();
2110 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002111 onHelpUce();
2112 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002113 }
2114
2115 switch (arg) {
2116 case UCE_REMOVE_EAB_CONTACT:
2117 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002118 case UCE_GET_EAB_CONTACT:
2119 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002120 case UCE_GET_EAB_CAPABILITY:
2121 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002122 case UCE_GET_DEVICE_ENABLED:
2123 return handleUceGetDeviceEnabledCommand();
2124 case UCE_SET_DEVICE_ENABLED:
2125 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002126 case UCE_OVERRIDE_PUBLISH_CAPS:
2127 return handleUceOverridePublishCaps();
2128 case UCE_GET_LAST_PIDF_XML:
2129 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002130 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2131 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002132 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2133 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002134 }
2135 return -1;
2136 }
2137
2138 private int handleRemovingEabContactCommand() {
2139 int subId = getSubId("uce remove-eab-contact");
2140 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2141 return -1;
2142 }
2143
2144 String phoneNumber = getNextArgRequired();
2145 if (TextUtils.isEmpty(phoneNumber)) {
2146 return -1;
2147 }
2148 int result = 0;
2149 try {
2150 result = mInterface.removeContactFromEab(subId, phoneNumber);
2151 } catch (RemoteException e) {
2152 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2153 getErrPrintWriter().println("Exception: " + e.getMessage());
2154 return -1;
2155 }
2156
2157 if (VDBG) {
2158 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2159 }
calvinpan293ea1b2021-02-04 17:52:13 +08002160 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002161 }
2162
calvinpane4a8a1d2021-01-25 13:51:18 +08002163 private int handleGettingEabContactCommand() {
2164 String phoneNumber = getNextArgRequired();
2165 if (TextUtils.isEmpty(phoneNumber)) {
2166 return -1;
2167 }
2168 String result = "";
2169 try {
2170 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002171 } catch (RemoteException e) {
2172 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2173 getErrPrintWriter().println("Exception: " + e.getMessage());
2174 return -1;
2175 }
2176
2177 if (VDBG) {
2178 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2179 }
calvinpan293ea1b2021-02-04 17:52:13 +08002180 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002181 return 0;
2182 }
2183
Calvin Pana1434322021-07-01 19:27:01 +08002184 private int handleGettingEabCapabilityCommand() {
2185 String phoneNumber = getNextArgRequired();
2186 if (TextUtils.isEmpty(phoneNumber)) {
2187 return -1;
2188 }
2189 String result = "";
2190 try {
2191 result = mInterface.getCapabilityFromEab(phoneNumber);
2192 } catch (RemoteException e) {
2193 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2194 getErrPrintWriter().println("Exception: " + e.getMessage());
2195 return -1;
2196 }
2197
2198 if (VDBG) {
2199 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2200 }
2201 getOutPrintWriter().println(result);
2202 return 0;
2203 }
2204
James.cf Lin4b784aa2021-01-31 03:25:15 +08002205 private int handleUceGetDeviceEnabledCommand() {
2206 boolean result = false;
2207 try {
2208 result = mInterface.getDeviceUceEnabled();
2209 } catch (RemoteException e) {
2210 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2211 return -1;
2212 }
2213 if (VDBG) {
2214 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2215 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002216 getOutPrintWriter().println(result);
2217 return 0;
2218 }
2219
James.cf Lin4b784aa2021-01-31 03:25:15 +08002220 private int handleUceSetDeviceEnabledCommand() {
2221 String enabledStr = getNextArg();
2222 if (TextUtils.isEmpty(enabledStr)) {
2223 return -1;
2224 }
2225
2226 try {
2227 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2228 mInterface.setDeviceUceEnabled(isEnabled);
2229 if (VDBG) {
2230 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2231 }
2232 } catch (NumberFormatException | RemoteException e) {
2233 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2234 getErrPrintWriter().println("Exception: " + e.getMessage());
2235 return -1;
2236 }
2237 return 0;
2238 }
2239
James.cf Line8713a42021-04-29 16:04:26 +08002240 private int handleUceRemoveRequestDisallowedStatus() {
2241 int subId = getSubId("uce remove-request-disallowed-status");
2242 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2243 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2244 return -1;
2245 }
2246 boolean result;
2247 try {
2248 result = mInterface.removeUceRequestDisallowedStatus(subId);
2249 } catch (RemoteException e) {
2250 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2251 return -1;
2252 }
2253 if (VDBG) {
2254 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2255 }
2256 getOutPrintWriter().println(result);
2257 return 0;
2258 }
2259
James.cf Lin0fc71b02021-05-25 01:37:38 +08002260 private int handleUceSetCapRequestTimeout() {
2261 int subId = getSubId("uce set-capabilities-request-timeout");
2262 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2263 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2264 return -1;
2265 }
2266 long timeoutAfterMs = Long.valueOf(getNextArg());
2267 boolean result;
2268 try {
2269 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2270 } catch (RemoteException e) {
2271 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2272 return -1;
2273 }
2274 if (VDBG) {
2275 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2276 }
2277 getOutPrintWriter().println(result);
2278 return 0;
2279 }
2280
Hui Wangbaaee6a2021-02-19 20:45:36 -08002281 private int handleSrcSetTestEnabledCommand() {
2282 String enabledStr = getNextArg();
2283 if (enabledStr == null) {
2284 return -1;
2285 }
2286
2287 try {
2288 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2289 if (VDBG) {
2290 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2291 }
2292 getOutPrintWriter().println("Done");
2293 } catch (NumberFormatException | RemoteException e) {
2294 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2295 getErrPrintWriter().println("Exception: " + e.getMessage());
2296 return -1;
2297 }
2298 return 0;
2299 }
2300
2301 private int handleSrcGetTestEnabledCommand() {
2302 boolean result = false;
2303 try {
2304 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2305 } catch (RemoteException e) {
2306 return -1;
2307 }
2308 if (VDBG) {
2309 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2310 }
2311 getOutPrintWriter().println(result);
2312 return 0;
2313 }
2314
Brad Ebinger14d467f2021-02-12 06:18:28 +00002315 private int handleUceOverridePublishCaps() {
2316 int subId = getSubId("uce override-published-caps");
2317 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2318 return -1;
2319 }
2320 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2321 String operation = getNextArgRequired();
2322 String caps = getNextArg();
2323 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2324 && !"list".equals(operation)) {
2325 getErrPrintWriter().println("Invalid operation: " + operation);
2326 return -1;
2327 }
2328
2329 // add/remove requires capabilities to be specified.
2330 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2331 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2332 + "specified");
2333 return -1;
2334 }
2335
2336 ArraySet<String> capSet = new ArraySet<>();
2337 if (!TextUtils.isEmpty(caps)) {
2338 String[] capArray = caps.split(":");
2339 for (String cap : capArray) {
2340 // Allow unknown tags to be passed in as well.
2341 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2342 }
2343 }
2344
2345 RcsContactUceCapability result = null;
2346 try {
2347 switch (operation) {
2348 case "add":
2349 result = mInterface.addUceRegistrationOverrideShell(subId,
2350 new ArrayList<>(capSet));
2351 break;
2352 case "remove":
2353 result = mInterface.removeUceRegistrationOverrideShell(subId,
2354 new ArrayList<>(capSet));
2355 break;
2356 case "clear":
2357 result = mInterface.clearUceRegistrationOverrideShell(subId);
2358 break;
2359 case "list":
2360 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2361 break;
2362 }
2363 } catch (RemoteException e) {
2364 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2365 getErrPrintWriter().println("Exception: " + e.getMessage());
2366 return -1;
2367 } catch (ServiceSpecificException sse) {
2368 // Reconstruct ImsException
2369 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2370 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2371 getErrPrintWriter().println("Exception: " + imsException);
2372 return -1;
2373 }
2374 if (result == null) {
2375 getErrPrintWriter().println("Service not available");
2376 return -1;
2377 }
2378 getOutPrintWriter().println(result);
2379 return 0;
2380 }
2381
2382 private int handleUceGetPidfXml() {
2383 int subId = getSubId("uce get-last-publish-pidf");
2384 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2385 return -1;
2386 }
2387
2388 String result;
2389 try {
2390 result = mInterface.getLastUcePidfXmlShell(subId);
2391 } catch (RemoteException e) {
2392 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2393 getErrPrintWriter().println("Exception: " + e.getMessage());
2394 return -1;
2395 } catch (ServiceSpecificException sse) {
2396 // Reconstruct ImsException
2397 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2398 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2399 getErrPrintWriter().println("Exception: " + imsException);
2400 return -1;
2401 }
2402 if (result == null) {
2403 getErrPrintWriter().println("Service not available");
2404 return -1;
2405 }
2406 getOutPrintWriter().println(result);
2407 return 0;
2408 }
2409
Hui Wang761a6682020-10-31 05:12:53 +00002410 private int handleSrcSetDeviceEnabledCommand() {
2411 String enabledStr = getNextArg();
2412 if (enabledStr == null) {
2413 return -1;
2414 }
2415
2416 try {
2417 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2418 if (VDBG) {
2419 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2420 }
2421 getOutPrintWriter().println("Done");
2422 } catch (NumberFormatException | RemoteException e) {
2423 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2424 getErrPrintWriter().println("Exception: " + e.getMessage());
2425 return -1;
2426 }
2427 return 0;
2428 }
2429
2430 private int handleSrcGetDeviceEnabledCommand() {
2431 boolean result = false;
2432 try {
2433 result = mInterface.getDeviceSingleRegistrationEnabled();
2434 } catch (RemoteException e) {
2435 return -1;
2436 }
2437 if (VDBG) {
2438 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2439 }
2440 getOutPrintWriter().println(result);
2441 return 0;
2442 }
2443
2444 private int handleSrcSetCarrierEnabledCommand() {
2445 //the release time value could be -1
2446 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2447 : SubscriptionManager.getDefaultSubscriptionId();
2448 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2449 return -1;
2450 }
2451
2452 String enabledStr = getNextArg();
2453 if (enabledStr == null) {
2454 return -1;
2455 }
2456
2457 try {
2458 boolean result =
2459 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2460 if (VDBG) {
2461 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2462 + enabledStr + ", result=" + result);
2463 }
2464 getOutPrintWriter().println(result);
2465 } catch (NumberFormatException | RemoteException e) {
2466 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2467 + enabledStr + ", error" + e.getMessage());
2468 getErrPrintWriter().println("Exception: " + e.getMessage());
2469 return -1;
2470 }
2471 return 0;
2472 }
2473
2474 private int handleSrcGetCarrierEnabledCommand() {
2475 int subId = getSubId("src get-carrier-enabled");
2476 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2477 return -1;
2478 }
2479
2480 boolean result = false;
2481 try {
2482 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2483 } catch (RemoteException e) {
2484 return -1;
2485 }
2486 if (VDBG) {
2487 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2488 }
2489 getOutPrintWriter().println(result);
2490 return 0;
2491 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002492
Hui Wangb647abe2021-02-26 09:33:38 -08002493 private int handleSrcSetFeatureValidationCommand() {
2494 //the release time value could be -1
2495 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2496 : SubscriptionManager.getDefaultSubscriptionId();
2497 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2498 return -1;
2499 }
2500
2501 String enabledStr = getNextArg();
2502 if (enabledStr == null) {
2503 return -1;
2504 }
2505
2506 try {
2507 boolean result =
2508 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2509 if (VDBG) {
2510 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2511 + enabledStr + ", result=" + result);
2512 }
2513 getOutPrintWriter().println(result);
2514 } catch (NumberFormatException | RemoteException e) {
2515 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2516 + enabledStr + ", error" + e.getMessage());
2517 getErrPrintWriter().println("Exception: " + e.getMessage());
2518 return -1;
2519 }
2520 return 0;
2521 }
2522
2523 private int handleSrcGetFeatureValidationCommand() {
2524 int subId = getSubId("src get-feature-validation");
2525 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2526 return -1;
2527 }
2528
2529 Boolean result = false;
2530 try {
2531 result = mInterface.getImsFeatureValidationOverride(subId);
2532 } catch (RemoteException e) {
2533 return -1;
2534 }
2535 if (VDBG) {
2536 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2537 }
2538 getOutPrintWriter().println(result);
2539 return 0;
2540 }
2541
2542
Hall Liuaa4211e2021-01-20 15:43:39 -08002543 private void onHelpCallComposer() {
2544 PrintWriter pw = getOutPrintWriter();
2545 pw.println("Call composer commands");
2546 pw.println(" callcomposer test-mode enable|disable|query");
2547 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2548 pw.println(" upload/download from carrier servers is disabled, and operations are");
2549 pw.println(" performed using emulated local files instead.");
2550 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2551 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2552 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002553 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2554 pw.println(" Enables or disables the user setting for call composer, as set by");
2555 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002556 }
2557
2558 private int handleCallComposerCommand() {
2559 String arg = getNextArg();
2560 if (arg == null) {
2561 onHelpCallComposer();
2562 return 0;
2563 }
2564
2565 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2566 "MODIFY_PHONE_STATE required for call composer shell cmds");
2567 switch (arg) {
2568 case CALL_COMPOSER_TEST_MODE: {
2569 String enabledStr = getNextArg();
2570 if (ENABLE.equals(enabledStr)) {
2571 CallComposerPictureManager.sTestMode = true;
2572 } else if (DISABLE.equals(enabledStr)) {
2573 CallComposerPictureManager.sTestMode = false;
2574 } else if (QUERY.equals(enabledStr)) {
2575 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2576 } else {
2577 onHelpCallComposer();
2578 return 1;
2579 }
2580 break;
2581 }
2582 case CALL_COMPOSER_SIMULATE_CALL: {
2583 int subscriptionId = Integer.valueOf(getNextArg());
2584 String uuidString = getNextArg();
2585 UUID uuid = UUID.fromString(uuidString);
2586 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2587 Binder.withCleanCallingIdentity(() -> {
2588 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2589 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2590 });
2591 try {
2592 Uri uri = storageUriFuture.get();
2593 getOutPrintWriter().println(String.valueOf(uri));
2594 } catch (Exception e) {
2595 throw new RuntimeException(e);
2596 }
2597 break;
2598 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002599 case CALL_COMPOSER_USER_SETTING: {
2600 try {
2601 int subscriptionId = Integer.valueOf(getNextArg());
2602 String enabledStr = getNextArg();
2603 if (ENABLE.equals(enabledStr)) {
2604 mInterface.setCallComposerStatus(subscriptionId,
2605 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2606 } else if (DISABLE.equals(enabledStr)) {
2607 mInterface.setCallComposerStatus(subscriptionId,
2608 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2609 } else if (QUERY.equals(enabledStr)) {
2610 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2611 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2612 } else {
2613 onHelpCallComposer();
2614 return 1;
2615 }
2616 } catch (RemoteException e) {
2617 e.printStackTrace(getOutPrintWriter());
2618 return 1;
2619 }
2620 break;
2621 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002622 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002623 return 0;
2624 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002625
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002626 private int handleHasCarrierPrivilegesCommand() {
2627 String packageName = getNextArgRequired();
2628
2629 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002630 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002631 try {
2632 hasCarrierPrivileges =
2633 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2634 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2635 } catch (RemoteException e) {
2636 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2637 getErrPrintWriter().println("Exception: " + e.getMessage());
2638 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002639 } finally {
2640 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002641 }
2642
2643 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002644 return 0;
2645 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002646
2647 private int handleAllowedNetworkTypesCommand(String command) {
2648 if (!checkShellUid()) {
2649 return -1;
2650 }
2651
2652 PrintWriter errPw = getErrPrintWriter();
2653 String tag = command + ": ";
2654 String opt;
2655 int subId = -1;
2656 Log.v(LOG_TAG, command + " start");
2657
2658 while ((opt = getNextOption()) != null) {
2659 if (opt.equals("-s")) {
2660 try {
2661 subId = slotStringToSubId(tag, getNextArgRequired());
2662 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2663 errPw.println(tag + "No valid subscription found.");
2664 return -1;
2665 }
2666 } catch (IllegalArgumentException e) {
2667 // Missing slot id
2668 errPw.println(tag + "SLOT_ID expected after -s.");
2669 return -1;
2670 }
2671 } else {
2672 errPw.println(tag + "Unknown option " + opt);
2673 return -1;
2674 }
2675 }
2676
2677 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2678 return handleGetAllowedNetworkTypesCommand(subId);
2679 }
2680 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2681 return handleSetAllowedNetworkTypesCommand(subId);
2682 }
2683 return -1;
2684 }
2685
2686 private int handleGetAllowedNetworkTypesCommand(int subId) {
2687 PrintWriter errPw = getErrPrintWriter();
2688
2689 long result = -1;
2690 try {
2691 if (mInterface != null) {
2692 result = mInterface.getAllowedNetworkTypesForReason(subId,
2693 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2694 } else {
2695 throw new IllegalStateException("telephony service is null.");
2696 }
2697 } catch (RemoteException e) {
2698 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2699 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2700 return -1;
2701 }
2702
2703 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2704 return 0;
2705 }
2706
2707 private int handleSetAllowedNetworkTypesCommand(int subId) {
2708 PrintWriter errPw = getErrPrintWriter();
2709
2710 String bitmaskString = getNextArg();
2711 if (TextUtils.isEmpty(bitmaskString)) {
2712 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2713 return -1;
2714 }
2715 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2716 if (allowedNetworkTypes < 0) {
2717 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2718 return -1;
2719 }
2720 boolean result = false;
2721 try {
2722 if (mInterface != null) {
2723 result = mInterface.setAllowedNetworkTypesForReason(subId,
2724 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2725 } else {
2726 throw new IllegalStateException("telephony service is null.");
2727 }
2728 } catch (RemoteException e) {
2729 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2730 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2731 return -1;
2732 }
2733
2734 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2735 if (result) {
2736 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2737 }
2738 getOutPrintWriter().println(resultMessage);
2739 return 0;
2740 }
2741
2742 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2743 if (TextUtils.isEmpty(bitmaskString)) {
2744 return -1;
2745 }
2746 if (VDBG) {
2747 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2748 + ", length: " + bitmaskString.length());
2749 }
2750 try {
2751 return Long.parseLong(bitmaskString, 2);
2752 } catch (NumberFormatException e) {
2753 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2754 return -1;
2755 }
2756 }
Jack Yu4c0a5502021-12-03 23:58:26 -08002757
2758 private int handleGetDataMode() {
2759 if (!checkShellUid()) {
2760 return -1;
2761 }
2762
2763 boolean newDataStackEnabled = false;
2764 try {
2765 newDataStackEnabled = mInterface.isUsingNewDataStack();
2766 } catch (RemoteException e) {
2767 getOutPrintWriter().println("Something went wrong. " + e);
2768 return -1;
2769 }
2770
2771 getOutPrintWriter().println("Telephony new data stack is "
2772 + (newDataStackEnabled ? "enabled." : "disabled."));
2773
2774 boolean configEnabled = Boolean.parseBoolean(DeviceConfig.getProperty(
2775 DeviceConfig.NAMESPACE_TELEPHONY, "new_telephony_data_enabled"));
2776 if (configEnabled != newDataStackEnabled) {
2777 getOutPrintWriter().println("The config has been "
2778 + (configEnabled ? "enabled" : "disabled") + ". Need to reboot the device.");
2779 } else {
2780 getOutPrintWriter().println("Run the following command to "
2781 + (configEnabled ? "disable" : "enable") + " the new telephony data stack.");
2782 getOutPrintWriter().println("adb root && adb shell device_config put telephony "
2783 + "new_telephony_data_enabled " + (configEnabled ? "false" : "true")
2784 + " && adb reboot");
2785 }
2786 return 0;
2787 }
jimsun3b9ccac2021-10-26 15:01:23 +08002788
2789 private int handleRadioSetModemServiceCommand() {
2790 PrintWriter errPw = getErrPrintWriter();
2791 String serviceName = null;
2792
2793 String opt;
2794 while ((opt = getNextOption()) != null) {
2795 switch (opt) {
2796 case "-s": {
2797 serviceName = getNextArgRequired();
2798 break;
2799 }
2800 }
2801 }
2802
2803 try {
2804 boolean result = mInterface.setModemService(serviceName);
2805 if (VDBG) {
2806 Log.v(LOG_TAG,
2807 "RadioSetModemService " + serviceName + ", result = " + result);
2808 }
2809 getOutPrintWriter().println(result);
2810 } catch (RemoteException e) {
2811 Log.w(LOG_TAG,
2812 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2813 errPw.println("Exception: " + e.getMessage());
2814 return -1;
2815 }
2816 return 0;
2817 }
2818
2819 private int handleRadioGetModemServiceCommand() {
2820 PrintWriter errPw = getErrPrintWriter();
2821 String result;
2822
2823 try {
2824 result = mInterface.getModemService();
2825 getOutPrintWriter().println(result);
2826 } catch (RemoteException e) {
2827 errPw.println("Exception: " + e.getMessage());
2828 return -1;
2829 }
2830 if (VDBG) {
2831 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2832 }
2833 return 0;
2834 }
2835
2836 private int handleRadioCommand() {
2837 String arg = getNextArg();
2838 if (arg == null) {
2839 onHelpRadio();
2840 return 0;
2841 }
2842
2843 switch (arg) {
2844 case RADIO_SET_MODEM_SERVICE:
2845 return handleRadioSetModemServiceCommand();
2846
2847 case RADIO_GET_MODEM_SERVICE:
2848 return handleRadioGetModemServiceCommand();
2849 }
2850
2851 return -1;
2852 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002853}