blob: c83ea645e9b7445d47f470553824f2d4f7518b70 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000031import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070032import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070033import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010034import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070035import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000037import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070038import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080039import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000040import android.telephony.ims.ImsException;
41import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080042import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080043import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000044import android.util.ArrayMap;
45import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070046import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070047import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
Brad Ebinger14d467f2021-02-12 06:18:28 +000049import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080051import com.android.internal.telephony.Phone;
52import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080053import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080054import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080055import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080056import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080057import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070058
59import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080060import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000061import java.util.Arrays;
62import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010063import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080064import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010065import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010067import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080068import java.util.UUID;
69import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070
71/**
72 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
73 * permission checks have been done before onCommand was called. Make sure any commands processed
74 * here also contain the appropriate permissions checks.
75 */
76
Hall Liua1548bd2019-12-24 14:14:12 -080077public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070078
79 private static final String LOG_TAG = "TelephonyShellCommand";
80 // Don't commit with this true.
81 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070082 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
Hall Liuaa4211e2021-01-20 15:43:39 -080084 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080086 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080087 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080088 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070089 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000090 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000091 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010092 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080093 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080094 private static final String ENABLE = "enable";
95 private static final String DISABLE = "disable";
96 private static final String QUERY = "query";
97
Hall Liu7135e502021-02-04 16:58:17 -080098 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800100 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800101
Brad Ebinger999d3302020-11-25 14:31:39 -0800102 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
103 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
104 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700105 // Used to disable or enable processing of conference event package data from the network.
106 // This is handy for testing scenarios where CEP data does not exist on a network which does
107 // support CEP data.
108 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700109
Hall Liud892bec2018-11-30 14:51:45 -0800110 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800111 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100113 private static final String CC_GET_VALUE = "get-value";
114 private static final String CC_SET_VALUE = "set-value";
115 private static final String CC_CLEAR_VALUES = "clear-values";
116
Hui Wang641e81c2020-10-12 12:14:23 -0700117 private static final String GBA_SUBCOMMAND = "gba";
118 private static final String GBA_SET_SERVICE = "set-service";
119 private static final String GBA_GET_SERVICE = "get-service";
120 private static final String GBA_SET_RELEASE_TIME = "set-release";
121 private static final String GBA_GET_RELEASE_TIME = "get-release";
122
Hui Wang761a6682020-10-31 05:12:53 +0000123 private static final String SINGLE_REGISTATION_CONFIG = "src";
124 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
125 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
126 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
127 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800128 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
129 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800130 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
131 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000132
Tyler Gunn92479152021-01-20 16:30:10 -0800133 private static final String D2D_SUBCOMMAND = "d2d";
134 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800135 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700136 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800137
Nazanin014f41e2021-05-06 17:26:31 -0700138 private static final String BARRING_SUBCOMMAND = "barring";
139 private static final String BARRING_SEND_INFO = "send";
140
James.cf Linbcdf8b32021-01-14 16:44:13 +0800141 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800142 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800143 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800144 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
145 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000146 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
147 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800148 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
149 "remove-request-disallowed-status";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800150
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800151 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
152 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
153
Jordan Liu0ccee222021-04-27 11:55:13 -0700154 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
155 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
156
Jack Nudelman644b91a2021-03-12 14:09:48 -0800157 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
158 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
159 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
160
SongFerngWang98dd5992021-05-13 17:50:00 +0800161 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
162 "get-allowed-network-types-for-users";
163 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
164 "set-allowed-network-types-for-users";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700165 // Take advantage of existing methods that already contain permissions checks when possible.
166 private final ITelephony mInterface;
167
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100168 private SubscriptionManager mSubscriptionManager;
169 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700170 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700171 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100172
173 private enum CcType {
174 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
175 STRING_ARRAY, UNKNOWN
176 }
177
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100178 private class CcOptionParseResult {
179 public int mSubId;
180 public boolean mPersistent;
181 }
182
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100183 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
184 // keys by looking at the end of the string which usually tells the type.
185 // For instance: "xxxx_string", "xxxx_string_array", etc.
186 // The carrier config keys in this map does not follow this convention. It is therefore not
187 // possible to infer the type for these keys by looking at the string.
188 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
189 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
190 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
191 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
192 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
193 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
194 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
195 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
196 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
197 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
198 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
199 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
200 CcType.STRING);
201 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
202 CcType.STRING_ARRAY);
203 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
204 CcType.STRING_ARRAY);
205 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
206 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
207 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
208 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
209 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
210 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
211 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
212 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
213 }
214 };
215
Brad Ebinger14d467f2021-02-12 06:18:28 +0000216 /**
217 * Map from a shorthand string to the feature tags required in registration required in order
218 * for the RCS feature to be considered "capable".
219 */
220 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
221 static {
222 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
223 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
224 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
225 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
226 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
227 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
228 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
229 FeatureTags.FEATURE_TAG_VIDEO)));
230 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
231 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
232 map.put("call_comp",
233 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
234 map.put("call_comp_mmtel",
235 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
236 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
237 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
238 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
239 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
240 // version
241 map.put("chatbot", new ArraySet<>(Arrays.asList(
242 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
243 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
244 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
245 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
246 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
247 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
248 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
249 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
250 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
251 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
252 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
253 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
254 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
255 }
256
257
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100258 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700259 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100260 mCarrierConfigManager =
261 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
262 mSubscriptionManager = (SubscriptionManager)
263 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700264 mTelephonyRegistryManager = (TelephonyRegistryManager)
265 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700266 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700267 }
268
269 @Override
270 public int onCommand(String cmd) {
271 if (cmd == null) {
272 return handleDefaultCommands(null);
273 }
274
275 switch (cmd) {
276 case IMS_SUBCOMMAND: {
277 return handleImsCommand();
278 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800279 case RCS_UCE_COMMAND:
280 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800281 case NUMBER_VERIFICATION_SUBCOMMAND:
282 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800283 case EMERGENCY_CALLBACK_MODE:
284 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800285 case EMERGENCY_NUMBER_TEST_MODE:
286 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100287 case CARRIER_CONFIG_SUBCOMMAND: {
288 return handleCcCommand();
289 }
Shuo Qianf5125122019-12-16 17:03:07 -0800290 case DATA_TEST_MODE:
291 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700292 case END_BLOCK_SUPPRESSION:
293 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700294 case GBA_SUBCOMMAND:
295 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800296 case D2D_SUBCOMMAND:
297 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700298 case BARRING_SUBCOMMAND:
299 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000300 case SINGLE_REGISTATION_CONFIG:
301 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000302 case RESTART_MODEM:
303 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800304 case CALL_COMPOSER_SUBCOMMAND:
305 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000306 case UNATTENDED_REBOOT:
307 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800308 case HAS_CARRIER_PRIVILEGES_COMMAND:
309 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800310 case THERMAL_MITIGATION_COMMAND:
311 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700312 case DISABLE_PHYSICAL_SUBSCRIPTION:
313 return handleEnablePhysicalSubscription(false);
314 case ENABLE_PHYSICAL_SUBSCRIPTION:
315 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800316 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
317 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
318 return handleAllowedNetworkTypesCommand(cmd);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700319 default: {
320 return handleDefaultCommands(cmd);
321 }
322 }
323 }
324
325 @Override
326 public void onHelp() {
327 PrintWriter pw = getOutPrintWriter();
328 pw.println("Telephony Commands:");
329 pw.println(" help");
330 pw.println(" Print this help text.");
331 pw.println(" ims");
332 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800333 pw.println(" uce");
334 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800335 pw.println(" emergency-number-test-mode");
336 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700337 pw.println(" end-block-suppression");
338 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800339 pw.println(" data");
340 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100341 pw.println(" cc");
342 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700343 pw.println(" gba");
344 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000345 pw.println(" src");
346 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000347 pw.println(" restart-modem");
348 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000349 pw.println(" unattended-reboot");
350 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800351 pw.println(" has-carrier-privileges [package]");
352 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800353 pw.println(" get-allowed-network-types-for-users");
354 pw.println(" Get the Allowed Network Types.");
355 pw.println(" set-allowed-network-types-for-users");
356 pw.println(" Set the Allowed Network Types.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700357 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800358 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800359 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700360 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800361 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100362 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700363 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000364 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800365 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700366 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800367 onHelpAllowedNetworkTypes();
Tyler Gunn92479152021-01-20 16:30:10 -0800368 }
369
370 private void onHelpD2D() {
371 PrintWriter pw = getOutPrintWriter();
372 pw.println("D2D Comms Commands:");
373 pw.println(" d2d send TYPE VALUE");
374 pw.println(" Sends a D2D message of specified type and value.");
375 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
376 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
377 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
378 MESSAGE_CALL_AUDIO_CODEC));
379 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
380 + Communicator.messageToString(
381 MESSAGE_DEVICE_BATTERY_STATE));
382 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
383 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800384 pw.println(" d2d transport TYPE");
385 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
386 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700387 pw.println(" d2d set-device-support true/default");
388 pw.println(" true - forces device support to be enabled for D2D.");
389 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
390 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700391 }
392
Nazanin014f41e2021-05-06 17:26:31 -0700393 private void onHelpBarring() {
394 PrintWriter pw = getOutPrintWriter();
395 pw.println("Barring Commands:");
396 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
397 + " -t CONDITIONAL_BARRING_TIME_SECS");
398 pw.println(" Notifies of a barring info change for the specified slot id.");
399 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
400 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
401 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
402 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
403 }
404
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700405 private void onHelpIms() {
406 PrintWriter pw = getOutPrintWriter();
407 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800408 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700409 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
410 pw.println(" ImsService. Options are:");
411 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
412 pw.println(" is specified, it will choose the default voice SIM slot.");
413 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
414 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800415 pw.println(" -f: Set the feature that this override if for, if no option is");
416 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700417 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
418 pw.println(" Gets the package name of the currently defined ImsService.");
419 pw.println(" Options are:");
420 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
421 pw.println(" is specified, it will choose the default voice SIM slot.");
422 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000423 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800424 pw.println(" -f: The feature type that the query will be requested for. If none is");
425 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800426 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
427 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
428 pw.println(" configuration overrides. Options are:");
429 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
430 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700431 pw.println(" ims enable [-s SLOT_ID]");
432 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
433 pw.println(" if none is specified.");
434 pw.println(" ims disable [-s SLOT_ID]");
435 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
436 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700437 pw.println(" ims conference-event-package [enable/disable]");
438 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700439 }
440
James.cf Linbcdf8b32021-01-14 16:44:13 +0800441 private void onHelpUce() {
442 PrintWriter pw = getOutPrintWriter();
443 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800444 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
445 pw.println(" Get the EAB contacts from the EAB database.");
446 pw.println(" Options are:");
447 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
448 pw.println(" Expected output format :");
449 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800450 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
451 pw.println(" Remove the EAB contacts from the EAB database.");
452 pw.println(" Options are:");
453 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
454 pw.println(" is specified, it will choose the default voice SIM slot.");
455 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800456 pw.println(" uce get-device-enabled");
457 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
458 pw.println(" uce set-device-enabled true|false");
459 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
460 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000461 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
462 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
463 pw.println(" Options are:");
464 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
465 pw.println(" is specified, it will choose the default voice SIM slot.");
466 pw.println(" add [CAPABILITY]: add a new capability");
467 pw.println(" remove [CAPABILITY]: remove a capability");
468 pw.println(" clear: clear all capability overrides");
469 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
470 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
471 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
472 pw.println(" chatbot_sa, chatbot_role] as well as full length");
473 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
474 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
475 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
476 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800477 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
478 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800479 }
480
Hall Liud892bec2018-11-30 14:51:45 -0800481 private void onHelpNumberVerification() {
482 PrintWriter pw = getOutPrintWriter();
483 pw.println("Number verification commands");
484 pw.println(" numverify override-package PACKAGE_NAME;");
485 pw.println(" Set the authorized package for number verification.");
486 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800487 pw.println(" numverify fake-call NUMBER;");
488 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
489 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800490 }
491
Jack Nudelman644b91a2021-03-12 14:09:48 -0800492 private void onHelpThermalMitigation() {
493 PrintWriter pw = getOutPrintWriter();
494 pw.println("Thermal mitigation commands");
495 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
496 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
497 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
498 pw.println(" Remove the package from one of the authorized packages for thermal "
499 + "mitigation.");
500 }
501
Jordan Liu0ccee222021-04-27 11:55:13 -0700502 private void onHelpDisableOrEnablePhysicalSubscription() {
503 PrintWriter pw = getOutPrintWriter();
504 pw.println("Disable or enable a physical subscription");
505 pw.println(" disable-physical-subscription SUB_ID");
506 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
507 pw.println(" enable-physical-subscription SUB_ID");
508 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
509 }
510
Shuo Qianf5125122019-12-16 17:03:07 -0800511 private void onHelpDataTestMode() {
512 PrintWriter pw = getOutPrintWriter();
513 pw.println("Mobile Data Test Mode Commands:");
514 pw.println(" data enable: enable mobile data connectivity");
515 pw.println(" data disable: disable mobile data connectivity");
516 }
517
sqian9d4df8b2019-01-15 18:32:07 -0800518 private void onHelpEmergencyNumber() {
519 PrintWriter pw = getOutPrintWriter();
520 pw.println("Emergency Number Test Mode Commands:");
521 pw.println(" emergency-number-test-mode ");
522 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
523 + " the test mode");
524 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700525 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800526 pw.println(" -c: clear the emergency number list in the test mode.");
527 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700528 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800529 pw.println(" -p: get the full emergency number list in the test mode.");
530 }
531
Shuo Qian489d9282020-07-09 11:30:03 -0700532 private void onHelpEndBlockSupperssion() {
533 PrintWriter pw = getOutPrintWriter();
534 pw.println("End Block Suppression command:");
535 pw.println(" end-block-suppression: disable suppressing blocking by contact");
536 pw.println(" with emergency services.");
537 }
538
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100539 private void onHelpCc() {
540 PrintWriter pw = getOutPrintWriter();
541 pw.println("Carrier Config Commands:");
542 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
543 pw.println(" Print carrier config values.");
544 pw.println(" Options are:");
545 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
546 pw.println(" is specified, it will choose the default voice SIM slot.");
547 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
548 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100549 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100550 pw.println(" Set carrier config KEY to NEW_VALUE.");
551 pw.println(" Options are:");
552 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
553 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100554 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100555 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
556 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
557 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
558 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
559 pw.println(" cc clear-values [-s SLOT_ID]");
560 pw.println(" Clear all carrier override values that has previously been set");
561 pw.println(" with set-value");
562 pw.println(" Options are:");
563 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
564 pw.println(" is specified, it will choose the default voice SIM slot.");
565 }
566
Hui Wang641e81c2020-10-12 12:14:23 -0700567 private void onHelpGba() {
568 PrintWriter pw = getOutPrintWriter();
569 pw.println("Gba Commands:");
570 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
571 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
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 get-service [-s SLOT_ID]");
576 pw.println(" Gets the package name of the currently defined GbaService.");
577 pw.println(" Options are:");
578 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
579 pw.println(" is specified, it will choose the default voice SIM slot.");
580 pw.println(" gba set-release [-s SLOT_ID] n");
581 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
582 pw.println(" Do not release/unbind if n is -1.");
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 pw.println(" gba get-release [-s SLOT_ID]");
587 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
588 pw.println(" Options are:");
589 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
590 pw.println(" is specified, it will choose the default voice SIM slot.");
591 }
592
Hui Wang761a6682020-10-31 05:12:53 +0000593 private void onHelpSrc() {
594 PrintWriter pw = getOutPrintWriter();
595 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800596 pw.println(" src set-test-enabled true|false");
597 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
598 pw.println(" The value could be true, false, or null(undefined).");
599 pw.println(" src get-test-enabled");
600 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000601 pw.println(" src set-device-enabled true|false|null");
602 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
603 pw.println(" The value could be true, false, or null(undefined).");
604 pw.println(" src get-device-enabled");
605 pw.println(" Gets the device config for RCS VoLTE single registration.");
606 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
607 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
608 pw.println(" The value could be true, false, or null(undefined).");
609 pw.println(" Options are:");
610 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
611 pw.println(" is specified, it will choose the default voice SIM slot.");
612 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
613 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
614 pw.println(" Options are:");
615 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
616 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800617 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
618 pw.println(" Sets ims feature validation result.");
619 pw.println(" The value could be true, false, or null(undefined).");
620 pw.println(" Options are:");
621 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
622 pw.println(" is specified, it will choose the default voice SIM slot.");
623 pw.println(" src get-feature-validation [-s SLOT_ID]");
624 pw.println(" Gets ims feature validation override value.");
625 pw.println(" Options are:");
626 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
627 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000628 }
629
SongFerngWang98dd5992021-05-13 17:50:00 +0800630 private void onHelpAllowedNetworkTypes() {
631 PrintWriter pw = getOutPrintWriter();
632 pw.println("Allowed Network Types Commands:");
633 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
634 pw.println(" Print allowed network types value.");
635 pw.println(" Options are:");
636 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
637 pw.println(" option is specified, it will choose the default voice SIM slot.");
638 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
639 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
640 pw.println(" Options are:");
641 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
642 pw.println(" option is specified, it will choose the default voice SIM slot.");
643 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
644 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
645 pw.println(" at TelephonyManager.java");
646 pw.println(" For example:");
647 pw.println(" NR only : 10000000000000000000");
648 pw.println(" NR|LTE : 11000001000000000000");
649 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
650 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
651 pw.println(" LTE only : 01000001000000000000");
652 }
653
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700654 private int handleImsCommand() {
655 String arg = getNextArg();
656 if (arg == null) {
657 onHelpIms();
658 return 0;
659 }
660
661 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800662 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700663 return handleImsSetServiceCommand();
664 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800665 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700666 return handleImsGetServiceCommand();
667 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800668 case IMS_CLEAR_SERVICE_OVERRIDE: {
669 return handleImsClearCarrierServiceCommand();
670 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800671 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700672 return handleEnableIms();
673 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800674 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700675 return handleDisableIms();
676 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700677 case IMS_CEP: {
678 return handleCepChange();
679 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700680 }
681
682 return -1;
683 }
684
Shuo Qianf5125122019-12-16 17:03:07 -0800685 private int handleDataTestModeCommand() {
686 PrintWriter errPw = getErrPrintWriter();
687 String arg = getNextArgRequired();
688 if (arg == null) {
689 onHelpDataTestMode();
690 return 0;
691 }
692 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800693 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800694 try {
695 mInterface.enableDataConnectivity();
696 } catch (RemoteException ex) {
697 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
698 errPw.println("Exception: " + ex.getMessage());
699 return -1;
700 }
701 break;
702 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800703 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800704 try {
705 mInterface.disableDataConnectivity();
706 } catch (RemoteException ex) {
707 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
708 errPw.println("Exception: " + ex.getMessage());
709 return -1;
710 }
711 break;
712 }
713 default:
714 onHelpDataTestMode();
715 break;
716 }
717 return 0;
718 }
719
Shuo Qianccbaf742021-02-22 18:32:21 -0800720 private int handleEmergencyCallbackModeCommand() {
721 PrintWriter errPw = getErrPrintWriter();
722 try {
723 mInterface.startEmergencyCallbackMode();
724 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
725 } catch (RemoteException ex) {
726 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
727 errPw.println("Exception: " + ex.getMessage());
728 return -1;
729 }
730 return 0;
731 }
732
sqian9d4df8b2019-01-15 18:32:07 -0800733 private int handleEmergencyNumberTestModeCommand() {
734 PrintWriter errPw = getErrPrintWriter();
735 String opt = getNextOption();
736 if (opt == null) {
737 onHelpEmergencyNumber();
738 return 0;
739 }
740
741 switch (opt) {
742 case "-a": {
743 String emergencyNumberCmd = getNextArgRequired();
744 if (emergencyNumberCmd == null
745 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700746 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800747 + " to be specified after -a in the command ");
748 return -1;
749 }
750 try {
751 mInterface.updateEmergencyNumberListTestMode(
752 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
753 new EmergencyNumber(emergencyNumberCmd, "", "",
754 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
755 new ArrayList<String>(),
756 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
757 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
758 } catch (RemoteException ex) {
759 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
760 + ", error " + ex.getMessage());
761 errPw.println("Exception: " + ex.getMessage());
762 return -1;
763 }
764 break;
765 }
766 case "-c": {
767 try {
768 mInterface.updateEmergencyNumberListTestMode(
769 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
770 } catch (RemoteException ex) {
771 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
772 errPw.println("Exception: " + ex.getMessage());
773 return -1;
774 }
775 break;
776 }
777 case "-r": {
778 String emergencyNumberCmd = getNextArgRequired();
779 if (emergencyNumberCmd == null
780 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700781 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800782 + " to be specified after -r in the command ");
783 return -1;
784 }
785 try {
786 mInterface.updateEmergencyNumberListTestMode(
787 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
788 new EmergencyNumber(emergencyNumberCmd, "", "",
789 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
790 new ArrayList<String>(),
791 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
792 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
793 } catch (RemoteException ex) {
794 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
795 + ", error " + ex.getMessage());
796 errPw.println("Exception: " + ex.getMessage());
797 return -1;
798 }
799 break;
800 }
801 case "-p": {
802 try {
803 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
804 } catch (RemoteException ex) {
805 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
806 errPw.println("Exception: " + ex.getMessage());
807 return -1;
808 }
809 break;
810 }
811 default:
812 onHelpEmergencyNumber();
813 break;
814 }
815 return 0;
816 }
817
Hall Liud892bec2018-11-30 14:51:45 -0800818 private int handleNumberVerificationCommand() {
819 String arg = getNextArg();
820 if (arg == null) {
821 onHelpNumberVerification();
822 return 0;
823 }
824
Hall Liuca5af3a2018-12-04 16:58:23 -0800825 if (!checkShellUid()) {
826 return -1;
827 }
828
Hall Liud892bec2018-11-30 14:51:45 -0800829 switch (arg) {
830 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800831 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
832 return 0;
833 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800834 case NUMBER_VERIFICATION_FAKE_CALL: {
835 boolean val = NumberVerificationManager.getInstance()
836 .checkIncomingCall(getNextArg());
837 getOutPrintWriter().println(val ? "1" : "0");
838 return 0;
839 }
Hall Liud892bec2018-11-30 14:51:45 -0800840 }
841
842 return -1;
843 }
844
Jordan Liu0ccee222021-04-27 11:55:13 -0700845 private boolean subIsEsim(int subId) {
846 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
847 if (info != null) {
848 return info.isEmbedded();
849 }
850 return false;
851 }
852
853 private int handleEnablePhysicalSubscription(boolean enable) {
854 PrintWriter errPw = getErrPrintWriter();
855 int subId = 0;
856 try {
857 subId = Integer.parseInt(getNextArgRequired());
858 } catch (NumberFormatException e) {
859 errPw.println((enable ? "enable" : "disable")
860 + "-physical-subscription requires an integer as a subId.");
861 return -1;
862 }
863 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
864 // non user build.
865 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
866 errPw.println("cc: Permission denied.");
867 return -1;
868 }
869 // Verify that the subId represents a physical sub
870 if (subIsEsim(subId)) {
871 errPw.println("SubId " + subId + " is not for a physical subscription");
872 return -1;
873 }
874 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
875 + " physical subscription with subId=" + subId);
876 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
877 return 0;
878 }
879
Jack Nudelman644b91a2021-03-12 14:09:48 -0800880 private int handleThermalMitigationCommand() {
881 String arg = getNextArg();
882 String packageName = getNextArg();
883 if (arg == null || packageName == null) {
884 onHelpThermalMitigation();
885 return 0;
886 }
887
888 if (!checkShellUid()) {
889 return -1;
890 }
891
892 switch (arg) {
893 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
894 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
895 return 0;
896 }
897 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
898 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
899 mContext);
900 return 0;
901 }
902 default:
903 onHelpThermalMitigation();
904 }
905
906 return -1;
907
908 }
909
Tyler Gunn92479152021-01-20 16:30:10 -0800910 private int handleD2dCommand() {
911 String arg = getNextArg();
912 if (arg == null) {
913 onHelpD2D();
914 return 0;
915 }
916
917 switch (arg) {
918 case D2D_SEND: {
919 return handleD2dSendCommand();
920 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800921 case D2D_TRANSPORT: {
922 return handleD2dTransportCommand();
923 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700924 case D2D_SET_DEVICE_SUPPORT: {
925 return handleD2dDeviceSupportedCommand();
926 }
Tyler Gunn92479152021-01-20 16:30:10 -0800927 }
928
929 return -1;
930 }
931
932 private int handleD2dSendCommand() {
933 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800934 int messageType = -1;
935 int messageValue = -1;
936
Tyler Gunn92479152021-01-20 16:30:10 -0800937 String arg = getNextArg();
938 if (arg == null) {
939 onHelpD2D();
940 return 0;
941 }
942 try {
943 messageType = Integer.parseInt(arg);
944 } catch (NumberFormatException e) {
945 errPw.println("message type must be a valid integer");
946 return -1;
947 }
948
949 arg = getNextArg();
950 if (arg == null) {
951 onHelpD2D();
952 return 0;
953 }
954 try {
955 messageValue = Integer.parseInt(arg);
956 } catch (NumberFormatException e) {
957 errPw.println("message value must be a valid integer");
958 return -1;
959 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800960
Tyler Gunn92479152021-01-20 16:30:10 -0800961 try {
962 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
963 } catch (RemoteException e) {
964 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
965 errPw.println("Exception: " + e.getMessage());
966 return -1;
967 }
968
969 return 0;
970 }
971
Tyler Gunnbabbda02021-02-10 11:05:02 -0800972 private int handleD2dTransportCommand() {
973 PrintWriter errPw = getErrPrintWriter();
974
975 String arg = getNextArg();
976 if (arg == null) {
977 onHelpD2D();
978 return 0;
979 }
980
981 try {
982 mInterface.setActiveDeviceToDeviceTransport(arg);
983 } catch (RemoteException e) {
984 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
985 errPw.println("Exception: " + e.getMessage());
986 return -1;
987 }
988 return 0;
989 }
Nazanin014f41e2021-05-06 17:26:31 -0700990 private int handleBarringCommand() {
991 String arg = getNextArg();
992 if (arg == null) {
993 onHelpBarring();
994 return 0;
995 }
996
997 switch (arg) {
998 case BARRING_SEND_INFO: {
999 return handleBarringSendCommand();
1000 }
1001 }
1002 return -1;
1003 }
1004
1005 private int handleBarringSendCommand() {
1006 PrintWriter errPw = getErrPrintWriter();
1007 int slotId = getDefaultSlot();
1008 int subId = SubscriptionManager.getSubId(slotId)[0];
1009 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1010 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1011 boolean isConditionallyBarred = false;
1012 int conditionalBarringTimeSeconds = 0;
1013
1014 String opt;
1015 while ((opt = getNextOption()) != null) {
1016 switch (opt) {
1017 case "-s": {
1018 try {
1019 slotId = Integer.parseInt(getNextArgRequired());
1020 subId = SubscriptionManager.getSubId(slotId)[0];
1021 } catch (NumberFormatException e) {
1022 errPw.println("barring send requires an integer as a SLOT_ID.");
1023 return -1;
1024 }
1025 break;
1026 }
1027 case "-b": {
1028 try {
1029 barringType = Integer.parseInt(getNextArgRequired());
1030 if (barringType < -1 || barringType > 2) {
1031 throw new NumberFormatException();
1032 }
1033
1034 } catch (NumberFormatException e) {
1035 errPw.println("barring send requires an integer in range [-1,2] as "
1036 + "a BARRING_TYPE.");
1037 return -1;
1038 }
1039 break;
1040 }
1041 case "-c": {
1042 try {
1043 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1044 } catch (Exception e) {
1045 errPw.println("barring send requires a boolean after -c indicating"
1046 + " conditional barring");
1047 return -1;
1048 }
1049 break;
1050 }
1051 case "-t": {
1052 try {
1053 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1054 } catch (NumberFormatException e) {
1055 errPw.println("barring send requires an integer for time of barring"
1056 + " in seconds after -t for conditional barring");
1057 return -1;
1058 }
1059 break;
1060 }
1061 }
1062 }
1063 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1064 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1065 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1066 barringServiceInfos.append(0, bsi);
1067 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1068 try {
1069 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1070 } catch (Exception e) {
1071 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1072 errPw.println("Exception: " + e.getMessage());
1073 return -1;
1074 }
1075 return 0;
1076 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001077
Tyler Gunnd4575212021-05-03 14:46:49 -07001078 private int handleD2dDeviceSupportedCommand() {
1079 PrintWriter errPw = getErrPrintWriter();
1080
1081 String arg = getNextArg();
1082 if (arg == null) {
1083 onHelpD2D();
1084 return 0;
1085 }
1086
1087 boolean isEnabled = "true".equals(arg.toLowerCase());
1088 try {
1089 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1090 } catch (RemoteException e) {
1091 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1092 errPw.println("Exception: " + e.getMessage());
1093 return -1;
1094 }
1095 return 0;
1096 }
1097
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001098 // ims set-ims-service
1099 private int handleImsSetServiceCommand() {
1100 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001101 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001102 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001103 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001104
1105 String opt;
1106 while ((opt = getNextOption()) != null) {
1107 switch (opt) {
1108 case "-s": {
1109 try {
1110 slotId = Integer.parseInt(getNextArgRequired());
1111 } catch (NumberFormatException e) {
1112 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1113 return -1;
1114 }
1115 break;
1116 }
1117 case "-c": {
1118 isCarrierService = true;
1119 break;
1120 }
1121 case "-d": {
1122 isCarrierService = false;
1123 break;
1124 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001125 case "-f": {
1126 String featureString = getNextArgRequired();
1127 String[] features = featureString.split(",");
1128 for (int i = 0; i < features.length; i++) {
1129 try {
1130 Integer result = Integer.parseInt(features[i]);
1131 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1132 || result >= ImsFeature.FEATURE_MAX) {
1133 errPw.println("ims set-ims-service -f " + result
1134 + " is an invalid feature.");
1135 return -1;
1136 }
1137 featuresList.add(result);
1138 } catch (NumberFormatException e) {
1139 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1140 + " as an integer.");
1141 return -1;
1142 }
1143 }
1144 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001145 }
1146 }
1147 // Mandatory param, either -c or -d
1148 if (isCarrierService == null) {
1149 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1150 return -1;
1151 }
1152
1153 String packageName = getNextArg();
1154
1155 try {
1156 if (packageName == null) {
1157 packageName = "";
1158 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001159 int[] featureArray = new int[featuresList.size()];
1160 for (int i = 0; i < featuresList.size(); i++) {
1161 featureArray[i] = featuresList.get(i);
1162 }
1163 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1164 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001165 if (VDBG) {
1166 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001167 + (isCarrierService ? "-c " : "-d ")
1168 + "-f " + featuresList + " "
1169 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001170 }
1171 getOutPrintWriter().println(result);
1172 } catch (RemoteException e) {
1173 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001174 + (isCarrierService ? "-c " : "-d ")
1175 + "-f " + featuresList + " "
1176 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001177 errPw.println("Exception: " + e.getMessage());
1178 return -1;
1179 }
1180 return 0;
1181 }
1182
Brad Ebinger999d3302020-11-25 14:31:39 -08001183 // ims clear-ims-service-override
1184 private int handleImsClearCarrierServiceCommand() {
1185 PrintWriter errPw = getErrPrintWriter();
1186 int slotId = getDefaultSlot();
1187
1188 String opt;
1189 while ((opt = getNextOption()) != null) {
1190 switch (opt) {
1191 case "-s": {
1192 try {
1193 slotId = Integer.parseInt(getNextArgRequired());
1194 } catch (NumberFormatException e) {
1195 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1196 return -1;
1197 }
1198 break;
1199 }
1200 }
1201 }
1202
1203 try {
1204 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1205 if (VDBG) {
1206 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1207 + ", result=" + result);
1208 }
1209 getOutPrintWriter().println(result);
1210 } catch (RemoteException e) {
1211 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1212 + ", error" + e.getMessage());
1213 errPw.println("Exception: " + e.getMessage());
1214 return -1;
1215 }
1216 return 0;
1217 }
1218
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001219 // ims get-ims-service
1220 private int handleImsGetServiceCommand() {
1221 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001222 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001223 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001224 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001225
1226 String opt;
1227 while ((opt = getNextOption()) != null) {
1228 switch (opt) {
1229 case "-s": {
1230 try {
1231 slotId = Integer.parseInt(getNextArgRequired());
1232 } catch (NumberFormatException e) {
1233 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1234 return -1;
1235 }
1236 break;
1237 }
1238 case "-c": {
1239 isCarrierService = true;
1240 break;
1241 }
1242 case "-d": {
1243 isCarrierService = false;
1244 break;
1245 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001246 case "-f": {
1247 try {
1248 featureType = Integer.parseInt(getNextArg());
1249 } catch (NumberFormatException e) {
1250 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1251 return -1;
1252 }
1253 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1254 || featureType >= ImsFeature.FEATURE_MAX) {
1255 errPw.println("ims get-ims-service -f invalid feature.");
1256 return -1;
1257 }
1258 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001259 }
1260 }
1261 // Mandatory param, either -c or -d
1262 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001263 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001264 return -1;
1265 }
1266
1267 String result;
1268 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001269 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001270 } catch (RemoteException e) {
1271 return -1;
1272 }
1273 if (VDBG) {
1274 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001275 + (isCarrierService ? "-c " : "-d ")
1276 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1277 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001278 }
1279 getOutPrintWriter().println(result);
1280 return 0;
1281 }
1282
1283 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001284 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001285 String opt;
1286 while ((opt = getNextOption()) != null) {
1287 switch (opt) {
1288 case "-s": {
1289 try {
1290 slotId = Integer.parseInt(getNextArgRequired());
1291 } catch (NumberFormatException e) {
1292 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1293 return -1;
1294 }
1295 break;
1296 }
1297 }
1298 }
1299 try {
1300 mInterface.enableIms(slotId);
1301 } catch (RemoteException e) {
1302 return -1;
1303 }
1304 if (VDBG) {
1305 Log.v(LOG_TAG, "ims enable -s " + slotId);
1306 }
1307 return 0;
1308 }
1309
1310 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001311 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001312 String opt;
1313 while ((opt = getNextOption()) != null) {
1314 switch (opt) {
1315 case "-s": {
1316 try {
1317 slotId = Integer.parseInt(getNextArgRequired());
1318 } catch (NumberFormatException e) {
1319 getErrPrintWriter().println(
1320 "ims disable requires an integer as a SLOT_ID.");
1321 return -1;
1322 }
1323 break;
1324 }
1325 }
1326 }
1327 try {
1328 mInterface.disableIms(slotId);
1329 } catch (RemoteException e) {
1330 return -1;
1331 }
1332 if (VDBG) {
1333 Log.v(LOG_TAG, "ims disable -s " + slotId);
1334 }
1335 return 0;
1336 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001337
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001338 private int handleCepChange() {
1339 Log.i(LOG_TAG, "handleCepChange");
1340 String opt = getNextArg();
1341 if (opt == null) {
1342 return -1;
1343 }
1344 boolean isCepEnabled = opt.equals("enable");
1345
1346 try {
1347 mInterface.setCepEnabled(isCepEnabled);
1348 } catch (RemoteException e) {
1349 return -1;
1350 }
1351 return 0;
1352 }
1353
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001354 private int getDefaultSlot() {
1355 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1356 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1357 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1358 // If there is no default, default to slot 0.
1359 slotId = DEFAULT_PHONE_ID;
1360 }
1361 return slotId;
1362 }
sqian2fff4a32018-11-05 14:18:37 -08001363
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001364 // Parse options related to Carrier Config Commands.
1365 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001366 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001367 CcOptionParseResult result = new CcOptionParseResult();
1368 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1369 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001370
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001371 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001372 while ((opt = getNextOption()) != null) {
1373 switch (opt) {
1374 case "-s": {
1375 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001376 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1377 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1378 errPw.println(tag + "No valid subscription found.");
1379 return null;
1380 }
1381
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001382 } catch (IllegalArgumentException e) {
1383 // Missing slot id
1384 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001385 return null;
1386 }
1387 break;
1388 }
1389 case "-p": {
1390 if (allowOptionPersistent) {
1391 result.mPersistent = true;
1392 } else {
1393 errPw.println(tag + "Unexpected option " + opt);
1394 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001395 }
1396 break;
1397 }
1398 default: {
1399 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001400 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001401 }
1402 }
1403 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001404 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001405 }
1406
1407 private int slotStringToSubId(String tag, String slotString) {
1408 int slotId = -1;
1409 try {
1410 slotId = Integer.parseInt(slotString);
1411 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001412 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1413 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1414 }
1415
1416 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001417 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1418 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1419 }
1420
Qiong Liuf25799b2020-09-10 10:13:46 +08001421 Phone phone = PhoneFactory.getPhone(slotId);
1422 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001423 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1424 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1425 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001426 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001427 }
1428
Hall Liud892bec2018-11-30 14:51:45 -08001429 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001430 // adb can run as root or as shell, depending on whether the device is rooted.
1431 return Binder.getCallingUid() == Process.SHELL_UID
1432 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001433 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001434
1435 private int handleCcCommand() {
1436 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1437 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001438 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001439 getErrPrintWriter().println("cc: Permission denied.");
1440 return -1;
1441 }
1442
1443 String arg = getNextArg();
1444 if (arg == null) {
1445 onHelpCc();
1446 return 0;
1447 }
1448
1449 switch (arg) {
1450 case CC_GET_VALUE: {
1451 return handleCcGetValue();
1452 }
1453 case CC_SET_VALUE: {
1454 return handleCcSetValue();
1455 }
1456 case CC_CLEAR_VALUES: {
1457 return handleCcClearValues();
1458 }
1459 default: {
1460 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1461 }
1462 }
1463 return -1;
1464 }
1465
1466 // cc get-value
1467 private int handleCcGetValue() {
1468 PrintWriter errPw = getErrPrintWriter();
1469 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1470 String key = null;
1471
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001472 // Parse all options
1473 CcOptionParseResult options = parseCcOptions(tag, false);
1474 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001475 return -1;
1476 }
1477
1478 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001479 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001480 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001481 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001482 return -1;
1483 }
1484
1485 // Get the key.
1486 key = getNextArg();
1487 if (key != null) {
1488 // A key was provided. Verify if it is a valid key
1489 if (!bundle.containsKey(key)) {
1490 errPw.println(tag + key + " is not a valid key.");
1491 return -1;
1492 }
1493
1494 // Print the carrier config value for key.
1495 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1496 } else {
1497 // No key provided. Show all values.
1498 // Iterate over a sorted list of all carrier config keys and print them.
1499 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1500 for (String k : sortedSet) {
1501 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1502 }
1503 }
1504 return 0;
1505 }
1506
1507 // cc set-value
1508 private int handleCcSetValue() {
1509 PrintWriter errPw = getErrPrintWriter();
1510 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1511
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001512 // Parse all options
1513 CcOptionParseResult options = parseCcOptions(tag, true);
1514 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001515 return -1;
1516 }
1517
1518 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001519 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001520 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001521 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001522 return -1;
1523 }
1524
1525 // Get the key.
1526 String key = getNextArg();
1527 if (key == null || key.equals("")) {
1528 errPw.println(tag + "KEY is missing");
1529 return -1;
1530 }
1531
1532 // Verify if the key is valid
1533 if (!originalValues.containsKey(key)) {
1534 errPw.println(tag + key + " is not a valid key.");
1535 return -1;
1536 }
1537
1538 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1539 ArrayList<String> valueList = new ArrayList<String>();
1540 while (peekNextArg() != null) {
1541 valueList.add(getNextArg());
1542 }
1543
1544 // Find the type of the carrier config value
1545 CcType type = getType(tag, key, originalValues);
1546 if (type == CcType.UNKNOWN) {
1547 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1548 return -1;
1549 }
1550
1551 // Create an override bundle containing the key and value that should be overriden.
1552 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1553 if (overrideBundle == null) {
1554 return -1;
1555 }
1556
1557 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001558 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001559
1560 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001561 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001562 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001563 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001564 return -1;
1565 }
1566
1567 // Print the original and new value.
1568 String originalValueString = ccValueToString(key, type, originalValues);
1569 String newValueString = ccValueToString(key, type, newValues);
1570 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1571 getOutPrintWriter().println("New value: \n" + newValueString);
1572
1573 return 0;
1574 }
1575
1576 // cc clear-values
1577 private int handleCcClearValues() {
1578 PrintWriter errPw = getErrPrintWriter();
1579 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1580
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001581 // Parse all options
1582 CcOptionParseResult options = parseCcOptions(tag, false);
1583 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001584 return -1;
1585 }
1586
1587 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001588 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001589 getOutPrintWriter()
1590 .println("All previously set carrier config override values has been cleared");
1591 return 0;
1592 }
1593
1594 private CcType getType(String tag, String key, PersistableBundle bundle) {
1595 // Find the type by checking the type of the current value stored in the bundle.
1596 Object value = bundle.get(key);
1597
1598 if (CC_TYPE_MAP.containsKey(key)) {
1599 return CC_TYPE_MAP.get(key);
1600 } else if (value != null) {
1601 if (value instanceof Boolean) {
1602 return CcType.BOOLEAN;
1603 } else if (value instanceof Double) {
1604 return CcType.DOUBLE;
1605 } else if (value instanceof double[]) {
1606 return CcType.DOUBLE_ARRAY;
1607 } else if (value instanceof Integer) {
1608 return CcType.INT;
1609 } else if (value instanceof int[]) {
1610 return CcType.INT_ARRAY;
1611 } else if (value instanceof Long) {
1612 return CcType.LONG;
1613 } else if (value instanceof long[]) {
1614 return CcType.LONG_ARRAY;
1615 } else if (value instanceof String) {
1616 return CcType.STRING;
1617 } else if (value instanceof String[]) {
1618 return CcType.STRING_ARRAY;
1619 }
1620 } else {
1621 // Current value was null and can therefore not be used in order to find the type.
1622 // Check the name of the key to infer the type. This check is not needed for primitive
1623 // data types (boolean, double, int and long), since they can not be null.
1624 if (key.endsWith("double_array")) {
1625 return CcType.DOUBLE_ARRAY;
1626 }
1627 if (key.endsWith("int_array")) {
1628 return CcType.INT_ARRAY;
1629 }
1630 if (key.endsWith("long_array")) {
1631 return CcType.LONG_ARRAY;
1632 }
1633 if (key.endsWith("string")) {
1634 return CcType.STRING;
1635 }
1636 if (key.endsWith("string_array") || key.endsWith("strings")) {
1637 return CcType.STRING_ARRAY;
1638 }
1639 }
1640
1641 // Not possible to infer the type by looking at the current value or the key.
1642 PrintWriter errPw = getErrPrintWriter();
1643 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1644 return CcType.UNKNOWN;
1645 }
1646
1647 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1648 String result;
1649 StringBuilder valueString = new StringBuilder();
1650 String typeString = type.toString();
1651 Object value = bundle.get(key);
1652
1653 if (value == null) {
1654 valueString.append("null");
1655 } else {
1656 switch (type) {
1657 case DOUBLE_ARRAY: {
1658 // Format the string representation of the int array as value1 value2......
1659 double[] valueArray = (double[]) value;
1660 for (int i = 0; i < valueArray.length; i++) {
1661 if (i != 0) {
1662 valueString.append(" ");
1663 }
1664 valueString.append(valueArray[i]);
1665 }
1666 break;
1667 }
1668 case INT_ARRAY: {
1669 // Format the string representation of the int array as value1 value2......
1670 int[] valueArray = (int[]) value;
1671 for (int i = 0; i < valueArray.length; i++) {
1672 if (i != 0) {
1673 valueString.append(" ");
1674 }
1675 valueString.append(valueArray[i]);
1676 }
1677 break;
1678 }
1679 case LONG_ARRAY: {
1680 // Format the string representation of the int array as value1 value2......
1681 long[] valueArray = (long[]) value;
1682 for (int i = 0; i < valueArray.length; i++) {
1683 if (i != 0) {
1684 valueString.append(" ");
1685 }
1686 valueString.append(valueArray[i]);
1687 }
1688 break;
1689 }
1690 case STRING: {
1691 valueString.append("\"" + value.toString() + "\"");
1692 break;
1693 }
1694 case STRING_ARRAY: {
1695 // Format the string representation of the string array as "value1" "value2"....
1696 String[] valueArray = (String[]) value;
1697 for (int i = 0; i < valueArray.length; i++) {
1698 if (i != 0) {
1699 valueString.append(" ");
1700 }
1701 if (valueArray[i] != null) {
1702 valueString.append("\"" + valueArray[i] + "\"");
1703 } else {
1704 valueString.append("null");
1705 }
1706 }
1707 break;
1708 }
1709 default: {
1710 valueString.append(value.toString());
1711 }
1712 }
1713 }
1714 return String.format("%-70s %-15s %s", key, typeString, valueString);
1715 }
1716
1717 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1718 ArrayList<String> valueList) {
1719 PrintWriter errPw = getErrPrintWriter();
1720 PersistableBundle bundle = new PersistableBundle();
1721
1722 // First verify that a valid number of values has been provided for the type.
1723 switch (type) {
1724 case BOOLEAN:
1725 case DOUBLE:
1726 case INT:
1727 case LONG: {
1728 if (valueList.size() != 1) {
1729 errPw.println(tag + "Expected 1 value for type " + type
1730 + ". Found: " + valueList.size());
1731 return null;
1732 }
1733 break;
1734 }
1735 case STRING: {
1736 if (valueList.size() > 1) {
1737 errPw.println(tag + "Expected 0 or 1 values for type " + type
1738 + ". Found: " + valueList.size());
1739 return null;
1740 }
1741 break;
1742 }
1743 }
1744
1745 // Parse the value according to type and add it to the Bundle.
1746 switch (type) {
1747 case BOOLEAN: {
1748 if ("true".equalsIgnoreCase(valueList.get(0))) {
1749 bundle.putBoolean(key, true);
1750 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1751 bundle.putBoolean(key, false);
1752 } else {
1753 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1754 return null;
1755 }
1756 break;
1757 }
1758 case DOUBLE: {
1759 try {
1760 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1761 } catch (NumberFormatException nfe) {
1762 // Not a valid double
1763 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1764 return null;
1765 }
1766 break;
1767 }
1768 case DOUBLE_ARRAY: {
1769 double[] valueDoubleArray = null;
1770 if (valueList.size() > 0) {
1771 valueDoubleArray = new double[valueList.size()];
1772 for (int i = 0; i < valueList.size(); i++) {
1773 try {
1774 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1775 } catch (NumberFormatException nfe) {
1776 // Not a valid double
1777 errPw.println(
1778 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1779 return null;
1780 }
1781 }
1782 }
1783 bundle.putDoubleArray(key, valueDoubleArray);
1784 break;
1785 }
1786 case INT: {
1787 try {
1788 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1789 } catch (NumberFormatException nfe) {
1790 // Not a valid integer
1791 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1792 return null;
1793 }
1794 break;
1795 }
1796 case INT_ARRAY: {
1797 int[] valueIntArray = null;
1798 if (valueList.size() > 0) {
1799 valueIntArray = new int[valueList.size()];
1800 for (int i = 0; i < valueList.size(); i++) {
1801 try {
1802 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1803 } catch (NumberFormatException nfe) {
1804 // Not a valid integer
1805 errPw.println(tag
1806 + "Unable to parse " + valueList.get(i) + " as an integer.");
1807 return null;
1808 }
1809 }
1810 }
1811 bundle.putIntArray(key, valueIntArray);
1812 break;
1813 }
1814 case LONG: {
1815 try {
1816 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1817 } catch (NumberFormatException nfe) {
1818 // Not a valid long
1819 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1820 return null;
1821 }
1822 break;
1823 }
1824 case LONG_ARRAY: {
1825 long[] valueLongArray = null;
1826 if (valueList.size() > 0) {
1827 valueLongArray = new long[valueList.size()];
1828 for (int i = 0; i < valueList.size(); i++) {
1829 try {
1830 valueLongArray[i] = Long.parseLong(valueList.get(i));
1831 } catch (NumberFormatException nfe) {
1832 // Not a valid long
1833 errPw.println(
1834 tag + "Unable to parse " + valueList.get(i) + " as a long");
1835 return null;
1836 }
1837 }
1838 }
1839 bundle.putLongArray(key, valueLongArray);
1840 break;
1841 }
1842 case STRING: {
1843 String value = null;
1844 if (valueList.size() > 0) {
1845 value = valueList.get(0);
1846 }
1847 bundle.putString(key, value);
1848 break;
1849 }
1850 case STRING_ARRAY: {
1851 String[] valueStringArray = null;
1852 if (valueList.size() > 0) {
1853 valueStringArray = new String[valueList.size()];
1854 valueList.toArray(valueStringArray);
1855 }
1856 bundle.putStringArray(key, valueStringArray);
1857 break;
1858 }
1859 }
1860 return bundle;
1861 }
Shuo Qian489d9282020-07-09 11:30:03 -07001862
1863 private int handleEndBlockSuppressionCommand() {
1864 if (!checkShellUid()) {
1865 return -1;
1866 }
1867
1868 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1869 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1870 }
1871 return 0;
1872 }
Hui Wang641e81c2020-10-12 12:14:23 -07001873
Michele Berionne54af4632020-12-28 20:23:16 +00001874 private int handleRestartModemCommand() {
1875 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1876 // non user build.
1877 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1878 getErrPrintWriter().println("RestartModem: Permission denied.");
1879 return -1;
1880 }
1881
1882 boolean result = TelephonyManager.getDefault().rebootRadio();
1883 getOutPrintWriter().println(result);
1884
1885 return result ? 0 : -1;
1886 }
1887
Michele Berionne5e411512020-11-13 02:36:59 +00001888 private int handleUnattendedReboot() {
1889 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1890 // non user build.
1891 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1892 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1893 return -1;
1894 }
1895
1896 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1897 getOutPrintWriter().println("result: " + result);
1898
1899 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1900 }
1901
Hui Wang641e81c2020-10-12 12:14:23 -07001902 private int handleGbaCommand() {
1903 String arg = getNextArg();
1904 if (arg == null) {
1905 onHelpGba();
1906 return 0;
1907 }
1908
1909 switch (arg) {
1910 case GBA_SET_SERVICE: {
1911 return handleGbaSetServiceCommand();
1912 }
1913 case GBA_GET_SERVICE: {
1914 return handleGbaGetServiceCommand();
1915 }
1916 case GBA_SET_RELEASE_TIME: {
1917 return handleGbaSetReleaseCommand();
1918 }
1919 case GBA_GET_RELEASE_TIME: {
1920 return handleGbaGetReleaseCommand();
1921 }
1922 }
1923
1924 return -1;
1925 }
1926
1927 private int getSubId(String cmd) {
1928 int slotId = getDefaultSlot();
1929 String opt = getNextOption();
1930 if (opt != null && opt.equals("-s")) {
1931 try {
1932 slotId = Integer.parseInt(getNextArgRequired());
1933 } catch (NumberFormatException e) {
1934 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1935 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1936 }
1937 }
1938 int[] subIds = SubscriptionManager.getSubId(slotId);
1939 return subIds[0];
1940 }
1941
1942 private int handleGbaSetServiceCommand() {
1943 int subId = getSubId("gba set-service");
1944 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1945 return -1;
1946 }
1947
1948 String packageName = getNextArg();
1949 try {
1950 if (packageName == null) {
1951 packageName = "";
1952 }
1953 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1954 if (VDBG) {
1955 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1956 + packageName + ", result=" + result);
1957 }
1958 getOutPrintWriter().println(result);
1959 } catch (RemoteException e) {
1960 Log.w(LOG_TAG, "gba set-service " + subId + " "
1961 + packageName + ", error" + e.getMessage());
1962 getErrPrintWriter().println("Exception: " + e.getMessage());
1963 return -1;
1964 }
1965 return 0;
1966 }
1967
1968 private int handleGbaGetServiceCommand() {
1969 String result;
1970
1971 int subId = getSubId("gba get-service");
1972 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1973 return -1;
1974 }
1975
1976 try {
1977 result = mInterface.getBoundGbaService(subId);
1978 } catch (RemoteException e) {
1979 return -1;
1980 }
1981 if (VDBG) {
1982 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1983 }
1984 getOutPrintWriter().println(result);
1985 return 0;
1986 }
1987
1988 private int handleGbaSetReleaseCommand() {
1989 //the release time value could be -1
1990 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1991 : SubscriptionManager.getDefaultSubscriptionId();
1992 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1993 return -1;
1994 }
1995
1996 String intervalStr = getNextArg();
1997 if (intervalStr == null) {
1998 return -1;
1999 }
2000
2001 try {
2002 int interval = Integer.parseInt(intervalStr);
2003 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2004 if (VDBG) {
2005 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2006 + intervalStr + ", result=" + result);
2007 }
2008 getOutPrintWriter().println(result);
2009 } catch (NumberFormatException | RemoteException e) {
2010 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2011 + intervalStr + ", error" + e.getMessage());
2012 getErrPrintWriter().println("Exception: " + e.getMessage());
2013 return -1;
2014 }
2015 return 0;
2016 }
2017
2018 private int handleGbaGetReleaseCommand() {
2019 int subId = getSubId("gba get-release");
2020 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2021 return -1;
2022 }
2023
2024 int result = 0;
2025 try {
2026 result = mInterface.getGbaReleaseTime(subId);
2027 } catch (RemoteException e) {
2028 return -1;
2029 }
2030 if (VDBG) {
2031 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2032 }
2033 getOutPrintWriter().println(result);
2034 return 0;
2035 }
Hui Wang761a6682020-10-31 05:12:53 +00002036
2037 private int handleSingleRegistrationConfigCommand() {
2038 String arg = getNextArg();
2039 if (arg == null) {
2040 onHelpSrc();
2041 return 0;
2042 }
2043
2044 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002045 case SRC_SET_TEST_ENABLED: {
2046 return handleSrcSetTestEnabledCommand();
2047 }
2048 case SRC_GET_TEST_ENABLED: {
2049 return handleSrcGetTestEnabledCommand();
2050 }
Hui Wang761a6682020-10-31 05:12:53 +00002051 case SRC_SET_DEVICE_ENABLED: {
2052 return handleSrcSetDeviceEnabledCommand();
2053 }
2054 case SRC_GET_DEVICE_ENABLED: {
2055 return handleSrcGetDeviceEnabledCommand();
2056 }
2057 case SRC_SET_CARRIER_ENABLED: {
2058 return handleSrcSetCarrierEnabledCommand();
2059 }
2060 case SRC_GET_CARRIER_ENABLED: {
2061 return handleSrcGetCarrierEnabledCommand();
2062 }
Hui Wangb647abe2021-02-26 09:33:38 -08002063 case SRC_SET_FEATURE_ENABLED: {
2064 return handleSrcSetFeatureValidationCommand();
2065 }
2066 case SRC_GET_FEATURE_ENABLED: {
2067 return handleSrcGetFeatureValidationCommand();
2068 }
Hui Wang761a6682020-10-31 05:12:53 +00002069 }
2070
2071 return -1;
2072 }
2073
James.cf Linbcdf8b32021-01-14 16:44:13 +08002074 private int handleRcsUceCommand() {
2075 String arg = getNextArg();
2076 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002077 onHelpUce();
2078 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002079 }
2080
2081 switch (arg) {
2082 case UCE_REMOVE_EAB_CONTACT:
2083 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002084 case UCE_GET_EAB_CONTACT:
2085 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002086 case UCE_GET_DEVICE_ENABLED:
2087 return handleUceGetDeviceEnabledCommand();
2088 case UCE_SET_DEVICE_ENABLED:
2089 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002090 case UCE_OVERRIDE_PUBLISH_CAPS:
2091 return handleUceOverridePublishCaps();
2092 case UCE_GET_LAST_PIDF_XML:
2093 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002094 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2095 return handleUceRemoveRequestDisallowedStatus();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002096 }
2097 return -1;
2098 }
2099
2100 private int handleRemovingEabContactCommand() {
2101 int subId = getSubId("uce remove-eab-contact");
2102 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2103 return -1;
2104 }
2105
2106 String phoneNumber = getNextArgRequired();
2107 if (TextUtils.isEmpty(phoneNumber)) {
2108 return -1;
2109 }
2110 int result = 0;
2111 try {
2112 result = mInterface.removeContactFromEab(subId, phoneNumber);
2113 } catch (RemoteException e) {
2114 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2115 getErrPrintWriter().println("Exception: " + e.getMessage());
2116 return -1;
2117 }
2118
2119 if (VDBG) {
2120 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2121 }
calvinpan293ea1b2021-02-04 17:52:13 +08002122 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002123 }
2124
calvinpane4a8a1d2021-01-25 13:51:18 +08002125 private int handleGettingEabContactCommand() {
2126 String phoneNumber = getNextArgRequired();
2127 if (TextUtils.isEmpty(phoneNumber)) {
2128 return -1;
2129 }
2130 String result = "";
2131 try {
2132 result = mInterface.getContactFromEab(phoneNumber);
2133
2134 } catch (RemoteException e) {
2135 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2136 getErrPrintWriter().println("Exception: " + e.getMessage());
2137 return -1;
2138 }
2139
2140 if (VDBG) {
2141 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2142 }
calvinpan293ea1b2021-02-04 17:52:13 +08002143 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002144 return 0;
2145 }
2146
2147 private int handleUceGetDeviceEnabledCommand() {
2148 boolean result = false;
2149 try {
2150 result = mInterface.getDeviceUceEnabled();
2151 } catch (RemoteException e) {
2152 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2153 return -1;
2154 }
2155 if (VDBG) {
2156 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2157 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002158 getOutPrintWriter().println(result);
2159 return 0;
2160 }
2161
James.cf Lin4b784aa2021-01-31 03:25:15 +08002162 private int handleUceSetDeviceEnabledCommand() {
2163 String enabledStr = getNextArg();
2164 if (TextUtils.isEmpty(enabledStr)) {
2165 return -1;
2166 }
2167
2168 try {
2169 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2170 mInterface.setDeviceUceEnabled(isEnabled);
2171 if (VDBG) {
2172 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2173 }
2174 } catch (NumberFormatException | RemoteException e) {
2175 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2176 getErrPrintWriter().println("Exception: " + e.getMessage());
2177 return -1;
2178 }
2179 return 0;
2180 }
2181
James.cf Line8713a42021-04-29 16:04:26 +08002182 private int handleUceRemoveRequestDisallowedStatus() {
2183 int subId = getSubId("uce remove-request-disallowed-status");
2184 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2185 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2186 return -1;
2187 }
2188 boolean result;
2189 try {
2190 result = mInterface.removeUceRequestDisallowedStatus(subId);
2191 } catch (RemoteException e) {
2192 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2193 return -1;
2194 }
2195 if (VDBG) {
2196 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2197 }
2198 getOutPrintWriter().println(result);
2199 return 0;
2200 }
2201
Hui Wangbaaee6a2021-02-19 20:45:36 -08002202 private int handleSrcSetTestEnabledCommand() {
2203 String enabledStr = getNextArg();
2204 if (enabledStr == null) {
2205 return -1;
2206 }
2207
2208 try {
2209 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2210 if (VDBG) {
2211 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2212 }
2213 getOutPrintWriter().println("Done");
2214 } catch (NumberFormatException | RemoteException e) {
2215 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2216 getErrPrintWriter().println("Exception: " + e.getMessage());
2217 return -1;
2218 }
2219 return 0;
2220 }
2221
2222 private int handleSrcGetTestEnabledCommand() {
2223 boolean result = false;
2224 try {
2225 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2226 } catch (RemoteException e) {
2227 return -1;
2228 }
2229 if (VDBG) {
2230 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2231 }
2232 getOutPrintWriter().println(result);
2233 return 0;
2234 }
2235
Brad Ebinger14d467f2021-02-12 06:18:28 +00002236 private int handleUceOverridePublishCaps() {
2237 int subId = getSubId("uce override-published-caps");
2238 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2239 return -1;
2240 }
2241 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2242 String operation = getNextArgRequired();
2243 String caps = getNextArg();
2244 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2245 && !"list".equals(operation)) {
2246 getErrPrintWriter().println("Invalid operation: " + operation);
2247 return -1;
2248 }
2249
2250 // add/remove requires capabilities to be specified.
2251 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2252 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2253 + "specified");
2254 return -1;
2255 }
2256
2257 ArraySet<String> capSet = new ArraySet<>();
2258 if (!TextUtils.isEmpty(caps)) {
2259 String[] capArray = caps.split(":");
2260 for (String cap : capArray) {
2261 // Allow unknown tags to be passed in as well.
2262 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2263 }
2264 }
2265
2266 RcsContactUceCapability result = null;
2267 try {
2268 switch (operation) {
2269 case "add":
2270 result = mInterface.addUceRegistrationOverrideShell(subId,
2271 new ArrayList<>(capSet));
2272 break;
2273 case "remove":
2274 result = mInterface.removeUceRegistrationOverrideShell(subId,
2275 new ArrayList<>(capSet));
2276 break;
2277 case "clear":
2278 result = mInterface.clearUceRegistrationOverrideShell(subId);
2279 break;
2280 case "list":
2281 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2282 break;
2283 }
2284 } catch (RemoteException e) {
2285 Log.w(LOG_TAG, "uce override-published-caps, 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 override-published-caps, 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
2303 private int handleUceGetPidfXml() {
2304 int subId = getSubId("uce get-last-publish-pidf");
2305 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2306 return -1;
2307 }
2308
2309 String result;
2310 try {
2311 result = mInterface.getLastUcePidfXmlShell(subId);
2312 } catch (RemoteException e) {
2313 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2314 getErrPrintWriter().println("Exception: " + e.getMessage());
2315 return -1;
2316 } catch (ServiceSpecificException sse) {
2317 // Reconstruct ImsException
2318 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2319 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2320 getErrPrintWriter().println("Exception: " + imsException);
2321 return -1;
2322 }
2323 if (result == null) {
2324 getErrPrintWriter().println("Service not available");
2325 return -1;
2326 }
2327 getOutPrintWriter().println(result);
2328 return 0;
2329 }
2330
Hui Wang761a6682020-10-31 05:12:53 +00002331 private int handleSrcSetDeviceEnabledCommand() {
2332 String enabledStr = getNextArg();
2333 if (enabledStr == null) {
2334 return -1;
2335 }
2336
2337 try {
2338 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2339 if (VDBG) {
2340 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2341 }
2342 getOutPrintWriter().println("Done");
2343 } catch (NumberFormatException | RemoteException e) {
2344 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2345 getErrPrintWriter().println("Exception: " + e.getMessage());
2346 return -1;
2347 }
2348 return 0;
2349 }
2350
2351 private int handleSrcGetDeviceEnabledCommand() {
2352 boolean result = false;
2353 try {
2354 result = mInterface.getDeviceSingleRegistrationEnabled();
2355 } catch (RemoteException e) {
2356 return -1;
2357 }
2358 if (VDBG) {
2359 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2360 }
2361 getOutPrintWriter().println(result);
2362 return 0;
2363 }
2364
2365 private int handleSrcSetCarrierEnabledCommand() {
2366 //the release time value could be -1
2367 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2368 : SubscriptionManager.getDefaultSubscriptionId();
2369 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2370 return -1;
2371 }
2372
2373 String enabledStr = getNextArg();
2374 if (enabledStr == null) {
2375 return -1;
2376 }
2377
2378 try {
2379 boolean result =
2380 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2381 if (VDBG) {
2382 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2383 + enabledStr + ", result=" + result);
2384 }
2385 getOutPrintWriter().println(result);
2386 } catch (NumberFormatException | RemoteException e) {
2387 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2388 + enabledStr + ", error" + e.getMessage());
2389 getErrPrintWriter().println("Exception: " + e.getMessage());
2390 return -1;
2391 }
2392 return 0;
2393 }
2394
2395 private int handleSrcGetCarrierEnabledCommand() {
2396 int subId = getSubId("src get-carrier-enabled");
2397 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2398 return -1;
2399 }
2400
2401 boolean result = false;
2402 try {
2403 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2404 } catch (RemoteException e) {
2405 return -1;
2406 }
2407 if (VDBG) {
2408 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2409 }
2410 getOutPrintWriter().println(result);
2411 return 0;
2412 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002413
Hui Wangb647abe2021-02-26 09:33:38 -08002414 private int handleSrcSetFeatureValidationCommand() {
2415 //the release time value could be -1
2416 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2417 : SubscriptionManager.getDefaultSubscriptionId();
2418 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2419 return -1;
2420 }
2421
2422 String enabledStr = getNextArg();
2423 if (enabledStr == null) {
2424 return -1;
2425 }
2426
2427 try {
2428 boolean result =
2429 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2430 if (VDBG) {
2431 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2432 + enabledStr + ", result=" + result);
2433 }
2434 getOutPrintWriter().println(result);
2435 } catch (NumberFormatException | RemoteException e) {
2436 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2437 + enabledStr + ", error" + e.getMessage());
2438 getErrPrintWriter().println("Exception: " + e.getMessage());
2439 return -1;
2440 }
2441 return 0;
2442 }
2443
2444 private int handleSrcGetFeatureValidationCommand() {
2445 int subId = getSubId("src get-feature-validation");
2446 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2447 return -1;
2448 }
2449
2450 Boolean result = false;
2451 try {
2452 result = mInterface.getImsFeatureValidationOverride(subId);
2453 } catch (RemoteException e) {
2454 return -1;
2455 }
2456 if (VDBG) {
2457 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2458 }
2459 getOutPrintWriter().println(result);
2460 return 0;
2461 }
2462
2463
Hall Liuaa4211e2021-01-20 15:43:39 -08002464 private void onHelpCallComposer() {
2465 PrintWriter pw = getOutPrintWriter();
2466 pw.println("Call composer commands");
2467 pw.println(" callcomposer test-mode enable|disable|query");
2468 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2469 pw.println(" upload/download from carrier servers is disabled, and operations are");
2470 pw.println(" performed using emulated local files instead.");
2471 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2472 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2473 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002474 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2475 pw.println(" Enables or disables the user setting for call composer, as set by");
2476 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002477 }
2478
2479 private int handleCallComposerCommand() {
2480 String arg = getNextArg();
2481 if (arg == null) {
2482 onHelpCallComposer();
2483 return 0;
2484 }
2485
2486 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2487 "MODIFY_PHONE_STATE required for call composer shell cmds");
2488 switch (arg) {
2489 case CALL_COMPOSER_TEST_MODE: {
2490 String enabledStr = getNextArg();
2491 if (ENABLE.equals(enabledStr)) {
2492 CallComposerPictureManager.sTestMode = true;
2493 } else if (DISABLE.equals(enabledStr)) {
2494 CallComposerPictureManager.sTestMode = false;
2495 } else if (QUERY.equals(enabledStr)) {
2496 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2497 } else {
2498 onHelpCallComposer();
2499 return 1;
2500 }
2501 break;
2502 }
2503 case CALL_COMPOSER_SIMULATE_CALL: {
2504 int subscriptionId = Integer.valueOf(getNextArg());
2505 String uuidString = getNextArg();
2506 UUID uuid = UUID.fromString(uuidString);
2507 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2508 Binder.withCleanCallingIdentity(() -> {
2509 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2510 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2511 });
2512 try {
2513 Uri uri = storageUriFuture.get();
2514 getOutPrintWriter().println(String.valueOf(uri));
2515 } catch (Exception e) {
2516 throw new RuntimeException(e);
2517 }
2518 break;
2519 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002520 case CALL_COMPOSER_USER_SETTING: {
2521 try {
2522 int subscriptionId = Integer.valueOf(getNextArg());
2523 String enabledStr = getNextArg();
2524 if (ENABLE.equals(enabledStr)) {
2525 mInterface.setCallComposerStatus(subscriptionId,
2526 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2527 } else if (DISABLE.equals(enabledStr)) {
2528 mInterface.setCallComposerStatus(subscriptionId,
2529 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2530 } else if (QUERY.equals(enabledStr)) {
2531 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2532 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2533 } else {
2534 onHelpCallComposer();
2535 return 1;
2536 }
2537 } catch (RemoteException e) {
2538 e.printStackTrace(getOutPrintWriter());
2539 return 1;
2540 }
2541 break;
2542 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002543 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002544 return 0;
2545 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002546
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002547 private int handleHasCarrierPrivilegesCommand() {
2548 String packageName = getNextArgRequired();
2549
2550 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002551 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002552 try {
2553 hasCarrierPrivileges =
2554 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2555 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2556 } catch (RemoteException e) {
2557 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2558 getErrPrintWriter().println("Exception: " + e.getMessage());
2559 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002560 } finally {
2561 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002562 }
2563
2564 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002565 return 0;
2566 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002567
2568 private int handleAllowedNetworkTypesCommand(String command) {
2569 if (!checkShellUid()) {
2570 return -1;
2571 }
2572
2573 PrintWriter errPw = getErrPrintWriter();
2574 String tag = command + ": ";
2575 String opt;
2576 int subId = -1;
2577 Log.v(LOG_TAG, command + " start");
2578
2579 while ((opt = getNextOption()) != null) {
2580 if (opt.equals("-s")) {
2581 try {
2582 subId = slotStringToSubId(tag, getNextArgRequired());
2583 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2584 errPw.println(tag + "No valid subscription found.");
2585 return -1;
2586 }
2587 } catch (IllegalArgumentException e) {
2588 // Missing slot id
2589 errPw.println(tag + "SLOT_ID expected after -s.");
2590 return -1;
2591 }
2592 } else {
2593 errPw.println(tag + "Unknown option " + opt);
2594 return -1;
2595 }
2596 }
2597
2598 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2599 return handleGetAllowedNetworkTypesCommand(subId);
2600 }
2601 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2602 return handleSetAllowedNetworkTypesCommand(subId);
2603 }
2604 return -1;
2605 }
2606
2607 private int handleGetAllowedNetworkTypesCommand(int subId) {
2608 PrintWriter errPw = getErrPrintWriter();
2609
2610 long result = -1;
2611 try {
2612 if (mInterface != null) {
2613 result = mInterface.getAllowedNetworkTypesForReason(subId,
2614 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2615 } else {
2616 throw new IllegalStateException("telephony service is null.");
2617 }
2618 } catch (RemoteException e) {
2619 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2620 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2621 return -1;
2622 }
2623
2624 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2625 return 0;
2626 }
2627
2628 private int handleSetAllowedNetworkTypesCommand(int subId) {
2629 PrintWriter errPw = getErrPrintWriter();
2630
2631 String bitmaskString = getNextArg();
2632 if (TextUtils.isEmpty(bitmaskString)) {
2633 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2634 return -1;
2635 }
2636 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2637 if (allowedNetworkTypes < 0) {
2638 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2639 return -1;
2640 }
2641 boolean result = false;
2642 try {
2643 if (mInterface != null) {
2644 result = mInterface.setAllowedNetworkTypesForReason(subId,
2645 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2646 } else {
2647 throw new IllegalStateException("telephony service is null.");
2648 }
2649 } catch (RemoteException e) {
2650 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2651 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2652 return -1;
2653 }
2654
2655 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2656 if (result) {
2657 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2658 }
2659 getOutPrintWriter().println(resultMessage);
2660 return 0;
2661 }
2662
2663 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2664 if (TextUtils.isEmpty(bitmaskString)) {
2665 return -1;
2666 }
2667 if (VDBG) {
2668 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2669 + ", length: " + bitmaskString.length());
2670 }
2671 try {
2672 return Long.parseLong(bitmaskString, 2);
2673 } catch (NumberFormatException e) {
2674 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2675 return -1;
2676 }
2677 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002678}