blob: d2a3c40b6b0380ec4926db30dcc4767e80410305 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000031import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070032import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070033import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010034import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070035import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000037import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070038import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080039import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000040import android.telephony.ims.ImsException;
41import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080042import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080043import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000044import android.util.ArrayMap;
45import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070046import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070047import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
Brad Ebinger14d467f2021-02-12 06:18:28 +000049import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080051import com.android.internal.telephony.Phone;
52import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080053import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080054import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080055import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080056import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080057import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070058
59import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080060import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000061import java.util.Arrays;
62import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010063import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080064import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010065import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010067import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080068import java.util.UUID;
69import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070
71/**
72 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
73 * permission checks have been done before onCommand was called. Make sure any commands processed
74 * here also contain the appropriate permissions checks.
75 */
76
Hall Liua1548bd2019-12-24 14:14:12 -080077public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070078
79 private static final String LOG_TAG = "TelephonyShellCommand";
80 // Don't commit with this true.
81 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070082 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
Hall Liuaa4211e2021-01-20 15:43:39 -080084 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080086 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080087 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080088 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070089 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000090 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000091 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010092 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080093 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080094 private static final String ENABLE = "enable";
95 private static final String DISABLE = "disable";
96 private static final String QUERY = "query";
97
Hall Liu7135e502021-02-04 16:58:17 -080098 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800100 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800101
Brad Ebinger999d3302020-11-25 14:31:39 -0800102 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
103 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
104 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700105 // Used to disable or enable processing of conference event package data from the network.
106 // This is handy for testing scenarios where CEP data does not exist on a network which does
107 // support CEP data.
108 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700109
Hall Liud892bec2018-11-30 14:51:45 -0800110 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800111 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100113 private static final String CC_GET_VALUE = "get-value";
114 private static final String CC_SET_VALUE = "set-value";
115 private static final String CC_CLEAR_VALUES = "clear-values";
116
Hui Wang641e81c2020-10-12 12:14:23 -0700117 private static final String GBA_SUBCOMMAND = "gba";
118 private static final String GBA_SET_SERVICE = "set-service";
119 private static final String GBA_GET_SERVICE = "get-service";
120 private static final String GBA_SET_RELEASE_TIME = "set-release";
121 private static final String GBA_GET_RELEASE_TIME = "get-release";
122
Hui Wang761a6682020-10-31 05:12:53 +0000123 private static final String SINGLE_REGISTATION_CONFIG = "src";
124 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
125 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
126 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
127 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800128 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
129 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800130 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
131 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000132
Tyler Gunn92479152021-01-20 16:30:10 -0800133 private static final String D2D_SUBCOMMAND = "d2d";
134 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800135 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800136
Nazanin014f41e2021-05-06 17:26:31 -0700137 private static final String BARRING_SUBCOMMAND = "barring";
138 private static final String BARRING_SEND_INFO = "send";
139
James.cf Linbcdf8b32021-01-14 16:44:13 +0800140 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800141 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800142 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800143 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
144 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000145 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
146 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800147 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
148 "remove-request-disallowed-status";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800149
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800150 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
151 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
152
Jordan Liu0ccee222021-04-27 11:55:13 -0700153 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
154 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
155
Jack Nudelman644b91a2021-03-12 14:09:48 -0800156 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
157 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
158 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
159
SongFerngWang98dd5992021-05-13 17:50:00 +0800160 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
161 "get-allowed-network-types-for-users";
162 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
163 "set-allowed-network-types-for-users";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700164 // Take advantage of existing methods that already contain permissions checks when possible.
165 private final ITelephony mInterface;
166
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100167 private SubscriptionManager mSubscriptionManager;
168 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700169 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700170 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100171
172 private enum CcType {
173 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
174 STRING_ARRAY, UNKNOWN
175 }
176
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100177 private class CcOptionParseResult {
178 public int mSubId;
179 public boolean mPersistent;
180 }
181
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100182 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
183 // keys by looking at the end of the string which usually tells the type.
184 // For instance: "xxxx_string", "xxxx_string_array", etc.
185 // The carrier config keys in this map does not follow this convention. It is therefore not
186 // possible to infer the type for these keys by looking at the string.
187 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
188 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
189 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
190 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
191 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
192 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
193 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
194 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
195 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
196 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
197 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
198 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
199 CcType.STRING);
200 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
201 CcType.STRING_ARRAY);
202 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
203 CcType.STRING_ARRAY);
204 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
205 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
206 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
207 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
208 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
209 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
210 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
211 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
212 }
213 };
214
Brad Ebinger14d467f2021-02-12 06:18:28 +0000215 /**
216 * Map from a shorthand string to the feature tags required in registration required in order
217 * for the RCS feature to be considered "capable".
218 */
219 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
220 static {
221 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
222 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
223 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
224 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
225 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
226 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
227 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
228 FeatureTags.FEATURE_TAG_VIDEO)));
229 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
230 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
231 map.put("call_comp",
232 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
233 map.put("call_comp_mmtel",
234 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
235 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
236 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
237 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
238 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
239 // version
240 map.put("chatbot", new ArraySet<>(Arrays.asList(
241 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
242 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
243 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
244 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
245 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
246 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
247 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
248 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
249 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
250 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
251 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
252 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
253 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
254 }
255
256
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100257 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700258 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100259 mCarrierConfigManager =
260 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
261 mSubscriptionManager = (SubscriptionManager)
262 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700263 mTelephonyRegistryManager = (TelephonyRegistryManager)
264 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700265 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700266 }
267
268 @Override
269 public int onCommand(String cmd) {
270 if (cmd == null) {
271 return handleDefaultCommands(null);
272 }
273
274 switch (cmd) {
275 case IMS_SUBCOMMAND: {
276 return handleImsCommand();
277 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800278 case RCS_UCE_COMMAND:
279 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800280 case NUMBER_VERIFICATION_SUBCOMMAND:
281 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800282 case EMERGENCY_CALLBACK_MODE:
283 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800284 case EMERGENCY_NUMBER_TEST_MODE:
285 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100286 case CARRIER_CONFIG_SUBCOMMAND: {
287 return handleCcCommand();
288 }
Shuo Qianf5125122019-12-16 17:03:07 -0800289 case DATA_TEST_MODE:
290 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700291 case END_BLOCK_SUPPRESSION:
292 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700293 case GBA_SUBCOMMAND:
294 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800295 case D2D_SUBCOMMAND:
296 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700297 case BARRING_SUBCOMMAND:
298 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000299 case SINGLE_REGISTATION_CONFIG:
300 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000301 case RESTART_MODEM:
302 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800303 case CALL_COMPOSER_SUBCOMMAND:
304 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000305 case UNATTENDED_REBOOT:
306 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800307 case HAS_CARRIER_PRIVILEGES_COMMAND:
308 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800309 case THERMAL_MITIGATION_COMMAND:
310 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700311 case DISABLE_PHYSICAL_SUBSCRIPTION:
312 return handleEnablePhysicalSubscription(false);
313 case ENABLE_PHYSICAL_SUBSCRIPTION:
314 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800315 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
316 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
317 return handleAllowedNetworkTypesCommand(cmd);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700318 default: {
319 return handleDefaultCommands(cmd);
320 }
321 }
322 }
323
324 @Override
325 public void onHelp() {
326 PrintWriter pw = getOutPrintWriter();
327 pw.println("Telephony Commands:");
328 pw.println(" help");
329 pw.println(" Print this help text.");
330 pw.println(" ims");
331 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800332 pw.println(" uce");
333 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800334 pw.println(" emergency-number-test-mode");
335 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700336 pw.println(" end-block-suppression");
337 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800338 pw.println(" data");
339 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100340 pw.println(" cc");
341 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700342 pw.println(" gba");
343 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000344 pw.println(" src");
345 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000346 pw.println(" restart-modem");
347 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000348 pw.println(" unattended-reboot");
349 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800350 pw.println(" has-carrier-privileges [package]");
351 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800352 pw.println(" get-allowed-network-types-for-users");
353 pw.println(" Get the Allowed Network Types.");
354 pw.println(" set-allowed-network-types-for-users");
355 pw.println(" Set the Allowed Network Types.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700356 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800357 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800358 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700359 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800360 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100361 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700362 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000363 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800364 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700365 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800366 onHelpAllowedNetworkTypes();
Tyler Gunn92479152021-01-20 16:30:10 -0800367 }
368
369 private void onHelpD2D() {
370 PrintWriter pw = getOutPrintWriter();
371 pw.println("D2D Comms Commands:");
372 pw.println(" d2d send TYPE VALUE");
373 pw.println(" Sends a D2D message of specified type and value.");
374 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
375 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
376 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
377 MESSAGE_CALL_AUDIO_CODEC));
378 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
379 + Communicator.messageToString(
380 MESSAGE_DEVICE_BATTERY_STATE));
381 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
382 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800383 pw.println(" d2d transport TYPE");
384 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
385 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700386 }
387
Nazanin014f41e2021-05-06 17:26:31 -0700388 private void onHelpBarring() {
389 PrintWriter pw = getOutPrintWriter();
390 pw.println("Barring Commands:");
391 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
392 + " -t CONDITIONAL_BARRING_TIME_SECS");
393 pw.println(" Notifies of a barring info change for the specified slot id.");
394 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
395 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
396 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
397 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
398 }
399
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700400 private void onHelpIms() {
401 PrintWriter pw = getOutPrintWriter();
402 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800403 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700404 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
405 pw.println(" ImsService. Options are:");
406 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
407 pw.println(" is specified, it will choose the default voice SIM slot.");
408 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
409 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800410 pw.println(" -f: Set the feature that this override if for, if no option is");
411 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700412 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
413 pw.println(" Gets the package name of the currently defined ImsService.");
414 pw.println(" Options are:");
415 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
416 pw.println(" is specified, it will choose the default voice SIM slot.");
417 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000418 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800419 pw.println(" -f: The feature type that the query will be requested for. If none is");
420 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800421 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
422 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
423 pw.println(" configuration overrides. Options are:");
424 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
425 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700426 pw.println(" ims enable [-s SLOT_ID]");
427 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
428 pw.println(" if none is specified.");
429 pw.println(" ims disable [-s SLOT_ID]");
430 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
431 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700432 pw.println(" ims conference-event-package [enable/disable]");
433 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700434 }
435
James.cf Linbcdf8b32021-01-14 16:44:13 +0800436 private void onHelpUce() {
437 PrintWriter pw = getOutPrintWriter();
438 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800439 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
440 pw.println(" Get the EAB contacts from the EAB database.");
441 pw.println(" Options are:");
442 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
443 pw.println(" Expected output format :");
444 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800445 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
446 pw.println(" Remove the EAB contacts from the EAB database.");
447 pw.println(" Options are:");
448 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
449 pw.println(" is specified, it will choose the default voice SIM slot.");
450 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800451 pw.println(" uce get-device-enabled");
452 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
453 pw.println(" uce set-device-enabled true|false");
454 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
455 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000456 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
457 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
458 pw.println(" Options are:");
459 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
460 pw.println(" is specified, it will choose the default voice SIM slot.");
461 pw.println(" add [CAPABILITY]: add a new capability");
462 pw.println(" remove [CAPABILITY]: remove a capability");
463 pw.println(" clear: clear all capability overrides");
464 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
465 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
466 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
467 pw.println(" chatbot_sa, chatbot_role] as well as full length");
468 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
469 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
470 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
471 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800472 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
473 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800474 }
475
Hall Liud892bec2018-11-30 14:51:45 -0800476 private void onHelpNumberVerification() {
477 PrintWriter pw = getOutPrintWriter();
478 pw.println("Number verification commands");
479 pw.println(" numverify override-package PACKAGE_NAME;");
480 pw.println(" Set the authorized package for number verification.");
481 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800482 pw.println(" numverify fake-call NUMBER;");
483 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
484 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800485 }
486
Jack Nudelman644b91a2021-03-12 14:09:48 -0800487 private void onHelpThermalMitigation() {
488 PrintWriter pw = getOutPrintWriter();
489 pw.println("Thermal mitigation commands");
490 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
491 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
492 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
493 pw.println(" Remove the package from one of the authorized packages for thermal "
494 + "mitigation.");
495 }
496
Jordan Liu0ccee222021-04-27 11:55:13 -0700497 private void onHelpDisableOrEnablePhysicalSubscription() {
498 PrintWriter pw = getOutPrintWriter();
499 pw.println("Disable or enable a physical subscription");
500 pw.println(" disable-physical-subscription SUB_ID");
501 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
502 pw.println(" enable-physical-subscription SUB_ID");
503 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
504 }
505
Shuo Qianf5125122019-12-16 17:03:07 -0800506 private void onHelpDataTestMode() {
507 PrintWriter pw = getOutPrintWriter();
508 pw.println("Mobile Data Test Mode Commands:");
509 pw.println(" data enable: enable mobile data connectivity");
510 pw.println(" data disable: disable mobile data connectivity");
511 }
512
sqian9d4df8b2019-01-15 18:32:07 -0800513 private void onHelpEmergencyNumber() {
514 PrintWriter pw = getOutPrintWriter();
515 pw.println("Emergency Number Test Mode Commands:");
516 pw.println(" emergency-number-test-mode ");
517 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
518 + " the test mode");
519 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700520 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800521 pw.println(" -c: clear the emergency number list in the test mode.");
522 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700523 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800524 pw.println(" -p: get the full emergency number list in the test mode.");
525 }
526
Shuo Qian489d9282020-07-09 11:30:03 -0700527 private void onHelpEndBlockSupperssion() {
528 PrintWriter pw = getOutPrintWriter();
529 pw.println("End Block Suppression command:");
530 pw.println(" end-block-suppression: disable suppressing blocking by contact");
531 pw.println(" with emergency services.");
532 }
533
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100534 private void onHelpCc() {
535 PrintWriter pw = getOutPrintWriter();
536 pw.println("Carrier Config Commands:");
537 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
538 pw.println(" Print carrier config values.");
539 pw.println(" Options are:");
540 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
541 pw.println(" is specified, it will choose the default voice SIM slot.");
542 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
543 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100544 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100545 pw.println(" Set carrier config KEY to NEW_VALUE.");
546 pw.println(" Options are:");
547 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
548 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100549 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100550 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
551 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
552 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
553 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
554 pw.println(" cc clear-values [-s SLOT_ID]");
555 pw.println(" Clear all carrier override values that has previously been set");
556 pw.println(" with set-value");
557 pw.println(" Options are:");
558 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
559 pw.println(" is specified, it will choose the default voice SIM slot.");
560 }
561
Hui Wang641e81c2020-10-12 12:14:23 -0700562 private void onHelpGba() {
563 PrintWriter pw = getOutPrintWriter();
564 pw.println("Gba Commands:");
565 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
566 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
567 pw.println(" Options are:");
568 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
569 pw.println(" is specified, it will choose the default voice SIM slot.");
570 pw.println(" gba get-service [-s SLOT_ID]");
571 pw.println(" Gets the package name of the currently defined GbaService.");
572 pw.println(" Options are:");
573 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
574 pw.println(" is specified, it will choose the default voice SIM slot.");
575 pw.println(" gba set-release [-s SLOT_ID] n");
576 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
577 pw.println(" Do not release/unbind if n is -1.");
578 pw.println(" Options are:");
579 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
580 pw.println(" is specified, it will choose the default voice SIM slot.");
581 pw.println(" gba get-release [-s SLOT_ID]");
582 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
583 pw.println(" Options are:");
584 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
585 pw.println(" is specified, it will choose the default voice SIM slot.");
586 }
587
Hui Wang761a6682020-10-31 05:12:53 +0000588 private void onHelpSrc() {
589 PrintWriter pw = getOutPrintWriter();
590 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800591 pw.println(" src set-test-enabled true|false");
592 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
593 pw.println(" The value could be true, false, or null(undefined).");
594 pw.println(" src get-test-enabled");
595 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000596 pw.println(" src set-device-enabled true|false|null");
597 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
598 pw.println(" The value could be true, false, or null(undefined).");
599 pw.println(" src get-device-enabled");
600 pw.println(" Gets the device config for RCS VoLTE single registration.");
601 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
602 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
603 pw.println(" The value could be true, false, or null(undefined).");
604 pw.println(" Options are:");
605 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
606 pw.println(" is specified, it will choose the default voice SIM slot.");
607 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
608 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
609 pw.println(" Options are:");
610 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
611 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800612 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
613 pw.println(" Sets ims feature validation result.");
614 pw.println(" The value could be true, false, or null(undefined).");
615 pw.println(" Options are:");
616 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
617 pw.println(" is specified, it will choose the default voice SIM slot.");
618 pw.println(" src get-feature-validation [-s SLOT_ID]");
619 pw.println(" Gets ims feature validation override value.");
620 pw.println(" Options are:");
621 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
622 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000623 }
624
SongFerngWang98dd5992021-05-13 17:50:00 +0800625 private void onHelpAllowedNetworkTypes() {
626 PrintWriter pw = getOutPrintWriter();
627 pw.println("Allowed Network Types Commands:");
628 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
629 pw.println(" Print allowed network types value.");
630 pw.println(" Options are:");
631 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
632 pw.println(" option is specified, it will choose the default voice SIM slot.");
633 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
634 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
635 pw.println(" Options are:");
636 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
637 pw.println(" option is specified, it will choose the default voice SIM slot.");
638 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
639 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
640 pw.println(" at TelephonyManager.java");
641 pw.println(" For example:");
642 pw.println(" NR only : 10000000000000000000");
643 pw.println(" NR|LTE : 11000001000000000000");
644 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
645 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
646 pw.println(" LTE only : 01000001000000000000");
647 }
648
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700649 private int handleImsCommand() {
650 String arg = getNextArg();
651 if (arg == null) {
652 onHelpIms();
653 return 0;
654 }
655
656 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800657 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700658 return handleImsSetServiceCommand();
659 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800660 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700661 return handleImsGetServiceCommand();
662 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800663 case IMS_CLEAR_SERVICE_OVERRIDE: {
664 return handleImsClearCarrierServiceCommand();
665 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800666 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700667 return handleEnableIms();
668 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800669 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700670 return handleDisableIms();
671 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700672 case IMS_CEP: {
673 return handleCepChange();
674 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700675 }
676
677 return -1;
678 }
679
Shuo Qianf5125122019-12-16 17:03:07 -0800680 private int handleDataTestModeCommand() {
681 PrintWriter errPw = getErrPrintWriter();
682 String arg = getNextArgRequired();
683 if (arg == null) {
684 onHelpDataTestMode();
685 return 0;
686 }
687 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800688 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800689 try {
690 mInterface.enableDataConnectivity();
691 } catch (RemoteException ex) {
692 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
693 errPw.println("Exception: " + ex.getMessage());
694 return -1;
695 }
696 break;
697 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800698 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800699 try {
700 mInterface.disableDataConnectivity();
701 } catch (RemoteException ex) {
702 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
703 errPw.println("Exception: " + ex.getMessage());
704 return -1;
705 }
706 break;
707 }
708 default:
709 onHelpDataTestMode();
710 break;
711 }
712 return 0;
713 }
714
Shuo Qianccbaf742021-02-22 18:32:21 -0800715 private int handleEmergencyCallbackModeCommand() {
716 PrintWriter errPw = getErrPrintWriter();
717 try {
718 mInterface.startEmergencyCallbackMode();
719 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
720 } catch (RemoteException ex) {
721 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
722 errPw.println("Exception: " + ex.getMessage());
723 return -1;
724 }
725 return 0;
726 }
727
sqian9d4df8b2019-01-15 18:32:07 -0800728 private int handleEmergencyNumberTestModeCommand() {
729 PrintWriter errPw = getErrPrintWriter();
730 String opt = getNextOption();
731 if (opt == null) {
732 onHelpEmergencyNumber();
733 return 0;
734 }
735
736 switch (opt) {
737 case "-a": {
738 String emergencyNumberCmd = getNextArgRequired();
739 if (emergencyNumberCmd == null
740 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700741 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800742 + " to be specified after -a in the command ");
743 return -1;
744 }
745 try {
746 mInterface.updateEmergencyNumberListTestMode(
747 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
748 new EmergencyNumber(emergencyNumberCmd, "", "",
749 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
750 new ArrayList<String>(),
751 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
752 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
753 } catch (RemoteException ex) {
754 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
755 + ", error " + ex.getMessage());
756 errPw.println("Exception: " + ex.getMessage());
757 return -1;
758 }
759 break;
760 }
761 case "-c": {
762 try {
763 mInterface.updateEmergencyNumberListTestMode(
764 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
765 } catch (RemoteException ex) {
766 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
767 errPw.println("Exception: " + ex.getMessage());
768 return -1;
769 }
770 break;
771 }
772 case "-r": {
773 String emergencyNumberCmd = getNextArgRequired();
774 if (emergencyNumberCmd == null
775 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700776 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800777 + " to be specified after -r in the command ");
778 return -1;
779 }
780 try {
781 mInterface.updateEmergencyNumberListTestMode(
782 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
783 new EmergencyNumber(emergencyNumberCmd, "", "",
784 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
785 new ArrayList<String>(),
786 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
787 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
788 } catch (RemoteException ex) {
789 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
790 + ", error " + ex.getMessage());
791 errPw.println("Exception: " + ex.getMessage());
792 return -1;
793 }
794 break;
795 }
796 case "-p": {
797 try {
798 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
799 } catch (RemoteException ex) {
800 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
801 errPw.println("Exception: " + ex.getMessage());
802 return -1;
803 }
804 break;
805 }
806 default:
807 onHelpEmergencyNumber();
808 break;
809 }
810 return 0;
811 }
812
Hall Liud892bec2018-11-30 14:51:45 -0800813 private int handleNumberVerificationCommand() {
814 String arg = getNextArg();
815 if (arg == null) {
816 onHelpNumberVerification();
817 return 0;
818 }
819
Hall Liuca5af3a2018-12-04 16:58:23 -0800820 if (!checkShellUid()) {
821 return -1;
822 }
823
Hall Liud892bec2018-11-30 14:51:45 -0800824 switch (arg) {
825 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800826 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
827 return 0;
828 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800829 case NUMBER_VERIFICATION_FAKE_CALL: {
830 boolean val = NumberVerificationManager.getInstance()
831 .checkIncomingCall(getNextArg());
832 getOutPrintWriter().println(val ? "1" : "0");
833 return 0;
834 }
Hall Liud892bec2018-11-30 14:51:45 -0800835 }
836
837 return -1;
838 }
839
Jordan Liu0ccee222021-04-27 11:55:13 -0700840 private boolean subIsEsim(int subId) {
841 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
842 if (info != null) {
843 return info.isEmbedded();
844 }
845 return false;
846 }
847
848 private int handleEnablePhysicalSubscription(boolean enable) {
849 PrintWriter errPw = getErrPrintWriter();
850 int subId = 0;
851 try {
852 subId = Integer.parseInt(getNextArgRequired());
853 } catch (NumberFormatException e) {
854 errPw.println((enable ? "enable" : "disable")
855 + "-physical-subscription requires an integer as a subId.");
856 return -1;
857 }
858 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
859 // non user build.
860 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
861 errPw.println("cc: Permission denied.");
862 return -1;
863 }
864 // Verify that the subId represents a physical sub
865 if (subIsEsim(subId)) {
866 errPw.println("SubId " + subId + " is not for a physical subscription");
867 return -1;
868 }
869 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
870 + " physical subscription with subId=" + subId);
871 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
872 return 0;
873 }
874
Jack Nudelman644b91a2021-03-12 14:09:48 -0800875 private int handleThermalMitigationCommand() {
876 String arg = getNextArg();
877 String packageName = getNextArg();
878 if (arg == null || packageName == null) {
879 onHelpThermalMitigation();
880 return 0;
881 }
882
883 if (!checkShellUid()) {
884 return -1;
885 }
886
887 switch (arg) {
888 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
889 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
890 return 0;
891 }
892 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
893 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
894 mContext);
895 return 0;
896 }
897 default:
898 onHelpThermalMitigation();
899 }
900
901 return -1;
902
903 }
904
Tyler Gunn92479152021-01-20 16:30:10 -0800905 private int handleD2dCommand() {
906 String arg = getNextArg();
907 if (arg == null) {
908 onHelpD2D();
909 return 0;
910 }
911
912 switch (arg) {
913 case D2D_SEND: {
914 return handleD2dSendCommand();
915 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800916 case D2D_TRANSPORT: {
917 return handleD2dTransportCommand();
918 }
Tyler Gunn92479152021-01-20 16:30:10 -0800919 }
920
921 return -1;
922 }
923
924 private int handleD2dSendCommand() {
925 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800926 int messageType = -1;
927 int messageValue = -1;
928
Tyler Gunn92479152021-01-20 16:30:10 -0800929 String arg = getNextArg();
930 if (arg == null) {
931 onHelpD2D();
932 return 0;
933 }
934 try {
935 messageType = Integer.parseInt(arg);
936 } catch (NumberFormatException e) {
937 errPw.println("message type must be a valid integer");
938 return -1;
939 }
940
941 arg = getNextArg();
942 if (arg == null) {
943 onHelpD2D();
944 return 0;
945 }
946 try {
947 messageValue = Integer.parseInt(arg);
948 } catch (NumberFormatException e) {
949 errPw.println("message value must be a valid integer");
950 return -1;
951 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800952
Tyler Gunn92479152021-01-20 16:30:10 -0800953 try {
954 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
955 } catch (RemoteException e) {
956 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
957 errPw.println("Exception: " + e.getMessage());
958 return -1;
959 }
960
961 return 0;
962 }
963
Tyler Gunnbabbda02021-02-10 11:05:02 -0800964 private int handleD2dTransportCommand() {
965 PrintWriter errPw = getErrPrintWriter();
966
967 String arg = getNextArg();
968 if (arg == null) {
969 onHelpD2D();
970 return 0;
971 }
972
973 try {
974 mInterface.setActiveDeviceToDeviceTransport(arg);
975 } catch (RemoteException e) {
976 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
977 errPw.println("Exception: " + e.getMessage());
978 return -1;
979 }
980 return 0;
981 }
Nazanin014f41e2021-05-06 17:26:31 -0700982 private int handleBarringCommand() {
983 String arg = getNextArg();
984 if (arg == null) {
985 onHelpBarring();
986 return 0;
987 }
988
989 switch (arg) {
990 case BARRING_SEND_INFO: {
991 return handleBarringSendCommand();
992 }
993 }
994 return -1;
995 }
996
997 private int handleBarringSendCommand() {
998 PrintWriter errPw = getErrPrintWriter();
999 int slotId = getDefaultSlot();
1000 int subId = SubscriptionManager.getSubId(slotId)[0];
1001 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1002 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1003 boolean isConditionallyBarred = false;
1004 int conditionalBarringTimeSeconds = 0;
1005
1006 String opt;
1007 while ((opt = getNextOption()) != null) {
1008 switch (opt) {
1009 case "-s": {
1010 try {
1011 slotId = Integer.parseInt(getNextArgRequired());
1012 subId = SubscriptionManager.getSubId(slotId)[0];
1013 } catch (NumberFormatException e) {
1014 errPw.println("barring send requires an integer as a SLOT_ID.");
1015 return -1;
1016 }
1017 break;
1018 }
1019 case "-b": {
1020 try {
1021 barringType = Integer.parseInt(getNextArgRequired());
1022 if (barringType < -1 || barringType > 2) {
1023 throw new NumberFormatException();
1024 }
1025
1026 } catch (NumberFormatException e) {
1027 errPw.println("barring send requires an integer in range [-1,2] as "
1028 + "a BARRING_TYPE.");
1029 return -1;
1030 }
1031 break;
1032 }
1033 case "-c": {
1034 try {
1035 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1036 } catch (Exception e) {
1037 errPw.println("barring send requires a boolean after -c indicating"
1038 + " conditional barring");
1039 return -1;
1040 }
1041 break;
1042 }
1043 case "-t": {
1044 try {
1045 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1046 } catch (NumberFormatException e) {
1047 errPw.println("barring send requires an integer for time of barring"
1048 + " in seconds after -t for conditional barring");
1049 return -1;
1050 }
1051 break;
1052 }
1053 }
1054 }
1055 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1056 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1057 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1058 barringServiceInfos.append(0, bsi);
1059 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1060 try {
1061 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1062 } catch (Exception e) {
1063 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1064 errPw.println("Exception: " + e.getMessage());
1065 return -1;
1066 }
1067 return 0;
1068 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001069
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001070 // ims set-ims-service
1071 private int handleImsSetServiceCommand() {
1072 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001073 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001074 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001075 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001076
1077 String opt;
1078 while ((opt = getNextOption()) != null) {
1079 switch (opt) {
1080 case "-s": {
1081 try {
1082 slotId = Integer.parseInt(getNextArgRequired());
1083 } catch (NumberFormatException e) {
1084 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1085 return -1;
1086 }
1087 break;
1088 }
1089 case "-c": {
1090 isCarrierService = true;
1091 break;
1092 }
1093 case "-d": {
1094 isCarrierService = false;
1095 break;
1096 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001097 case "-f": {
1098 String featureString = getNextArgRequired();
1099 String[] features = featureString.split(",");
1100 for (int i = 0; i < features.length; i++) {
1101 try {
1102 Integer result = Integer.parseInt(features[i]);
1103 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1104 || result >= ImsFeature.FEATURE_MAX) {
1105 errPw.println("ims set-ims-service -f " + result
1106 + " is an invalid feature.");
1107 return -1;
1108 }
1109 featuresList.add(result);
1110 } catch (NumberFormatException e) {
1111 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1112 + " as an integer.");
1113 return -1;
1114 }
1115 }
1116 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001117 }
1118 }
1119 // Mandatory param, either -c or -d
1120 if (isCarrierService == null) {
1121 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1122 return -1;
1123 }
1124
1125 String packageName = getNextArg();
1126
1127 try {
1128 if (packageName == null) {
1129 packageName = "";
1130 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001131 int[] featureArray = new int[featuresList.size()];
1132 for (int i = 0; i < featuresList.size(); i++) {
1133 featureArray[i] = featuresList.get(i);
1134 }
1135 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1136 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001137 if (VDBG) {
1138 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001139 + (isCarrierService ? "-c " : "-d ")
1140 + "-f " + featuresList + " "
1141 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001142 }
1143 getOutPrintWriter().println(result);
1144 } catch (RemoteException e) {
1145 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001146 + (isCarrierService ? "-c " : "-d ")
1147 + "-f " + featuresList + " "
1148 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001149 errPw.println("Exception: " + e.getMessage());
1150 return -1;
1151 }
1152 return 0;
1153 }
1154
Brad Ebinger999d3302020-11-25 14:31:39 -08001155 // ims clear-ims-service-override
1156 private int handleImsClearCarrierServiceCommand() {
1157 PrintWriter errPw = getErrPrintWriter();
1158 int slotId = getDefaultSlot();
1159
1160 String opt;
1161 while ((opt = getNextOption()) != null) {
1162 switch (opt) {
1163 case "-s": {
1164 try {
1165 slotId = Integer.parseInt(getNextArgRequired());
1166 } catch (NumberFormatException e) {
1167 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1168 return -1;
1169 }
1170 break;
1171 }
1172 }
1173 }
1174
1175 try {
1176 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1177 if (VDBG) {
1178 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1179 + ", result=" + result);
1180 }
1181 getOutPrintWriter().println(result);
1182 } catch (RemoteException e) {
1183 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1184 + ", error" + e.getMessage());
1185 errPw.println("Exception: " + e.getMessage());
1186 return -1;
1187 }
1188 return 0;
1189 }
1190
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001191 // ims get-ims-service
1192 private int handleImsGetServiceCommand() {
1193 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001194 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001195 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001196 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001197
1198 String opt;
1199 while ((opt = getNextOption()) != null) {
1200 switch (opt) {
1201 case "-s": {
1202 try {
1203 slotId = Integer.parseInt(getNextArgRequired());
1204 } catch (NumberFormatException e) {
1205 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1206 return -1;
1207 }
1208 break;
1209 }
1210 case "-c": {
1211 isCarrierService = true;
1212 break;
1213 }
1214 case "-d": {
1215 isCarrierService = false;
1216 break;
1217 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001218 case "-f": {
1219 try {
1220 featureType = Integer.parseInt(getNextArg());
1221 } catch (NumberFormatException e) {
1222 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1223 return -1;
1224 }
1225 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1226 || featureType >= ImsFeature.FEATURE_MAX) {
1227 errPw.println("ims get-ims-service -f invalid feature.");
1228 return -1;
1229 }
1230 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001231 }
1232 }
1233 // Mandatory param, either -c or -d
1234 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001235 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001236 return -1;
1237 }
1238
1239 String result;
1240 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001241 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001242 } catch (RemoteException e) {
1243 return -1;
1244 }
1245 if (VDBG) {
1246 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001247 + (isCarrierService ? "-c " : "-d ")
1248 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1249 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001250 }
1251 getOutPrintWriter().println(result);
1252 return 0;
1253 }
1254
1255 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001256 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001257 String opt;
1258 while ((opt = getNextOption()) != null) {
1259 switch (opt) {
1260 case "-s": {
1261 try {
1262 slotId = Integer.parseInt(getNextArgRequired());
1263 } catch (NumberFormatException e) {
1264 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1265 return -1;
1266 }
1267 break;
1268 }
1269 }
1270 }
1271 try {
1272 mInterface.enableIms(slotId);
1273 } catch (RemoteException e) {
1274 return -1;
1275 }
1276 if (VDBG) {
1277 Log.v(LOG_TAG, "ims enable -s " + slotId);
1278 }
1279 return 0;
1280 }
1281
1282 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001283 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001284 String opt;
1285 while ((opt = getNextOption()) != null) {
1286 switch (opt) {
1287 case "-s": {
1288 try {
1289 slotId = Integer.parseInt(getNextArgRequired());
1290 } catch (NumberFormatException e) {
1291 getErrPrintWriter().println(
1292 "ims disable requires an integer as a SLOT_ID.");
1293 return -1;
1294 }
1295 break;
1296 }
1297 }
1298 }
1299 try {
1300 mInterface.disableIms(slotId);
1301 } catch (RemoteException e) {
1302 return -1;
1303 }
1304 if (VDBG) {
1305 Log.v(LOG_TAG, "ims disable -s " + slotId);
1306 }
1307 return 0;
1308 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001309
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001310 private int handleCepChange() {
1311 Log.i(LOG_TAG, "handleCepChange");
1312 String opt = getNextArg();
1313 if (opt == null) {
1314 return -1;
1315 }
1316 boolean isCepEnabled = opt.equals("enable");
1317
1318 try {
1319 mInterface.setCepEnabled(isCepEnabled);
1320 } catch (RemoteException e) {
1321 return -1;
1322 }
1323 return 0;
1324 }
1325
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001326 private int getDefaultSlot() {
1327 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1328 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1329 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1330 // If there is no default, default to slot 0.
1331 slotId = DEFAULT_PHONE_ID;
1332 }
1333 return slotId;
1334 }
sqian2fff4a32018-11-05 14:18:37 -08001335
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001336 // Parse options related to Carrier Config Commands.
1337 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001338 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001339 CcOptionParseResult result = new CcOptionParseResult();
1340 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1341 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001342
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001343 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001344 while ((opt = getNextOption()) != null) {
1345 switch (opt) {
1346 case "-s": {
1347 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001348 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1349 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1350 errPw.println(tag + "No valid subscription found.");
1351 return null;
1352 }
1353
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001354 } catch (IllegalArgumentException e) {
1355 // Missing slot id
1356 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001357 return null;
1358 }
1359 break;
1360 }
1361 case "-p": {
1362 if (allowOptionPersistent) {
1363 result.mPersistent = true;
1364 } else {
1365 errPw.println(tag + "Unexpected option " + opt);
1366 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001367 }
1368 break;
1369 }
1370 default: {
1371 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001372 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001373 }
1374 }
1375 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001376 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001377 }
1378
1379 private int slotStringToSubId(String tag, String slotString) {
1380 int slotId = -1;
1381 try {
1382 slotId = Integer.parseInt(slotString);
1383 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001384 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1385 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1386 }
1387
1388 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001389 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1390 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1391 }
1392
Qiong Liuf25799b2020-09-10 10:13:46 +08001393 Phone phone = PhoneFactory.getPhone(slotId);
1394 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001395 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1396 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1397 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001398 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001399 }
1400
Hall Liud892bec2018-11-30 14:51:45 -08001401 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001402 // adb can run as root or as shell, depending on whether the device is rooted.
1403 return Binder.getCallingUid() == Process.SHELL_UID
1404 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001405 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001406
1407 private int handleCcCommand() {
1408 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1409 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001410 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001411 getErrPrintWriter().println("cc: Permission denied.");
1412 return -1;
1413 }
1414
1415 String arg = getNextArg();
1416 if (arg == null) {
1417 onHelpCc();
1418 return 0;
1419 }
1420
1421 switch (arg) {
1422 case CC_GET_VALUE: {
1423 return handleCcGetValue();
1424 }
1425 case CC_SET_VALUE: {
1426 return handleCcSetValue();
1427 }
1428 case CC_CLEAR_VALUES: {
1429 return handleCcClearValues();
1430 }
1431 default: {
1432 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1433 }
1434 }
1435 return -1;
1436 }
1437
1438 // cc get-value
1439 private int handleCcGetValue() {
1440 PrintWriter errPw = getErrPrintWriter();
1441 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1442 String key = null;
1443
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001444 // Parse all options
1445 CcOptionParseResult options = parseCcOptions(tag, false);
1446 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001447 return -1;
1448 }
1449
1450 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001451 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001452 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001453 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001454 return -1;
1455 }
1456
1457 // Get the key.
1458 key = getNextArg();
1459 if (key != null) {
1460 // A key was provided. Verify if it is a valid key
1461 if (!bundle.containsKey(key)) {
1462 errPw.println(tag + key + " is not a valid key.");
1463 return -1;
1464 }
1465
1466 // Print the carrier config value for key.
1467 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1468 } else {
1469 // No key provided. Show all values.
1470 // Iterate over a sorted list of all carrier config keys and print them.
1471 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1472 for (String k : sortedSet) {
1473 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1474 }
1475 }
1476 return 0;
1477 }
1478
1479 // cc set-value
1480 private int handleCcSetValue() {
1481 PrintWriter errPw = getErrPrintWriter();
1482 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1483
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001484 // Parse all options
1485 CcOptionParseResult options = parseCcOptions(tag, true);
1486 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001487 return -1;
1488 }
1489
1490 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001491 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001492 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001493 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001494 return -1;
1495 }
1496
1497 // Get the key.
1498 String key = getNextArg();
1499 if (key == null || key.equals("")) {
1500 errPw.println(tag + "KEY is missing");
1501 return -1;
1502 }
1503
1504 // Verify if the key is valid
1505 if (!originalValues.containsKey(key)) {
1506 errPw.println(tag + key + " is not a valid key.");
1507 return -1;
1508 }
1509
1510 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1511 ArrayList<String> valueList = new ArrayList<String>();
1512 while (peekNextArg() != null) {
1513 valueList.add(getNextArg());
1514 }
1515
1516 // Find the type of the carrier config value
1517 CcType type = getType(tag, key, originalValues);
1518 if (type == CcType.UNKNOWN) {
1519 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1520 return -1;
1521 }
1522
1523 // Create an override bundle containing the key and value that should be overriden.
1524 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1525 if (overrideBundle == null) {
1526 return -1;
1527 }
1528
1529 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001530 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001531
1532 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001533 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001534 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001535 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001536 return -1;
1537 }
1538
1539 // Print the original and new value.
1540 String originalValueString = ccValueToString(key, type, originalValues);
1541 String newValueString = ccValueToString(key, type, newValues);
1542 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1543 getOutPrintWriter().println("New value: \n" + newValueString);
1544
1545 return 0;
1546 }
1547
1548 // cc clear-values
1549 private int handleCcClearValues() {
1550 PrintWriter errPw = getErrPrintWriter();
1551 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1552
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001553 // Parse all options
1554 CcOptionParseResult options = parseCcOptions(tag, false);
1555 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001556 return -1;
1557 }
1558
1559 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001560 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001561 getOutPrintWriter()
1562 .println("All previously set carrier config override values has been cleared");
1563 return 0;
1564 }
1565
1566 private CcType getType(String tag, String key, PersistableBundle bundle) {
1567 // Find the type by checking the type of the current value stored in the bundle.
1568 Object value = bundle.get(key);
1569
1570 if (CC_TYPE_MAP.containsKey(key)) {
1571 return CC_TYPE_MAP.get(key);
1572 } else if (value != null) {
1573 if (value instanceof Boolean) {
1574 return CcType.BOOLEAN;
1575 } else if (value instanceof Double) {
1576 return CcType.DOUBLE;
1577 } else if (value instanceof double[]) {
1578 return CcType.DOUBLE_ARRAY;
1579 } else if (value instanceof Integer) {
1580 return CcType.INT;
1581 } else if (value instanceof int[]) {
1582 return CcType.INT_ARRAY;
1583 } else if (value instanceof Long) {
1584 return CcType.LONG;
1585 } else if (value instanceof long[]) {
1586 return CcType.LONG_ARRAY;
1587 } else if (value instanceof String) {
1588 return CcType.STRING;
1589 } else if (value instanceof String[]) {
1590 return CcType.STRING_ARRAY;
1591 }
1592 } else {
1593 // Current value was null and can therefore not be used in order to find the type.
1594 // Check the name of the key to infer the type. This check is not needed for primitive
1595 // data types (boolean, double, int and long), since they can not be null.
1596 if (key.endsWith("double_array")) {
1597 return CcType.DOUBLE_ARRAY;
1598 }
1599 if (key.endsWith("int_array")) {
1600 return CcType.INT_ARRAY;
1601 }
1602 if (key.endsWith("long_array")) {
1603 return CcType.LONG_ARRAY;
1604 }
1605 if (key.endsWith("string")) {
1606 return CcType.STRING;
1607 }
1608 if (key.endsWith("string_array") || key.endsWith("strings")) {
1609 return CcType.STRING_ARRAY;
1610 }
1611 }
1612
1613 // Not possible to infer the type by looking at the current value or the key.
1614 PrintWriter errPw = getErrPrintWriter();
1615 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1616 return CcType.UNKNOWN;
1617 }
1618
1619 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1620 String result;
1621 StringBuilder valueString = new StringBuilder();
1622 String typeString = type.toString();
1623 Object value = bundle.get(key);
1624
1625 if (value == null) {
1626 valueString.append("null");
1627 } else {
1628 switch (type) {
1629 case DOUBLE_ARRAY: {
1630 // Format the string representation of the int array as value1 value2......
1631 double[] valueArray = (double[]) value;
1632 for (int i = 0; i < valueArray.length; i++) {
1633 if (i != 0) {
1634 valueString.append(" ");
1635 }
1636 valueString.append(valueArray[i]);
1637 }
1638 break;
1639 }
1640 case INT_ARRAY: {
1641 // Format the string representation of the int array as value1 value2......
1642 int[] valueArray = (int[]) value;
1643 for (int i = 0; i < valueArray.length; i++) {
1644 if (i != 0) {
1645 valueString.append(" ");
1646 }
1647 valueString.append(valueArray[i]);
1648 }
1649 break;
1650 }
1651 case LONG_ARRAY: {
1652 // Format the string representation of the int array as value1 value2......
1653 long[] valueArray = (long[]) value;
1654 for (int i = 0; i < valueArray.length; i++) {
1655 if (i != 0) {
1656 valueString.append(" ");
1657 }
1658 valueString.append(valueArray[i]);
1659 }
1660 break;
1661 }
1662 case STRING: {
1663 valueString.append("\"" + value.toString() + "\"");
1664 break;
1665 }
1666 case STRING_ARRAY: {
1667 // Format the string representation of the string array as "value1" "value2"....
1668 String[] valueArray = (String[]) value;
1669 for (int i = 0; i < valueArray.length; i++) {
1670 if (i != 0) {
1671 valueString.append(" ");
1672 }
1673 if (valueArray[i] != null) {
1674 valueString.append("\"" + valueArray[i] + "\"");
1675 } else {
1676 valueString.append("null");
1677 }
1678 }
1679 break;
1680 }
1681 default: {
1682 valueString.append(value.toString());
1683 }
1684 }
1685 }
1686 return String.format("%-70s %-15s %s", key, typeString, valueString);
1687 }
1688
1689 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1690 ArrayList<String> valueList) {
1691 PrintWriter errPw = getErrPrintWriter();
1692 PersistableBundle bundle = new PersistableBundle();
1693
1694 // First verify that a valid number of values has been provided for the type.
1695 switch (type) {
1696 case BOOLEAN:
1697 case DOUBLE:
1698 case INT:
1699 case LONG: {
1700 if (valueList.size() != 1) {
1701 errPw.println(tag + "Expected 1 value for type " + type
1702 + ". Found: " + valueList.size());
1703 return null;
1704 }
1705 break;
1706 }
1707 case STRING: {
1708 if (valueList.size() > 1) {
1709 errPw.println(tag + "Expected 0 or 1 values for type " + type
1710 + ". Found: " + valueList.size());
1711 return null;
1712 }
1713 break;
1714 }
1715 }
1716
1717 // Parse the value according to type and add it to the Bundle.
1718 switch (type) {
1719 case BOOLEAN: {
1720 if ("true".equalsIgnoreCase(valueList.get(0))) {
1721 bundle.putBoolean(key, true);
1722 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1723 bundle.putBoolean(key, false);
1724 } else {
1725 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1726 return null;
1727 }
1728 break;
1729 }
1730 case DOUBLE: {
1731 try {
1732 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1733 } catch (NumberFormatException nfe) {
1734 // Not a valid double
1735 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1736 return null;
1737 }
1738 break;
1739 }
1740 case DOUBLE_ARRAY: {
1741 double[] valueDoubleArray = null;
1742 if (valueList.size() > 0) {
1743 valueDoubleArray = new double[valueList.size()];
1744 for (int i = 0; i < valueList.size(); i++) {
1745 try {
1746 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1747 } catch (NumberFormatException nfe) {
1748 // Not a valid double
1749 errPw.println(
1750 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1751 return null;
1752 }
1753 }
1754 }
1755 bundle.putDoubleArray(key, valueDoubleArray);
1756 break;
1757 }
1758 case INT: {
1759 try {
1760 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1761 } catch (NumberFormatException nfe) {
1762 // Not a valid integer
1763 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1764 return null;
1765 }
1766 break;
1767 }
1768 case INT_ARRAY: {
1769 int[] valueIntArray = null;
1770 if (valueList.size() > 0) {
1771 valueIntArray = new int[valueList.size()];
1772 for (int i = 0; i < valueList.size(); i++) {
1773 try {
1774 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1775 } catch (NumberFormatException nfe) {
1776 // Not a valid integer
1777 errPw.println(tag
1778 + "Unable to parse " + valueList.get(i) + " as an integer.");
1779 return null;
1780 }
1781 }
1782 }
1783 bundle.putIntArray(key, valueIntArray);
1784 break;
1785 }
1786 case LONG: {
1787 try {
1788 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1789 } catch (NumberFormatException nfe) {
1790 // Not a valid long
1791 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1792 return null;
1793 }
1794 break;
1795 }
1796 case LONG_ARRAY: {
1797 long[] valueLongArray = null;
1798 if (valueList.size() > 0) {
1799 valueLongArray = new long[valueList.size()];
1800 for (int i = 0; i < valueList.size(); i++) {
1801 try {
1802 valueLongArray[i] = Long.parseLong(valueList.get(i));
1803 } catch (NumberFormatException nfe) {
1804 // Not a valid long
1805 errPw.println(
1806 tag + "Unable to parse " + valueList.get(i) + " as a long");
1807 return null;
1808 }
1809 }
1810 }
1811 bundle.putLongArray(key, valueLongArray);
1812 break;
1813 }
1814 case STRING: {
1815 String value = null;
1816 if (valueList.size() > 0) {
1817 value = valueList.get(0);
1818 }
1819 bundle.putString(key, value);
1820 break;
1821 }
1822 case STRING_ARRAY: {
1823 String[] valueStringArray = null;
1824 if (valueList.size() > 0) {
1825 valueStringArray = new String[valueList.size()];
1826 valueList.toArray(valueStringArray);
1827 }
1828 bundle.putStringArray(key, valueStringArray);
1829 break;
1830 }
1831 }
1832 return bundle;
1833 }
Shuo Qian489d9282020-07-09 11:30:03 -07001834
1835 private int handleEndBlockSuppressionCommand() {
1836 if (!checkShellUid()) {
1837 return -1;
1838 }
1839
1840 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1841 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1842 }
1843 return 0;
1844 }
Hui Wang641e81c2020-10-12 12:14:23 -07001845
Michele Berionne54af4632020-12-28 20:23:16 +00001846 private int handleRestartModemCommand() {
1847 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1848 // non user build.
1849 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1850 getErrPrintWriter().println("RestartModem: Permission denied.");
1851 return -1;
1852 }
1853
1854 boolean result = TelephonyManager.getDefault().rebootRadio();
1855 getOutPrintWriter().println(result);
1856
1857 return result ? 0 : -1;
1858 }
1859
Michele Berionne5e411512020-11-13 02:36:59 +00001860 private int handleUnattendedReboot() {
1861 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1862 // non user build.
1863 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1864 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1865 return -1;
1866 }
1867
1868 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1869 getOutPrintWriter().println("result: " + result);
1870
1871 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1872 }
1873
Hui Wang641e81c2020-10-12 12:14:23 -07001874 private int handleGbaCommand() {
1875 String arg = getNextArg();
1876 if (arg == null) {
1877 onHelpGba();
1878 return 0;
1879 }
1880
1881 switch (arg) {
1882 case GBA_SET_SERVICE: {
1883 return handleGbaSetServiceCommand();
1884 }
1885 case GBA_GET_SERVICE: {
1886 return handleGbaGetServiceCommand();
1887 }
1888 case GBA_SET_RELEASE_TIME: {
1889 return handleGbaSetReleaseCommand();
1890 }
1891 case GBA_GET_RELEASE_TIME: {
1892 return handleGbaGetReleaseCommand();
1893 }
1894 }
1895
1896 return -1;
1897 }
1898
1899 private int getSubId(String cmd) {
1900 int slotId = getDefaultSlot();
1901 String opt = getNextOption();
1902 if (opt != null && opt.equals("-s")) {
1903 try {
1904 slotId = Integer.parseInt(getNextArgRequired());
1905 } catch (NumberFormatException e) {
1906 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1907 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1908 }
1909 }
1910 int[] subIds = SubscriptionManager.getSubId(slotId);
1911 return subIds[0];
1912 }
1913
1914 private int handleGbaSetServiceCommand() {
1915 int subId = getSubId("gba set-service");
1916 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1917 return -1;
1918 }
1919
1920 String packageName = getNextArg();
1921 try {
1922 if (packageName == null) {
1923 packageName = "";
1924 }
1925 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1926 if (VDBG) {
1927 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1928 + packageName + ", result=" + result);
1929 }
1930 getOutPrintWriter().println(result);
1931 } catch (RemoteException e) {
1932 Log.w(LOG_TAG, "gba set-service " + subId + " "
1933 + packageName + ", error" + e.getMessage());
1934 getErrPrintWriter().println("Exception: " + e.getMessage());
1935 return -1;
1936 }
1937 return 0;
1938 }
1939
1940 private int handleGbaGetServiceCommand() {
1941 String result;
1942
1943 int subId = getSubId("gba get-service");
1944 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1945 return -1;
1946 }
1947
1948 try {
1949 result = mInterface.getBoundGbaService(subId);
1950 } catch (RemoteException e) {
1951 return -1;
1952 }
1953 if (VDBG) {
1954 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1955 }
1956 getOutPrintWriter().println(result);
1957 return 0;
1958 }
1959
1960 private int handleGbaSetReleaseCommand() {
1961 //the release time value could be -1
1962 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1963 : SubscriptionManager.getDefaultSubscriptionId();
1964 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1965 return -1;
1966 }
1967
1968 String intervalStr = getNextArg();
1969 if (intervalStr == null) {
1970 return -1;
1971 }
1972
1973 try {
1974 int interval = Integer.parseInt(intervalStr);
1975 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1976 if (VDBG) {
1977 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1978 + intervalStr + ", result=" + result);
1979 }
1980 getOutPrintWriter().println(result);
1981 } catch (NumberFormatException | RemoteException e) {
1982 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1983 + intervalStr + ", error" + e.getMessage());
1984 getErrPrintWriter().println("Exception: " + e.getMessage());
1985 return -1;
1986 }
1987 return 0;
1988 }
1989
1990 private int handleGbaGetReleaseCommand() {
1991 int subId = getSubId("gba get-release");
1992 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1993 return -1;
1994 }
1995
1996 int result = 0;
1997 try {
1998 result = mInterface.getGbaReleaseTime(subId);
1999 } catch (RemoteException e) {
2000 return -1;
2001 }
2002 if (VDBG) {
2003 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2004 }
2005 getOutPrintWriter().println(result);
2006 return 0;
2007 }
Hui Wang761a6682020-10-31 05:12:53 +00002008
2009 private int handleSingleRegistrationConfigCommand() {
2010 String arg = getNextArg();
2011 if (arg == null) {
2012 onHelpSrc();
2013 return 0;
2014 }
2015
2016 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002017 case SRC_SET_TEST_ENABLED: {
2018 return handleSrcSetTestEnabledCommand();
2019 }
2020 case SRC_GET_TEST_ENABLED: {
2021 return handleSrcGetTestEnabledCommand();
2022 }
Hui Wang761a6682020-10-31 05:12:53 +00002023 case SRC_SET_DEVICE_ENABLED: {
2024 return handleSrcSetDeviceEnabledCommand();
2025 }
2026 case SRC_GET_DEVICE_ENABLED: {
2027 return handleSrcGetDeviceEnabledCommand();
2028 }
2029 case SRC_SET_CARRIER_ENABLED: {
2030 return handleSrcSetCarrierEnabledCommand();
2031 }
2032 case SRC_GET_CARRIER_ENABLED: {
2033 return handleSrcGetCarrierEnabledCommand();
2034 }
Hui Wangb647abe2021-02-26 09:33:38 -08002035 case SRC_SET_FEATURE_ENABLED: {
2036 return handleSrcSetFeatureValidationCommand();
2037 }
2038 case SRC_GET_FEATURE_ENABLED: {
2039 return handleSrcGetFeatureValidationCommand();
2040 }
Hui Wang761a6682020-10-31 05:12:53 +00002041 }
2042
2043 return -1;
2044 }
2045
James.cf Linbcdf8b32021-01-14 16:44:13 +08002046 private int handleRcsUceCommand() {
2047 String arg = getNextArg();
2048 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002049 onHelpUce();
2050 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002051 }
2052
2053 switch (arg) {
2054 case UCE_REMOVE_EAB_CONTACT:
2055 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002056 case UCE_GET_EAB_CONTACT:
2057 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002058 case UCE_GET_DEVICE_ENABLED:
2059 return handleUceGetDeviceEnabledCommand();
2060 case UCE_SET_DEVICE_ENABLED:
2061 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002062 case UCE_OVERRIDE_PUBLISH_CAPS:
2063 return handleUceOverridePublishCaps();
2064 case UCE_GET_LAST_PIDF_XML:
2065 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002066 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2067 return handleUceRemoveRequestDisallowedStatus();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002068 }
2069 return -1;
2070 }
2071
2072 private int handleRemovingEabContactCommand() {
2073 int subId = getSubId("uce remove-eab-contact");
2074 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2075 return -1;
2076 }
2077
2078 String phoneNumber = getNextArgRequired();
2079 if (TextUtils.isEmpty(phoneNumber)) {
2080 return -1;
2081 }
2082 int result = 0;
2083 try {
2084 result = mInterface.removeContactFromEab(subId, phoneNumber);
2085 } catch (RemoteException e) {
2086 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2087 getErrPrintWriter().println("Exception: " + e.getMessage());
2088 return -1;
2089 }
2090
2091 if (VDBG) {
2092 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2093 }
calvinpan293ea1b2021-02-04 17:52:13 +08002094 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002095 }
2096
calvinpane4a8a1d2021-01-25 13:51:18 +08002097 private int handleGettingEabContactCommand() {
2098 String phoneNumber = getNextArgRequired();
2099 if (TextUtils.isEmpty(phoneNumber)) {
2100 return -1;
2101 }
2102 String result = "";
2103 try {
2104 result = mInterface.getContactFromEab(phoneNumber);
2105
2106 } catch (RemoteException e) {
2107 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2108 getErrPrintWriter().println("Exception: " + e.getMessage());
2109 return -1;
2110 }
2111
2112 if (VDBG) {
2113 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2114 }
calvinpan293ea1b2021-02-04 17:52:13 +08002115 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002116 return 0;
2117 }
2118
2119 private int handleUceGetDeviceEnabledCommand() {
2120 boolean result = false;
2121 try {
2122 result = mInterface.getDeviceUceEnabled();
2123 } catch (RemoteException e) {
2124 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2125 return -1;
2126 }
2127 if (VDBG) {
2128 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2129 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002130 getOutPrintWriter().println(result);
2131 return 0;
2132 }
2133
James.cf Lin4b784aa2021-01-31 03:25:15 +08002134 private int handleUceSetDeviceEnabledCommand() {
2135 String enabledStr = getNextArg();
2136 if (TextUtils.isEmpty(enabledStr)) {
2137 return -1;
2138 }
2139
2140 try {
2141 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2142 mInterface.setDeviceUceEnabled(isEnabled);
2143 if (VDBG) {
2144 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2145 }
2146 } catch (NumberFormatException | RemoteException e) {
2147 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2148 getErrPrintWriter().println("Exception: " + e.getMessage());
2149 return -1;
2150 }
2151 return 0;
2152 }
2153
James.cf Line8713a42021-04-29 16:04:26 +08002154 private int handleUceRemoveRequestDisallowedStatus() {
2155 int subId = getSubId("uce remove-request-disallowed-status");
2156 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2157 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2158 return -1;
2159 }
2160 boolean result;
2161 try {
2162 result = mInterface.removeUceRequestDisallowedStatus(subId);
2163 } catch (RemoteException e) {
2164 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2165 return -1;
2166 }
2167 if (VDBG) {
2168 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2169 }
2170 getOutPrintWriter().println(result);
2171 return 0;
2172 }
2173
Hui Wangbaaee6a2021-02-19 20:45:36 -08002174 private int handleSrcSetTestEnabledCommand() {
2175 String enabledStr = getNextArg();
2176 if (enabledStr == null) {
2177 return -1;
2178 }
2179
2180 try {
2181 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2182 if (VDBG) {
2183 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2184 }
2185 getOutPrintWriter().println("Done");
2186 } catch (NumberFormatException | RemoteException e) {
2187 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2188 getErrPrintWriter().println("Exception: " + e.getMessage());
2189 return -1;
2190 }
2191 return 0;
2192 }
2193
2194 private int handleSrcGetTestEnabledCommand() {
2195 boolean result = false;
2196 try {
2197 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2198 } catch (RemoteException e) {
2199 return -1;
2200 }
2201 if (VDBG) {
2202 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2203 }
2204 getOutPrintWriter().println(result);
2205 return 0;
2206 }
2207
Brad Ebinger14d467f2021-02-12 06:18:28 +00002208 private int handleUceOverridePublishCaps() {
2209 int subId = getSubId("uce override-published-caps");
2210 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2211 return -1;
2212 }
2213 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2214 String operation = getNextArgRequired();
2215 String caps = getNextArg();
2216 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2217 && !"list".equals(operation)) {
2218 getErrPrintWriter().println("Invalid operation: " + operation);
2219 return -1;
2220 }
2221
2222 // add/remove requires capabilities to be specified.
2223 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2224 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2225 + "specified");
2226 return -1;
2227 }
2228
2229 ArraySet<String> capSet = new ArraySet<>();
2230 if (!TextUtils.isEmpty(caps)) {
2231 String[] capArray = caps.split(":");
2232 for (String cap : capArray) {
2233 // Allow unknown tags to be passed in as well.
2234 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2235 }
2236 }
2237
2238 RcsContactUceCapability result = null;
2239 try {
2240 switch (operation) {
2241 case "add":
2242 result = mInterface.addUceRegistrationOverrideShell(subId,
2243 new ArrayList<>(capSet));
2244 break;
2245 case "remove":
2246 result = mInterface.removeUceRegistrationOverrideShell(subId,
2247 new ArrayList<>(capSet));
2248 break;
2249 case "clear":
2250 result = mInterface.clearUceRegistrationOverrideShell(subId);
2251 break;
2252 case "list":
2253 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2254 break;
2255 }
2256 } catch (RemoteException e) {
2257 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2258 getErrPrintWriter().println("Exception: " + e.getMessage());
2259 return -1;
2260 } catch (ServiceSpecificException sse) {
2261 // Reconstruct ImsException
2262 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2263 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2264 getErrPrintWriter().println("Exception: " + imsException);
2265 return -1;
2266 }
2267 if (result == null) {
2268 getErrPrintWriter().println("Service not available");
2269 return -1;
2270 }
2271 getOutPrintWriter().println(result);
2272 return 0;
2273 }
2274
2275 private int handleUceGetPidfXml() {
2276 int subId = getSubId("uce get-last-publish-pidf");
2277 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2278 return -1;
2279 }
2280
2281 String result;
2282 try {
2283 result = mInterface.getLastUcePidfXmlShell(subId);
2284 } catch (RemoteException e) {
2285 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2286 getErrPrintWriter().println("Exception: " + e.getMessage());
2287 return -1;
2288 } catch (ServiceSpecificException sse) {
2289 // Reconstruct ImsException
2290 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2291 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2292 getErrPrintWriter().println("Exception: " + imsException);
2293 return -1;
2294 }
2295 if (result == null) {
2296 getErrPrintWriter().println("Service not available");
2297 return -1;
2298 }
2299 getOutPrintWriter().println(result);
2300 return 0;
2301 }
2302
Hui Wang761a6682020-10-31 05:12:53 +00002303 private int handleSrcSetDeviceEnabledCommand() {
2304 String enabledStr = getNextArg();
2305 if (enabledStr == null) {
2306 return -1;
2307 }
2308
2309 try {
2310 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2311 if (VDBG) {
2312 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2313 }
2314 getOutPrintWriter().println("Done");
2315 } catch (NumberFormatException | RemoteException e) {
2316 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2317 getErrPrintWriter().println("Exception: " + e.getMessage());
2318 return -1;
2319 }
2320 return 0;
2321 }
2322
2323 private int handleSrcGetDeviceEnabledCommand() {
2324 boolean result = false;
2325 try {
2326 result = mInterface.getDeviceSingleRegistrationEnabled();
2327 } catch (RemoteException e) {
2328 return -1;
2329 }
2330 if (VDBG) {
2331 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2332 }
2333 getOutPrintWriter().println(result);
2334 return 0;
2335 }
2336
2337 private int handleSrcSetCarrierEnabledCommand() {
2338 //the release time value could be -1
2339 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2340 : SubscriptionManager.getDefaultSubscriptionId();
2341 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2342 return -1;
2343 }
2344
2345 String enabledStr = getNextArg();
2346 if (enabledStr == null) {
2347 return -1;
2348 }
2349
2350 try {
2351 boolean result =
2352 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2353 if (VDBG) {
2354 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2355 + enabledStr + ", result=" + result);
2356 }
2357 getOutPrintWriter().println(result);
2358 } catch (NumberFormatException | RemoteException e) {
2359 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2360 + enabledStr + ", error" + e.getMessage());
2361 getErrPrintWriter().println("Exception: " + e.getMessage());
2362 return -1;
2363 }
2364 return 0;
2365 }
2366
2367 private int handleSrcGetCarrierEnabledCommand() {
2368 int subId = getSubId("src get-carrier-enabled");
2369 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2370 return -1;
2371 }
2372
2373 boolean result = false;
2374 try {
2375 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2376 } catch (RemoteException e) {
2377 return -1;
2378 }
2379 if (VDBG) {
2380 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2381 }
2382 getOutPrintWriter().println(result);
2383 return 0;
2384 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002385
Hui Wangb647abe2021-02-26 09:33:38 -08002386 private int handleSrcSetFeatureValidationCommand() {
2387 //the release time value could be -1
2388 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2389 : SubscriptionManager.getDefaultSubscriptionId();
2390 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2391 return -1;
2392 }
2393
2394 String enabledStr = getNextArg();
2395 if (enabledStr == null) {
2396 return -1;
2397 }
2398
2399 try {
2400 boolean result =
2401 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2402 if (VDBG) {
2403 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2404 + enabledStr + ", result=" + result);
2405 }
2406 getOutPrintWriter().println(result);
2407 } catch (NumberFormatException | RemoteException e) {
2408 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2409 + enabledStr + ", error" + e.getMessage());
2410 getErrPrintWriter().println("Exception: " + e.getMessage());
2411 return -1;
2412 }
2413 return 0;
2414 }
2415
2416 private int handleSrcGetFeatureValidationCommand() {
2417 int subId = getSubId("src get-feature-validation");
2418 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2419 return -1;
2420 }
2421
2422 Boolean result = false;
2423 try {
2424 result = mInterface.getImsFeatureValidationOverride(subId);
2425 } catch (RemoteException e) {
2426 return -1;
2427 }
2428 if (VDBG) {
2429 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2430 }
2431 getOutPrintWriter().println(result);
2432 return 0;
2433 }
2434
2435
Hall Liuaa4211e2021-01-20 15:43:39 -08002436 private void onHelpCallComposer() {
2437 PrintWriter pw = getOutPrintWriter();
2438 pw.println("Call composer commands");
2439 pw.println(" callcomposer test-mode enable|disable|query");
2440 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2441 pw.println(" upload/download from carrier servers is disabled, and operations are");
2442 pw.println(" performed using emulated local files instead.");
2443 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2444 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2445 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002446 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2447 pw.println(" Enables or disables the user setting for call composer, as set by");
2448 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002449 }
2450
2451 private int handleCallComposerCommand() {
2452 String arg = getNextArg();
2453 if (arg == null) {
2454 onHelpCallComposer();
2455 return 0;
2456 }
2457
2458 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2459 "MODIFY_PHONE_STATE required for call composer shell cmds");
2460 switch (arg) {
2461 case CALL_COMPOSER_TEST_MODE: {
2462 String enabledStr = getNextArg();
2463 if (ENABLE.equals(enabledStr)) {
2464 CallComposerPictureManager.sTestMode = true;
2465 } else if (DISABLE.equals(enabledStr)) {
2466 CallComposerPictureManager.sTestMode = false;
2467 } else if (QUERY.equals(enabledStr)) {
2468 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2469 } else {
2470 onHelpCallComposer();
2471 return 1;
2472 }
2473 break;
2474 }
2475 case CALL_COMPOSER_SIMULATE_CALL: {
2476 int subscriptionId = Integer.valueOf(getNextArg());
2477 String uuidString = getNextArg();
2478 UUID uuid = UUID.fromString(uuidString);
2479 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2480 Binder.withCleanCallingIdentity(() -> {
2481 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2482 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2483 });
2484 try {
2485 Uri uri = storageUriFuture.get();
2486 getOutPrintWriter().println(String.valueOf(uri));
2487 } catch (Exception e) {
2488 throw new RuntimeException(e);
2489 }
2490 break;
2491 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002492 case CALL_COMPOSER_USER_SETTING: {
2493 try {
2494 int subscriptionId = Integer.valueOf(getNextArg());
2495 String enabledStr = getNextArg();
2496 if (ENABLE.equals(enabledStr)) {
2497 mInterface.setCallComposerStatus(subscriptionId,
2498 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2499 } else if (DISABLE.equals(enabledStr)) {
2500 mInterface.setCallComposerStatus(subscriptionId,
2501 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2502 } else if (QUERY.equals(enabledStr)) {
2503 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2504 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2505 } else {
2506 onHelpCallComposer();
2507 return 1;
2508 }
2509 } catch (RemoteException e) {
2510 e.printStackTrace(getOutPrintWriter());
2511 return 1;
2512 }
2513 break;
2514 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002515 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002516 return 0;
2517 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002518
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002519 private int handleHasCarrierPrivilegesCommand() {
2520 String packageName = getNextArgRequired();
2521
2522 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002523 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002524 try {
2525 hasCarrierPrivileges =
2526 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2527 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2528 } catch (RemoteException e) {
2529 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2530 getErrPrintWriter().println("Exception: " + e.getMessage());
2531 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002532 } finally {
2533 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002534 }
2535
2536 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002537 return 0;
2538 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002539
2540 private int handleAllowedNetworkTypesCommand(String command) {
2541 if (!checkShellUid()) {
2542 return -1;
2543 }
2544
2545 PrintWriter errPw = getErrPrintWriter();
2546 String tag = command + ": ";
2547 String opt;
2548 int subId = -1;
2549 Log.v(LOG_TAG, command + " start");
2550
2551 while ((opt = getNextOption()) != null) {
2552 if (opt.equals("-s")) {
2553 try {
2554 subId = slotStringToSubId(tag, getNextArgRequired());
2555 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2556 errPw.println(tag + "No valid subscription found.");
2557 return -1;
2558 }
2559 } catch (IllegalArgumentException e) {
2560 // Missing slot id
2561 errPw.println(tag + "SLOT_ID expected after -s.");
2562 return -1;
2563 }
2564 } else {
2565 errPw.println(tag + "Unknown option " + opt);
2566 return -1;
2567 }
2568 }
2569
2570 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2571 return handleGetAllowedNetworkTypesCommand(subId);
2572 }
2573 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2574 return handleSetAllowedNetworkTypesCommand(subId);
2575 }
2576 return -1;
2577 }
2578
2579 private int handleGetAllowedNetworkTypesCommand(int subId) {
2580 PrintWriter errPw = getErrPrintWriter();
2581
2582 long result = -1;
2583 try {
2584 if (mInterface != null) {
2585 result = mInterface.getAllowedNetworkTypesForReason(subId,
2586 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2587 } else {
2588 throw new IllegalStateException("telephony service is null.");
2589 }
2590 } catch (RemoteException e) {
2591 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2592 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2593 return -1;
2594 }
2595
2596 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2597 return 0;
2598 }
2599
2600 private int handleSetAllowedNetworkTypesCommand(int subId) {
2601 PrintWriter errPw = getErrPrintWriter();
2602
2603 String bitmaskString = getNextArg();
2604 if (TextUtils.isEmpty(bitmaskString)) {
2605 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2606 return -1;
2607 }
2608 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2609 if (allowedNetworkTypes < 0) {
2610 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2611 return -1;
2612 }
2613 boolean result = false;
2614 try {
2615 if (mInterface != null) {
2616 result = mInterface.setAllowedNetworkTypesForReason(subId,
2617 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2618 } else {
2619 throw new IllegalStateException("telephony service is null.");
2620 }
2621 } catch (RemoteException e) {
2622 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2623 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2624 return -1;
2625 }
2626
2627 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2628 if (result) {
2629 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2630 }
2631 getOutPrintWriter().println(resultMessage);
2632 return 0;
2633 }
2634
2635 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2636 if (TextUtils.isEmpty(bitmaskString)) {
2637 return -1;
2638 }
2639 if (VDBG) {
2640 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2641 + ", length: " + bitmaskString.length());
2642 }
2643 try {
2644 return Long.parseLong(bitmaskString, 2);
2645 } catch (NumberFormatException e) {
2646 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2647 return -1;
2648 }
2649 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002650}