blob: 3042aa308f2f2f9f678e1e3ab211805585a70b14 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000031import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070032import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070033import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010034import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070035import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000037import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070038import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080039import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000040import android.telephony.ims.ImsException;
41import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080042import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080043import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000044import android.util.ArrayMap;
45import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070046import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070047import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
Brad Ebinger14d467f2021-02-12 06:18:28 +000049import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080051import com.android.internal.telephony.Phone;
52import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080053import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080054import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080055import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080056import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080057import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070058
59import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080060import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000061import java.util.Arrays;
62import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010063import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080064import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010065import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010067import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080068import java.util.UUID;
69import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070070
71/**
72 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
73 * permission checks have been done before onCommand was called. Make sure any commands processed
74 * here also contain the appropriate permissions checks.
75 */
76
Hall Liua1548bd2019-12-24 14:14:12 -080077public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070078
79 private static final String LOG_TAG = "TelephonyShellCommand";
80 // Don't commit with this true.
81 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070082 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
Hall Liuaa4211e2021-01-20 15:43:39 -080084 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080086 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080087 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080088 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070089 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000090 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000091 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010092 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080093 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080094 private static final String ENABLE = "enable";
95 private static final String DISABLE = "disable";
96 private static final String QUERY = "query";
97
Hall Liu7135e502021-02-04 16:58:17 -080098 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800100 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800101
Brad Ebinger999d3302020-11-25 14:31:39 -0800102 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
103 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
104 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700105 // Used to disable or enable processing of conference event package data from the network.
106 // This is handy for testing scenarios where CEP data does not exist on a network which does
107 // support CEP data.
108 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700109
Hall Liud892bec2018-11-30 14:51:45 -0800110 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800111 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100113 private static final String CC_GET_VALUE = "get-value";
114 private static final String CC_SET_VALUE = "set-value";
115 private static final String CC_CLEAR_VALUES = "clear-values";
116
Hui Wang641e81c2020-10-12 12:14:23 -0700117 private static final String GBA_SUBCOMMAND = "gba";
118 private static final String GBA_SET_SERVICE = "set-service";
119 private static final String GBA_GET_SERVICE = "get-service";
120 private static final String GBA_SET_RELEASE_TIME = "set-release";
121 private static final String GBA_GET_RELEASE_TIME = "get-release";
122
Hui Wang761a6682020-10-31 05:12:53 +0000123 private static final String SINGLE_REGISTATION_CONFIG = "src";
124 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
125 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
126 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
127 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800128 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
129 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800130 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
131 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000132
Tyler Gunn92479152021-01-20 16:30:10 -0800133 private static final String D2D_SUBCOMMAND = "d2d";
134 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800135 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800136
Nazanin014f41e2021-05-06 17:26:31 -0700137 private static final String BARRING_SUBCOMMAND = "barring";
138 private static final String BARRING_SEND_INFO = "send";
139
James.cf Linbcdf8b32021-01-14 16:44:13 +0800140 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800141 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800142 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800143 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
144 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000145 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
146 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800147
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800148 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
149 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
150
Jordan Liu0ccee222021-04-27 11:55:13 -0700151 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
152 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
153
Jack Nudelman644b91a2021-03-12 14:09:48 -0800154 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
155 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
156 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
157
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700158 // Take advantage of existing methods that already contain permissions checks when possible.
159 private final ITelephony mInterface;
160
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100161 private SubscriptionManager mSubscriptionManager;
162 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700163 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700164 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100165
166 private enum CcType {
167 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
168 STRING_ARRAY, UNKNOWN
169 }
170
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100171 private class CcOptionParseResult {
172 public int mSubId;
173 public boolean mPersistent;
174 }
175
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100176 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
177 // keys by looking at the end of the string which usually tells the type.
178 // For instance: "xxxx_string", "xxxx_string_array", etc.
179 // The carrier config keys in this map does not follow this convention. It is therefore not
180 // possible to infer the type for these keys by looking at the string.
181 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
182 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
183 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
184 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
185 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
186 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
187 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
188 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
189 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
190 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
191 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
192 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
193 CcType.STRING);
194 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
195 CcType.STRING_ARRAY);
196 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
197 CcType.STRING_ARRAY);
198 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
199 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
200 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
201 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
202 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
203 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
204 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
205 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
206 }
207 };
208
Brad Ebinger14d467f2021-02-12 06:18:28 +0000209 /**
210 * Map from a shorthand string to the feature tags required in registration required in order
211 * for the RCS feature to be considered "capable".
212 */
213 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
214 static {
215 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
216 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
217 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
218 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
219 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
220 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
221 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
222 FeatureTags.FEATURE_TAG_VIDEO)));
223 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
224 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
225 map.put("call_comp",
226 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
227 map.put("call_comp_mmtel",
228 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
229 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
230 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
231 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
232 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
233 // version
234 map.put("chatbot", new ArraySet<>(Arrays.asList(
235 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
236 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
237 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
238 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
239 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
240 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
241 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
242 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
243 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
244 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
245 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
246 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
247 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
248 }
249
250
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100251 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700252 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100253 mCarrierConfigManager =
254 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
255 mSubscriptionManager = (SubscriptionManager)
256 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700257 mTelephonyRegistryManager = (TelephonyRegistryManager)
258 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700259 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700260 }
261
262 @Override
263 public int onCommand(String cmd) {
264 if (cmd == null) {
265 return handleDefaultCommands(null);
266 }
267
268 switch (cmd) {
269 case IMS_SUBCOMMAND: {
270 return handleImsCommand();
271 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800272 case RCS_UCE_COMMAND:
273 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800274 case NUMBER_VERIFICATION_SUBCOMMAND:
275 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800276 case EMERGENCY_CALLBACK_MODE:
277 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800278 case EMERGENCY_NUMBER_TEST_MODE:
279 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100280 case CARRIER_CONFIG_SUBCOMMAND: {
281 return handleCcCommand();
282 }
Shuo Qianf5125122019-12-16 17:03:07 -0800283 case DATA_TEST_MODE:
284 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700285 case END_BLOCK_SUPPRESSION:
286 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700287 case GBA_SUBCOMMAND:
288 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800289 case D2D_SUBCOMMAND:
290 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700291 case BARRING_SUBCOMMAND:
292 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000293 case SINGLE_REGISTATION_CONFIG:
294 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000295 case RESTART_MODEM:
296 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800297 case CALL_COMPOSER_SUBCOMMAND:
298 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000299 case UNATTENDED_REBOOT:
300 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800301 case HAS_CARRIER_PRIVILEGES_COMMAND:
302 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800303 case THERMAL_MITIGATION_COMMAND:
304 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700305 case DISABLE_PHYSICAL_SUBSCRIPTION:
306 return handleEnablePhysicalSubscription(false);
307 case ENABLE_PHYSICAL_SUBSCRIPTION:
308 return handleEnablePhysicalSubscription(true);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700309 default: {
310 return handleDefaultCommands(cmd);
311 }
312 }
313 }
314
315 @Override
316 public void onHelp() {
317 PrintWriter pw = getOutPrintWriter();
318 pw.println("Telephony Commands:");
319 pw.println(" help");
320 pw.println(" Print this help text.");
321 pw.println(" ims");
322 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800323 pw.println(" uce");
324 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800325 pw.println(" emergency-number-test-mode");
326 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700327 pw.println(" end-block-suppression");
328 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800329 pw.println(" data");
330 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100331 pw.println(" cc");
332 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700333 pw.println(" gba");
334 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000335 pw.println(" src");
336 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000337 pw.println(" restart-modem");
338 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000339 pw.println(" unattended-reboot");
340 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800341 pw.println(" has-carrier-privileges [package]");
342 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700343 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800344 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800345 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700346 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800347 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100348 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700349 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000350 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800351 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700352 onHelpDisableOrEnablePhysicalSubscription();
Tyler Gunn92479152021-01-20 16:30:10 -0800353 }
354
355 private void onHelpD2D() {
356 PrintWriter pw = getOutPrintWriter();
357 pw.println("D2D Comms Commands:");
358 pw.println(" d2d send TYPE VALUE");
359 pw.println(" Sends a D2D message of specified type and value.");
360 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
361 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
362 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
363 MESSAGE_CALL_AUDIO_CODEC));
364 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
365 + Communicator.messageToString(
366 MESSAGE_DEVICE_BATTERY_STATE));
367 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
368 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800369 pw.println(" d2d transport TYPE");
370 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
371 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700372 }
373
Nazanin014f41e2021-05-06 17:26:31 -0700374 private void onHelpBarring() {
375 PrintWriter pw = getOutPrintWriter();
376 pw.println("Barring Commands:");
377 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
378 + " -t CONDITIONAL_BARRING_TIME_SECS");
379 pw.println(" Notifies of a barring info change for the specified slot id.");
380 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
381 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
382 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
383 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
384 }
385
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700386 private void onHelpIms() {
387 PrintWriter pw = getOutPrintWriter();
388 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800389 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700390 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
391 pw.println(" ImsService. Options are:");
392 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
393 pw.println(" is specified, it will choose the default voice SIM slot.");
394 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
395 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800396 pw.println(" -f: Set the feature that this override if for, if no option is");
397 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700398 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
399 pw.println(" Gets the package name of the currently defined ImsService.");
400 pw.println(" Options are:");
401 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
402 pw.println(" is specified, it will choose the default voice SIM slot.");
403 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000404 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800405 pw.println(" -f: The feature type that the query will be requested for. If none is");
406 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800407 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
408 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
409 pw.println(" configuration overrides. Options are:");
410 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
411 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700412 pw.println(" ims enable [-s SLOT_ID]");
413 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
414 pw.println(" if none is specified.");
415 pw.println(" ims disable [-s SLOT_ID]");
416 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
417 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700418 pw.println(" ims conference-event-package [enable/disable]");
419 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700420 }
421
James.cf Linbcdf8b32021-01-14 16:44:13 +0800422 private void onHelpUce() {
423 PrintWriter pw = getOutPrintWriter();
424 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800425 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
426 pw.println(" Get the EAB contacts from the EAB database.");
427 pw.println(" Options are:");
428 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
429 pw.println(" Expected output format :");
430 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800431 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
432 pw.println(" Remove the EAB contacts from the EAB database.");
433 pw.println(" Options are:");
434 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
435 pw.println(" is specified, it will choose the default voice SIM slot.");
436 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800437 pw.println(" uce get-device-enabled");
438 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
439 pw.println(" uce set-device-enabled true|false");
440 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
441 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000442 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
443 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
444 pw.println(" Options are:");
445 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
446 pw.println(" is specified, it will choose the default voice SIM slot.");
447 pw.println(" add [CAPABILITY]: add a new capability");
448 pw.println(" remove [CAPABILITY]: remove a capability");
449 pw.println(" clear: clear all capability overrides");
450 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
451 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
452 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
453 pw.println(" chatbot_sa, chatbot_role] as well as full length");
454 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
455 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
456 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
457 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800458 }
459
Hall Liud892bec2018-11-30 14:51:45 -0800460 private void onHelpNumberVerification() {
461 PrintWriter pw = getOutPrintWriter();
462 pw.println("Number verification commands");
463 pw.println(" numverify override-package PACKAGE_NAME;");
464 pw.println(" Set the authorized package for number verification.");
465 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800466 pw.println(" numverify fake-call NUMBER;");
467 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
468 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800469 }
470
Jack Nudelman644b91a2021-03-12 14:09:48 -0800471 private void onHelpThermalMitigation() {
472 PrintWriter pw = getOutPrintWriter();
473 pw.println("Thermal mitigation commands");
474 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
475 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
476 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
477 pw.println(" Remove the package from one of the authorized packages for thermal "
478 + "mitigation.");
479 }
480
Jordan Liu0ccee222021-04-27 11:55:13 -0700481 private void onHelpDisableOrEnablePhysicalSubscription() {
482 PrintWriter pw = getOutPrintWriter();
483 pw.println("Disable or enable a physical subscription");
484 pw.println(" disable-physical-subscription SUB_ID");
485 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
486 pw.println(" enable-physical-subscription SUB_ID");
487 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
488 }
489
Shuo Qianf5125122019-12-16 17:03:07 -0800490 private void onHelpDataTestMode() {
491 PrintWriter pw = getOutPrintWriter();
492 pw.println("Mobile Data Test Mode Commands:");
493 pw.println(" data enable: enable mobile data connectivity");
494 pw.println(" data disable: disable mobile data connectivity");
495 }
496
sqian9d4df8b2019-01-15 18:32:07 -0800497 private void onHelpEmergencyNumber() {
498 PrintWriter pw = getOutPrintWriter();
499 pw.println("Emergency Number Test Mode Commands:");
500 pw.println(" emergency-number-test-mode ");
501 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
502 + " the test mode");
503 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700504 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800505 pw.println(" -c: clear the emergency number list in the test mode.");
506 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700507 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800508 pw.println(" -p: get the full emergency number list in the test mode.");
509 }
510
Shuo Qian489d9282020-07-09 11:30:03 -0700511 private void onHelpEndBlockSupperssion() {
512 PrintWriter pw = getOutPrintWriter();
513 pw.println("End Block Suppression command:");
514 pw.println(" end-block-suppression: disable suppressing blocking by contact");
515 pw.println(" with emergency services.");
516 }
517
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100518 private void onHelpCc() {
519 PrintWriter pw = getOutPrintWriter();
520 pw.println("Carrier Config Commands:");
521 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
522 pw.println(" Print carrier config values.");
523 pw.println(" Options are:");
524 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
525 pw.println(" is specified, it will choose the default voice SIM slot.");
526 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
527 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100528 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100529 pw.println(" Set carrier config KEY to NEW_VALUE.");
530 pw.println(" Options are:");
531 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
532 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100533 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100534 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
535 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
536 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
537 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
538 pw.println(" cc clear-values [-s SLOT_ID]");
539 pw.println(" Clear all carrier override values that has previously been set");
540 pw.println(" with set-value");
541 pw.println(" Options are:");
542 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
543 pw.println(" is specified, it will choose the default voice SIM slot.");
544 }
545
Hui Wang641e81c2020-10-12 12:14:23 -0700546 private void onHelpGba() {
547 PrintWriter pw = getOutPrintWriter();
548 pw.println("Gba Commands:");
549 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
550 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
551 pw.println(" Options are:");
552 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
553 pw.println(" is specified, it will choose the default voice SIM slot.");
554 pw.println(" gba get-service [-s SLOT_ID]");
555 pw.println(" Gets the package name of the currently defined GbaService.");
556 pw.println(" Options are:");
557 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
558 pw.println(" is specified, it will choose the default voice SIM slot.");
559 pw.println(" gba set-release [-s SLOT_ID] n");
560 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
561 pw.println(" Do not release/unbind if n is -1.");
562 pw.println(" Options are:");
563 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
564 pw.println(" is specified, it will choose the default voice SIM slot.");
565 pw.println(" gba get-release [-s SLOT_ID]");
566 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
567 pw.println(" Options are:");
568 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
569 pw.println(" is specified, it will choose the default voice SIM slot.");
570 }
571
Hui Wang761a6682020-10-31 05:12:53 +0000572 private void onHelpSrc() {
573 PrintWriter pw = getOutPrintWriter();
574 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800575 pw.println(" src set-test-enabled true|false");
576 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
577 pw.println(" The value could be true, false, or null(undefined).");
578 pw.println(" src get-test-enabled");
579 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000580 pw.println(" src set-device-enabled true|false|null");
581 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
582 pw.println(" The value could be true, false, or null(undefined).");
583 pw.println(" src get-device-enabled");
584 pw.println(" Gets the device config for RCS VoLTE single registration.");
585 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
586 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
587 pw.println(" The value could be true, false, or null(undefined).");
588 pw.println(" Options are:");
589 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
590 pw.println(" is specified, it will choose the default voice SIM slot.");
591 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
592 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
593 pw.println(" Options are:");
594 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
595 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800596 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
597 pw.println(" Sets ims feature validation result.");
598 pw.println(" The value could be true, false, or null(undefined).");
599 pw.println(" Options are:");
600 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
601 pw.println(" is specified, it will choose the default voice SIM slot.");
602 pw.println(" src get-feature-validation [-s SLOT_ID]");
603 pw.println(" Gets ims feature validation override value.");
604 pw.println(" Options are:");
605 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
606 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000607 }
608
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700609 private int handleImsCommand() {
610 String arg = getNextArg();
611 if (arg == null) {
612 onHelpIms();
613 return 0;
614 }
615
616 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800617 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700618 return handleImsSetServiceCommand();
619 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800620 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700621 return handleImsGetServiceCommand();
622 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800623 case IMS_CLEAR_SERVICE_OVERRIDE: {
624 return handleImsClearCarrierServiceCommand();
625 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800626 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700627 return handleEnableIms();
628 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800629 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700630 return handleDisableIms();
631 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700632 case IMS_CEP: {
633 return handleCepChange();
634 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700635 }
636
637 return -1;
638 }
639
Shuo Qianf5125122019-12-16 17:03:07 -0800640 private int handleDataTestModeCommand() {
641 PrintWriter errPw = getErrPrintWriter();
642 String arg = getNextArgRequired();
643 if (arg == null) {
644 onHelpDataTestMode();
645 return 0;
646 }
647 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800648 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800649 try {
650 mInterface.enableDataConnectivity();
651 } catch (RemoteException ex) {
652 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
653 errPw.println("Exception: " + ex.getMessage());
654 return -1;
655 }
656 break;
657 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800658 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800659 try {
660 mInterface.disableDataConnectivity();
661 } catch (RemoteException ex) {
662 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
663 errPw.println("Exception: " + ex.getMessage());
664 return -1;
665 }
666 break;
667 }
668 default:
669 onHelpDataTestMode();
670 break;
671 }
672 return 0;
673 }
674
Shuo Qianccbaf742021-02-22 18:32:21 -0800675 private int handleEmergencyCallbackModeCommand() {
676 PrintWriter errPw = getErrPrintWriter();
677 try {
678 mInterface.startEmergencyCallbackMode();
679 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
680 } catch (RemoteException ex) {
681 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
682 errPw.println("Exception: " + ex.getMessage());
683 return -1;
684 }
685 return 0;
686 }
687
sqian9d4df8b2019-01-15 18:32:07 -0800688 private int handleEmergencyNumberTestModeCommand() {
689 PrintWriter errPw = getErrPrintWriter();
690 String opt = getNextOption();
691 if (opt == null) {
692 onHelpEmergencyNumber();
693 return 0;
694 }
695
696 switch (opt) {
697 case "-a": {
698 String emergencyNumberCmd = getNextArgRequired();
699 if (emergencyNumberCmd == null
700 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700701 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800702 + " to be specified after -a in the command ");
703 return -1;
704 }
705 try {
706 mInterface.updateEmergencyNumberListTestMode(
707 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
708 new EmergencyNumber(emergencyNumberCmd, "", "",
709 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
710 new ArrayList<String>(),
711 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
712 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
713 } catch (RemoteException ex) {
714 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
715 + ", error " + ex.getMessage());
716 errPw.println("Exception: " + ex.getMessage());
717 return -1;
718 }
719 break;
720 }
721 case "-c": {
722 try {
723 mInterface.updateEmergencyNumberListTestMode(
724 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
725 } catch (RemoteException ex) {
726 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
727 errPw.println("Exception: " + ex.getMessage());
728 return -1;
729 }
730 break;
731 }
732 case "-r": {
733 String emergencyNumberCmd = getNextArgRequired();
734 if (emergencyNumberCmd == null
735 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700736 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800737 + " to be specified after -r in the command ");
738 return -1;
739 }
740 try {
741 mInterface.updateEmergencyNumberListTestMode(
742 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
743 new EmergencyNumber(emergencyNumberCmd, "", "",
744 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
745 new ArrayList<String>(),
746 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
747 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
748 } catch (RemoteException ex) {
749 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
750 + ", error " + ex.getMessage());
751 errPw.println("Exception: " + ex.getMessage());
752 return -1;
753 }
754 break;
755 }
756 case "-p": {
757 try {
758 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
759 } catch (RemoteException ex) {
760 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
761 errPw.println("Exception: " + ex.getMessage());
762 return -1;
763 }
764 break;
765 }
766 default:
767 onHelpEmergencyNumber();
768 break;
769 }
770 return 0;
771 }
772
Hall Liud892bec2018-11-30 14:51:45 -0800773 private int handleNumberVerificationCommand() {
774 String arg = getNextArg();
775 if (arg == null) {
776 onHelpNumberVerification();
777 return 0;
778 }
779
Hall Liuca5af3a2018-12-04 16:58:23 -0800780 if (!checkShellUid()) {
781 return -1;
782 }
783
Hall Liud892bec2018-11-30 14:51:45 -0800784 switch (arg) {
785 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800786 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
787 return 0;
788 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800789 case NUMBER_VERIFICATION_FAKE_CALL: {
790 boolean val = NumberVerificationManager.getInstance()
791 .checkIncomingCall(getNextArg());
792 getOutPrintWriter().println(val ? "1" : "0");
793 return 0;
794 }
Hall Liud892bec2018-11-30 14:51:45 -0800795 }
796
797 return -1;
798 }
799
Jordan Liu0ccee222021-04-27 11:55:13 -0700800 private boolean subIsEsim(int subId) {
801 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
802 if (info != null) {
803 return info.isEmbedded();
804 }
805 return false;
806 }
807
808 private int handleEnablePhysicalSubscription(boolean enable) {
809 PrintWriter errPw = getErrPrintWriter();
810 int subId = 0;
811 try {
812 subId = Integer.parseInt(getNextArgRequired());
813 } catch (NumberFormatException e) {
814 errPw.println((enable ? "enable" : "disable")
815 + "-physical-subscription requires an integer as a subId.");
816 return -1;
817 }
818 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
819 // non user build.
820 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
821 errPw.println("cc: Permission denied.");
822 return -1;
823 }
824 // Verify that the subId represents a physical sub
825 if (subIsEsim(subId)) {
826 errPw.println("SubId " + subId + " is not for a physical subscription");
827 return -1;
828 }
829 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
830 + " physical subscription with subId=" + subId);
831 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
832 return 0;
833 }
834
Jack Nudelman644b91a2021-03-12 14:09:48 -0800835 private int handleThermalMitigationCommand() {
836 String arg = getNextArg();
837 String packageName = getNextArg();
838 if (arg == null || packageName == null) {
839 onHelpThermalMitigation();
840 return 0;
841 }
842
843 if (!checkShellUid()) {
844 return -1;
845 }
846
847 switch (arg) {
848 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
849 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
850 return 0;
851 }
852 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
853 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
854 mContext);
855 return 0;
856 }
857 default:
858 onHelpThermalMitigation();
859 }
860
861 return -1;
862
863 }
864
Tyler Gunn92479152021-01-20 16:30:10 -0800865 private int handleD2dCommand() {
866 String arg = getNextArg();
867 if (arg == null) {
868 onHelpD2D();
869 return 0;
870 }
871
872 switch (arg) {
873 case D2D_SEND: {
874 return handleD2dSendCommand();
875 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800876 case D2D_TRANSPORT: {
877 return handleD2dTransportCommand();
878 }
Tyler Gunn92479152021-01-20 16:30:10 -0800879 }
880
881 return -1;
882 }
883
884 private int handleD2dSendCommand() {
885 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800886 int messageType = -1;
887 int messageValue = -1;
888
Tyler Gunn92479152021-01-20 16:30:10 -0800889 String arg = getNextArg();
890 if (arg == null) {
891 onHelpD2D();
892 return 0;
893 }
894 try {
895 messageType = Integer.parseInt(arg);
896 } catch (NumberFormatException e) {
897 errPw.println("message type must be a valid integer");
898 return -1;
899 }
900
901 arg = getNextArg();
902 if (arg == null) {
903 onHelpD2D();
904 return 0;
905 }
906 try {
907 messageValue = Integer.parseInt(arg);
908 } catch (NumberFormatException e) {
909 errPw.println("message value must be a valid integer");
910 return -1;
911 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800912
Tyler Gunn92479152021-01-20 16:30:10 -0800913 try {
914 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
915 } catch (RemoteException e) {
916 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
917 errPw.println("Exception: " + e.getMessage());
918 return -1;
919 }
920
921 return 0;
922 }
923
Tyler Gunnbabbda02021-02-10 11:05:02 -0800924 private int handleD2dTransportCommand() {
925 PrintWriter errPw = getErrPrintWriter();
926
927 String arg = getNextArg();
928 if (arg == null) {
929 onHelpD2D();
930 return 0;
931 }
932
933 try {
934 mInterface.setActiveDeviceToDeviceTransport(arg);
935 } catch (RemoteException e) {
936 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
937 errPw.println("Exception: " + e.getMessage());
938 return -1;
939 }
940 return 0;
941 }
Nazanin014f41e2021-05-06 17:26:31 -0700942 private int handleBarringCommand() {
943 String arg = getNextArg();
944 if (arg == null) {
945 onHelpBarring();
946 return 0;
947 }
948
949 switch (arg) {
950 case BARRING_SEND_INFO: {
951 return handleBarringSendCommand();
952 }
953 }
954 return -1;
955 }
956
957 private int handleBarringSendCommand() {
958 PrintWriter errPw = getErrPrintWriter();
959 int slotId = getDefaultSlot();
960 int subId = SubscriptionManager.getSubId(slotId)[0];
961 @BarringInfo.BarringServiceInfo.BarringType int barringType =
962 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
963 boolean isConditionallyBarred = false;
964 int conditionalBarringTimeSeconds = 0;
965
966 String opt;
967 while ((opt = getNextOption()) != null) {
968 switch (opt) {
969 case "-s": {
970 try {
971 slotId = Integer.parseInt(getNextArgRequired());
972 subId = SubscriptionManager.getSubId(slotId)[0];
973 } catch (NumberFormatException e) {
974 errPw.println("barring send requires an integer as a SLOT_ID.");
975 return -1;
976 }
977 break;
978 }
979 case "-b": {
980 try {
981 barringType = Integer.parseInt(getNextArgRequired());
982 if (barringType < -1 || barringType > 2) {
983 throw new NumberFormatException();
984 }
985
986 } catch (NumberFormatException e) {
987 errPw.println("barring send requires an integer in range [-1,2] as "
988 + "a BARRING_TYPE.");
989 return -1;
990 }
991 break;
992 }
993 case "-c": {
994 try {
995 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
996 } catch (Exception e) {
997 errPw.println("barring send requires a boolean after -c indicating"
998 + " conditional barring");
999 return -1;
1000 }
1001 break;
1002 }
1003 case "-t": {
1004 try {
1005 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1006 } catch (NumberFormatException e) {
1007 errPw.println("barring send requires an integer for time of barring"
1008 + " in seconds after -t for conditional barring");
1009 return -1;
1010 }
1011 break;
1012 }
1013 }
1014 }
1015 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1016 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1017 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1018 barringServiceInfos.append(0, bsi);
1019 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1020 try {
1021 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1022 } catch (Exception e) {
1023 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1024 errPw.println("Exception: " + e.getMessage());
1025 return -1;
1026 }
1027 return 0;
1028 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001029
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001030 // ims set-ims-service
1031 private int handleImsSetServiceCommand() {
1032 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001033 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001034 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001035 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001036
1037 String opt;
1038 while ((opt = getNextOption()) != null) {
1039 switch (opt) {
1040 case "-s": {
1041 try {
1042 slotId = Integer.parseInt(getNextArgRequired());
1043 } catch (NumberFormatException e) {
1044 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1045 return -1;
1046 }
1047 break;
1048 }
1049 case "-c": {
1050 isCarrierService = true;
1051 break;
1052 }
1053 case "-d": {
1054 isCarrierService = false;
1055 break;
1056 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001057 case "-f": {
1058 String featureString = getNextArgRequired();
1059 String[] features = featureString.split(",");
1060 for (int i = 0; i < features.length; i++) {
1061 try {
1062 Integer result = Integer.parseInt(features[i]);
1063 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1064 || result >= ImsFeature.FEATURE_MAX) {
1065 errPw.println("ims set-ims-service -f " + result
1066 + " is an invalid feature.");
1067 return -1;
1068 }
1069 featuresList.add(result);
1070 } catch (NumberFormatException e) {
1071 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1072 + " as an integer.");
1073 return -1;
1074 }
1075 }
1076 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001077 }
1078 }
1079 // Mandatory param, either -c or -d
1080 if (isCarrierService == null) {
1081 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1082 return -1;
1083 }
1084
1085 String packageName = getNextArg();
1086
1087 try {
1088 if (packageName == null) {
1089 packageName = "";
1090 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001091 int[] featureArray = new int[featuresList.size()];
1092 for (int i = 0; i < featuresList.size(); i++) {
1093 featureArray[i] = featuresList.get(i);
1094 }
1095 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1096 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001097 if (VDBG) {
1098 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001099 + (isCarrierService ? "-c " : "-d ")
1100 + "-f " + featuresList + " "
1101 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001102 }
1103 getOutPrintWriter().println(result);
1104 } catch (RemoteException e) {
1105 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001106 + (isCarrierService ? "-c " : "-d ")
1107 + "-f " + featuresList + " "
1108 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001109 errPw.println("Exception: " + e.getMessage());
1110 return -1;
1111 }
1112 return 0;
1113 }
1114
Brad Ebinger999d3302020-11-25 14:31:39 -08001115 // ims clear-ims-service-override
1116 private int handleImsClearCarrierServiceCommand() {
1117 PrintWriter errPw = getErrPrintWriter();
1118 int slotId = getDefaultSlot();
1119
1120 String opt;
1121 while ((opt = getNextOption()) != null) {
1122 switch (opt) {
1123 case "-s": {
1124 try {
1125 slotId = Integer.parseInt(getNextArgRequired());
1126 } catch (NumberFormatException e) {
1127 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1128 return -1;
1129 }
1130 break;
1131 }
1132 }
1133 }
1134
1135 try {
1136 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1137 if (VDBG) {
1138 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1139 + ", result=" + result);
1140 }
1141 getOutPrintWriter().println(result);
1142 } catch (RemoteException e) {
1143 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1144 + ", error" + e.getMessage());
1145 errPw.println("Exception: " + e.getMessage());
1146 return -1;
1147 }
1148 return 0;
1149 }
1150
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001151 // ims get-ims-service
1152 private int handleImsGetServiceCommand() {
1153 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001154 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001155 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001156 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001157
1158 String opt;
1159 while ((opt = getNextOption()) != null) {
1160 switch (opt) {
1161 case "-s": {
1162 try {
1163 slotId = Integer.parseInt(getNextArgRequired());
1164 } catch (NumberFormatException e) {
1165 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1166 return -1;
1167 }
1168 break;
1169 }
1170 case "-c": {
1171 isCarrierService = true;
1172 break;
1173 }
1174 case "-d": {
1175 isCarrierService = false;
1176 break;
1177 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001178 case "-f": {
1179 try {
1180 featureType = Integer.parseInt(getNextArg());
1181 } catch (NumberFormatException e) {
1182 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1183 return -1;
1184 }
1185 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1186 || featureType >= ImsFeature.FEATURE_MAX) {
1187 errPw.println("ims get-ims-service -f invalid feature.");
1188 return -1;
1189 }
1190 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001191 }
1192 }
1193 // Mandatory param, either -c or -d
1194 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001195 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001196 return -1;
1197 }
1198
1199 String result;
1200 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001201 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001202 } catch (RemoteException e) {
1203 return -1;
1204 }
1205 if (VDBG) {
1206 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001207 + (isCarrierService ? "-c " : "-d ")
1208 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1209 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001210 }
1211 getOutPrintWriter().println(result);
1212 return 0;
1213 }
1214
1215 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001216 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001217 String opt;
1218 while ((opt = getNextOption()) != null) {
1219 switch (opt) {
1220 case "-s": {
1221 try {
1222 slotId = Integer.parseInt(getNextArgRequired());
1223 } catch (NumberFormatException e) {
1224 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1225 return -1;
1226 }
1227 break;
1228 }
1229 }
1230 }
1231 try {
1232 mInterface.enableIms(slotId);
1233 } catch (RemoteException e) {
1234 return -1;
1235 }
1236 if (VDBG) {
1237 Log.v(LOG_TAG, "ims enable -s " + slotId);
1238 }
1239 return 0;
1240 }
1241
1242 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001243 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001244 String opt;
1245 while ((opt = getNextOption()) != null) {
1246 switch (opt) {
1247 case "-s": {
1248 try {
1249 slotId = Integer.parseInt(getNextArgRequired());
1250 } catch (NumberFormatException e) {
1251 getErrPrintWriter().println(
1252 "ims disable requires an integer as a SLOT_ID.");
1253 return -1;
1254 }
1255 break;
1256 }
1257 }
1258 }
1259 try {
1260 mInterface.disableIms(slotId);
1261 } catch (RemoteException e) {
1262 return -1;
1263 }
1264 if (VDBG) {
1265 Log.v(LOG_TAG, "ims disable -s " + slotId);
1266 }
1267 return 0;
1268 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001269
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001270 private int handleCepChange() {
1271 Log.i(LOG_TAG, "handleCepChange");
1272 String opt = getNextArg();
1273 if (opt == null) {
1274 return -1;
1275 }
1276 boolean isCepEnabled = opt.equals("enable");
1277
1278 try {
1279 mInterface.setCepEnabled(isCepEnabled);
1280 } catch (RemoteException e) {
1281 return -1;
1282 }
1283 return 0;
1284 }
1285
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001286 private int getDefaultSlot() {
1287 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1288 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1289 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1290 // If there is no default, default to slot 0.
1291 slotId = DEFAULT_PHONE_ID;
1292 }
1293 return slotId;
1294 }
sqian2fff4a32018-11-05 14:18:37 -08001295
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001296 // Parse options related to Carrier Config Commands.
1297 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001298 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001299 CcOptionParseResult result = new CcOptionParseResult();
1300 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1301 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001302
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001303 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001304 while ((opt = getNextOption()) != null) {
1305 switch (opt) {
1306 case "-s": {
1307 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001308 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1309 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1310 errPw.println(tag + "No valid subscription found.");
1311 return null;
1312 }
1313
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001314 } catch (IllegalArgumentException e) {
1315 // Missing slot id
1316 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001317 return null;
1318 }
1319 break;
1320 }
1321 case "-p": {
1322 if (allowOptionPersistent) {
1323 result.mPersistent = true;
1324 } else {
1325 errPw.println(tag + "Unexpected option " + opt);
1326 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001327 }
1328 break;
1329 }
1330 default: {
1331 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001332 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001333 }
1334 }
1335 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001336 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001337 }
1338
1339 private int slotStringToSubId(String tag, String slotString) {
1340 int slotId = -1;
1341 try {
1342 slotId = Integer.parseInt(slotString);
1343 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001344 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1345 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1346 }
1347
1348 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001349 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1350 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1351 }
1352
Qiong Liuf25799b2020-09-10 10:13:46 +08001353 Phone phone = PhoneFactory.getPhone(slotId);
1354 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001355 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1356 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1357 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001358 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001359 }
1360
Hall Liud892bec2018-11-30 14:51:45 -08001361 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001362 // adb can run as root or as shell, depending on whether the device is rooted.
1363 return Binder.getCallingUid() == Process.SHELL_UID
1364 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001365 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001366
1367 private int handleCcCommand() {
1368 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1369 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001370 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001371 getErrPrintWriter().println("cc: Permission denied.");
1372 return -1;
1373 }
1374
1375 String arg = getNextArg();
1376 if (arg == null) {
1377 onHelpCc();
1378 return 0;
1379 }
1380
1381 switch (arg) {
1382 case CC_GET_VALUE: {
1383 return handleCcGetValue();
1384 }
1385 case CC_SET_VALUE: {
1386 return handleCcSetValue();
1387 }
1388 case CC_CLEAR_VALUES: {
1389 return handleCcClearValues();
1390 }
1391 default: {
1392 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1393 }
1394 }
1395 return -1;
1396 }
1397
1398 // cc get-value
1399 private int handleCcGetValue() {
1400 PrintWriter errPw = getErrPrintWriter();
1401 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1402 String key = null;
1403
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001404 // Parse all options
1405 CcOptionParseResult options = parseCcOptions(tag, false);
1406 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001407 return -1;
1408 }
1409
1410 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001411 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001412 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001413 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001414 return -1;
1415 }
1416
1417 // Get the key.
1418 key = getNextArg();
1419 if (key != null) {
1420 // A key was provided. Verify if it is a valid key
1421 if (!bundle.containsKey(key)) {
1422 errPw.println(tag + key + " is not a valid key.");
1423 return -1;
1424 }
1425
1426 // Print the carrier config value for key.
1427 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1428 } else {
1429 // No key provided. Show all values.
1430 // Iterate over a sorted list of all carrier config keys and print them.
1431 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1432 for (String k : sortedSet) {
1433 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1434 }
1435 }
1436 return 0;
1437 }
1438
1439 // cc set-value
1440 private int handleCcSetValue() {
1441 PrintWriter errPw = getErrPrintWriter();
1442 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1443
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001444 // Parse all options
1445 CcOptionParseResult options = parseCcOptions(tag, true);
1446 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001447 return -1;
1448 }
1449
1450 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001451 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001452 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001453 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001454 return -1;
1455 }
1456
1457 // Get the key.
1458 String key = getNextArg();
1459 if (key == null || key.equals("")) {
1460 errPw.println(tag + "KEY is missing");
1461 return -1;
1462 }
1463
1464 // Verify if the key is valid
1465 if (!originalValues.containsKey(key)) {
1466 errPw.println(tag + key + " is not a valid key.");
1467 return -1;
1468 }
1469
1470 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1471 ArrayList<String> valueList = new ArrayList<String>();
1472 while (peekNextArg() != null) {
1473 valueList.add(getNextArg());
1474 }
1475
1476 // Find the type of the carrier config value
1477 CcType type = getType(tag, key, originalValues);
1478 if (type == CcType.UNKNOWN) {
1479 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1480 return -1;
1481 }
1482
1483 // Create an override bundle containing the key and value that should be overriden.
1484 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1485 if (overrideBundle == null) {
1486 return -1;
1487 }
1488
1489 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001490 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001491
1492 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001493 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001494 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001495 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001496 return -1;
1497 }
1498
1499 // Print the original and new value.
1500 String originalValueString = ccValueToString(key, type, originalValues);
1501 String newValueString = ccValueToString(key, type, newValues);
1502 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1503 getOutPrintWriter().println("New value: \n" + newValueString);
1504
1505 return 0;
1506 }
1507
1508 // cc clear-values
1509 private int handleCcClearValues() {
1510 PrintWriter errPw = getErrPrintWriter();
1511 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1512
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001513 // Parse all options
1514 CcOptionParseResult options = parseCcOptions(tag, false);
1515 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001516 return -1;
1517 }
1518
1519 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001520 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001521 getOutPrintWriter()
1522 .println("All previously set carrier config override values has been cleared");
1523 return 0;
1524 }
1525
1526 private CcType getType(String tag, String key, PersistableBundle bundle) {
1527 // Find the type by checking the type of the current value stored in the bundle.
1528 Object value = bundle.get(key);
1529
1530 if (CC_TYPE_MAP.containsKey(key)) {
1531 return CC_TYPE_MAP.get(key);
1532 } else if (value != null) {
1533 if (value instanceof Boolean) {
1534 return CcType.BOOLEAN;
1535 } else if (value instanceof Double) {
1536 return CcType.DOUBLE;
1537 } else if (value instanceof double[]) {
1538 return CcType.DOUBLE_ARRAY;
1539 } else if (value instanceof Integer) {
1540 return CcType.INT;
1541 } else if (value instanceof int[]) {
1542 return CcType.INT_ARRAY;
1543 } else if (value instanceof Long) {
1544 return CcType.LONG;
1545 } else if (value instanceof long[]) {
1546 return CcType.LONG_ARRAY;
1547 } else if (value instanceof String) {
1548 return CcType.STRING;
1549 } else if (value instanceof String[]) {
1550 return CcType.STRING_ARRAY;
1551 }
1552 } else {
1553 // Current value was null and can therefore not be used in order to find the type.
1554 // Check the name of the key to infer the type. This check is not needed for primitive
1555 // data types (boolean, double, int and long), since they can not be null.
1556 if (key.endsWith("double_array")) {
1557 return CcType.DOUBLE_ARRAY;
1558 }
1559 if (key.endsWith("int_array")) {
1560 return CcType.INT_ARRAY;
1561 }
1562 if (key.endsWith("long_array")) {
1563 return CcType.LONG_ARRAY;
1564 }
1565 if (key.endsWith("string")) {
1566 return CcType.STRING;
1567 }
1568 if (key.endsWith("string_array") || key.endsWith("strings")) {
1569 return CcType.STRING_ARRAY;
1570 }
1571 }
1572
1573 // Not possible to infer the type by looking at the current value or the key.
1574 PrintWriter errPw = getErrPrintWriter();
1575 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1576 return CcType.UNKNOWN;
1577 }
1578
1579 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1580 String result;
1581 StringBuilder valueString = new StringBuilder();
1582 String typeString = type.toString();
1583 Object value = bundle.get(key);
1584
1585 if (value == null) {
1586 valueString.append("null");
1587 } else {
1588 switch (type) {
1589 case DOUBLE_ARRAY: {
1590 // Format the string representation of the int array as value1 value2......
1591 double[] valueArray = (double[]) value;
1592 for (int i = 0; i < valueArray.length; i++) {
1593 if (i != 0) {
1594 valueString.append(" ");
1595 }
1596 valueString.append(valueArray[i]);
1597 }
1598 break;
1599 }
1600 case INT_ARRAY: {
1601 // Format the string representation of the int array as value1 value2......
1602 int[] valueArray = (int[]) value;
1603 for (int i = 0; i < valueArray.length; i++) {
1604 if (i != 0) {
1605 valueString.append(" ");
1606 }
1607 valueString.append(valueArray[i]);
1608 }
1609 break;
1610 }
1611 case LONG_ARRAY: {
1612 // Format the string representation of the int array as value1 value2......
1613 long[] valueArray = (long[]) value;
1614 for (int i = 0; i < valueArray.length; i++) {
1615 if (i != 0) {
1616 valueString.append(" ");
1617 }
1618 valueString.append(valueArray[i]);
1619 }
1620 break;
1621 }
1622 case STRING: {
1623 valueString.append("\"" + value.toString() + "\"");
1624 break;
1625 }
1626 case STRING_ARRAY: {
1627 // Format the string representation of the string array as "value1" "value2"....
1628 String[] valueArray = (String[]) value;
1629 for (int i = 0; i < valueArray.length; i++) {
1630 if (i != 0) {
1631 valueString.append(" ");
1632 }
1633 if (valueArray[i] != null) {
1634 valueString.append("\"" + valueArray[i] + "\"");
1635 } else {
1636 valueString.append("null");
1637 }
1638 }
1639 break;
1640 }
1641 default: {
1642 valueString.append(value.toString());
1643 }
1644 }
1645 }
1646 return String.format("%-70s %-15s %s", key, typeString, valueString);
1647 }
1648
1649 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1650 ArrayList<String> valueList) {
1651 PrintWriter errPw = getErrPrintWriter();
1652 PersistableBundle bundle = new PersistableBundle();
1653
1654 // First verify that a valid number of values has been provided for the type.
1655 switch (type) {
1656 case BOOLEAN:
1657 case DOUBLE:
1658 case INT:
1659 case LONG: {
1660 if (valueList.size() != 1) {
1661 errPw.println(tag + "Expected 1 value for type " + type
1662 + ". Found: " + valueList.size());
1663 return null;
1664 }
1665 break;
1666 }
1667 case STRING: {
1668 if (valueList.size() > 1) {
1669 errPw.println(tag + "Expected 0 or 1 values for type " + type
1670 + ". Found: " + valueList.size());
1671 return null;
1672 }
1673 break;
1674 }
1675 }
1676
1677 // Parse the value according to type and add it to the Bundle.
1678 switch (type) {
1679 case BOOLEAN: {
1680 if ("true".equalsIgnoreCase(valueList.get(0))) {
1681 bundle.putBoolean(key, true);
1682 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1683 bundle.putBoolean(key, false);
1684 } else {
1685 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1686 return null;
1687 }
1688 break;
1689 }
1690 case DOUBLE: {
1691 try {
1692 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1693 } catch (NumberFormatException nfe) {
1694 // Not a valid double
1695 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1696 return null;
1697 }
1698 break;
1699 }
1700 case DOUBLE_ARRAY: {
1701 double[] valueDoubleArray = null;
1702 if (valueList.size() > 0) {
1703 valueDoubleArray = new double[valueList.size()];
1704 for (int i = 0; i < valueList.size(); i++) {
1705 try {
1706 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1707 } catch (NumberFormatException nfe) {
1708 // Not a valid double
1709 errPw.println(
1710 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1711 return null;
1712 }
1713 }
1714 }
1715 bundle.putDoubleArray(key, valueDoubleArray);
1716 break;
1717 }
1718 case INT: {
1719 try {
1720 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1721 } catch (NumberFormatException nfe) {
1722 // Not a valid integer
1723 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1724 return null;
1725 }
1726 break;
1727 }
1728 case INT_ARRAY: {
1729 int[] valueIntArray = null;
1730 if (valueList.size() > 0) {
1731 valueIntArray = new int[valueList.size()];
1732 for (int i = 0; i < valueList.size(); i++) {
1733 try {
1734 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1735 } catch (NumberFormatException nfe) {
1736 // Not a valid integer
1737 errPw.println(tag
1738 + "Unable to parse " + valueList.get(i) + " as an integer.");
1739 return null;
1740 }
1741 }
1742 }
1743 bundle.putIntArray(key, valueIntArray);
1744 break;
1745 }
1746 case LONG: {
1747 try {
1748 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1749 } catch (NumberFormatException nfe) {
1750 // Not a valid long
1751 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1752 return null;
1753 }
1754 break;
1755 }
1756 case LONG_ARRAY: {
1757 long[] valueLongArray = null;
1758 if (valueList.size() > 0) {
1759 valueLongArray = new long[valueList.size()];
1760 for (int i = 0; i < valueList.size(); i++) {
1761 try {
1762 valueLongArray[i] = Long.parseLong(valueList.get(i));
1763 } catch (NumberFormatException nfe) {
1764 // Not a valid long
1765 errPw.println(
1766 tag + "Unable to parse " + valueList.get(i) + " as a long");
1767 return null;
1768 }
1769 }
1770 }
1771 bundle.putLongArray(key, valueLongArray);
1772 break;
1773 }
1774 case STRING: {
1775 String value = null;
1776 if (valueList.size() > 0) {
1777 value = valueList.get(0);
1778 }
1779 bundle.putString(key, value);
1780 break;
1781 }
1782 case STRING_ARRAY: {
1783 String[] valueStringArray = null;
1784 if (valueList.size() > 0) {
1785 valueStringArray = new String[valueList.size()];
1786 valueList.toArray(valueStringArray);
1787 }
1788 bundle.putStringArray(key, valueStringArray);
1789 break;
1790 }
1791 }
1792 return bundle;
1793 }
Shuo Qian489d9282020-07-09 11:30:03 -07001794
1795 private int handleEndBlockSuppressionCommand() {
1796 if (!checkShellUid()) {
1797 return -1;
1798 }
1799
1800 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1801 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1802 }
1803 return 0;
1804 }
Hui Wang641e81c2020-10-12 12:14:23 -07001805
Michele Berionne54af4632020-12-28 20:23:16 +00001806 private int handleRestartModemCommand() {
1807 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1808 // non user build.
1809 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1810 getErrPrintWriter().println("RestartModem: Permission denied.");
1811 return -1;
1812 }
1813
1814 boolean result = TelephonyManager.getDefault().rebootRadio();
1815 getOutPrintWriter().println(result);
1816
1817 return result ? 0 : -1;
1818 }
1819
Michele Berionne5e411512020-11-13 02:36:59 +00001820 private int handleUnattendedReboot() {
1821 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1822 // non user build.
1823 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1824 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1825 return -1;
1826 }
1827
1828 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1829 getOutPrintWriter().println("result: " + result);
1830
1831 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1832 }
1833
Hui Wang641e81c2020-10-12 12:14:23 -07001834 private int handleGbaCommand() {
1835 String arg = getNextArg();
1836 if (arg == null) {
1837 onHelpGba();
1838 return 0;
1839 }
1840
1841 switch (arg) {
1842 case GBA_SET_SERVICE: {
1843 return handleGbaSetServiceCommand();
1844 }
1845 case GBA_GET_SERVICE: {
1846 return handleGbaGetServiceCommand();
1847 }
1848 case GBA_SET_RELEASE_TIME: {
1849 return handleGbaSetReleaseCommand();
1850 }
1851 case GBA_GET_RELEASE_TIME: {
1852 return handleGbaGetReleaseCommand();
1853 }
1854 }
1855
1856 return -1;
1857 }
1858
1859 private int getSubId(String cmd) {
1860 int slotId = getDefaultSlot();
1861 String opt = getNextOption();
1862 if (opt != null && opt.equals("-s")) {
1863 try {
1864 slotId = Integer.parseInt(getNextArgRequired());
1865 } catch (NumberFormatException e) {
1866 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1867 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1868 }
1869 }
1870 int[] subIds = SubscriptionManager.getSubId(slotId);
1871 return subIds[0];
1872 }
1873
1874 private int handleGbaSetServiceCommand() {
1875 int subId = getSubId("gba set-service");
1876 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1877 return -1;
1878 }
1879
1880 String packageName = getNextArg();
1881 try {
1882 if (packageName == null) {
1883 packageName = "";
1884 }
1885 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1886 if (VDBG) {
1887 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1888 + packageName + ", result=" + result);
1889 }
1890 getOutPrintWriter().println(result);
1891 } catch (RemoteException e) {
1892 Log.w(LOG_TAG, "gba set-service " + subId + " "
1893 + packageName + ", error" + e.getMessage());
1894 getErrPrintWriter().println("Exception: " + e.getMessage());
1895 return -1;
1896 }
1897 return 0;
1898 }
1899
1900 private int handleGbaGetServiceCommand() {
1901 String result;
1902
1903 int subId = getSubId("gba get-service");
1904 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1905 return -1;
1906 }
1907
1908 try {
1909 result = mInterface.getBoundGbaService(subId);
1910 } catch (RemoteException e) {
1911 return -1;
1912 }
1913 if (VDBG) {
1914 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1915 }
1916 getOutPrintWriter().println(result);
1917 return 0;
1918 }
1919
1920 private int handleGbaSetReleaseCommand() {
1921 //the release time value could be -1
1922 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1923 : SubscriptionManager.getDefaultSubscriptionId();
1924 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1925 return -1;
1926 }
1927
1928 String intervalStr = getNextArg();
1929 if (intervalStr == null) {
1930 return -1;
1931 }
1932
1933 try {
1934 int interval = Integer.parseInt(intervalStr);
1935 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1936 if (VDBG) {
1937 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1938 + intervalStr + ", result=" + result);
1939 }
1940 getOutPrintWriter().println(result);
1941 } catch (NumberFormatException | RemoteException e) {
1942 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1943 + intervalStr + ", error" + e.getMessage());
1944 getErrPrintWriter().println("Exception: " + e.getMessage());
1945 return -1;
1946 }
1947 return 0;
1948 }
1949
1950 private int handleGbaGetReleaseCommand() {
1951 int subId = getSubId("gba get-release");
1952 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1953 return -1;
1954 }
1955
1956 int result = 0;
1957 try {
1958 result = mInterface.getGbaReleaseTime(subId);
1959 } catch (RemoteException e) {
1960 return -1;
1961 }
1962 if (VDBG) {
1963 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1964 }
1965 getOutPrintWriter().println(result);
1966 return 0;
1967 }
Hui Wang761a6682020-10-31 05:12:53 +00001968
1969 private int handleSingleRegistrationConfigCommand() {
1970 String arg = getNextArg();
1971 if (arg == null) {
1972 onHelpSrc();
1973 return 0;
1974 }
1975
1976 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001977 case SRC_SET_TEST_ENABLED: {
1978 return handleSrcSetTestEnabledCommand();
1979 }
1980 case SRC_GET_TEST_ENABLED: {
1981 return handleSrcGetTestEnabledCommand();
1982 }
Hui Wang761a6682020-10-31 05:12:53 +00001983 case SRC_SET_DEVICE_ENABLED: {
1984 return handleSrcSetDeviceEnabledCommand();
1985 }
1986 case SRC_GET_DEVICE_ENABLED: {
1987 return handleSrcGetDeviceEnabledCommand();
1988 }
1989 case SRC_SET_CARRIER_ENABLED: {
1990 return handleSrcSetCarrierEnabledCommand();
1991 }
1992 case SRC_GET_CARRIER_ENABLED: {
1993 return handleSrcGetCarrierEnabledCommand();
1994 }
Hui Wangb647abe2021-02-26 09:33:38 -08001995 case SRC_SET_FEATURE_ENABLED: {
1996 return handleSrcSetFeatureValidationCommand();
1997 }
1998 case SRC_GET_FEATURE_ENABLED: {
1999 return handleSrcGetFeatureValidationCommand();
2000 }
Hui Wang761a6682020-10-31 05:12:53 +00002001 }
2002
2003 return -1;
2004 }
2005
James.cf Linbcdf8b32021-01-14 16:44:13 +08002006 private int handleRcsUceCommand() {
2007 String arg = getNextArg();
2008 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002009 onHelpUce();
2010 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002011 }
2012
2013 switch (arg) {
2014 case UCE_REMOVE_EAB_CONTACT:
2015 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002016 case UCE_GET_EAB_CONTACT:
2017 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002018 case UCE_GET_DEVICE_ENABLED:
2019 return handleUceGetDeviceEnabledCommand();
2020 case UCE_SET_DEVICE_ENABLED:
2021 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002022 case UCE_OVERRIDE_PUBLISH_CAPS:
2023 return handleUceOverridePublishCaps();
2024 case UCE_GET_LAST_PIDF_XML:
2025 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002026 }
2027 return -1;
2028 }
2029
2030 private int handleRemovingEabContactCommand() {
2031 int subId = getSubId("uce remove-eab-contact");
2032 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2033 return -1;
2034 }
2035
2036 String phoneNumber = getNextArgRequired();
2037 if (TextUtils.isEmpty(phoneNumber)) {
2038 return -1;
2039 }
2040 int result = 0;
2041 try {
2042 result = mInterface.removeContactFromEab(subId, phoneNumber);
2043 } catch (RemoteException e) {
2044 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2045 getErrPrintWriter().println("Exception: " + e.getMessage());
2046 return -1;
2047 }
2048
2049 if (VDBG) {
2050 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2051 }
calvinpan293ea1b2021-02-04 17:52:13 +08002052 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002053 }
2054
calvinpane4a8a1d2021-01-25 13:51:18 +08002055 private int handleGettingEabContactCommand() {
2056 String phoneNumber = getNextArgRequired();
2057 if (TextUtils.isEmpty(phoneNumber)) {
2058 return -1;
2059 }
2060 String result = "";
2061 try {
2062 result = mInterface.getContactFromEab(phoneNumber);
2063
2064 } catch (RemoteException e) {
2065 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2066 getErrPrintWriter().println("Exception: " + e.getMessage());
2067 return -1;
2068 }
2069
2070 if (VDBG) {
2071 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2072 }
calvinpan293ea1b2021-02-04 17:52:13 +08002073 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002074 return 0;
2075 }
2076
2077 private int handleUceGetDeviceEnabledCommand() {
2078 boolean result = false;
2079 try {
2080 result = mInterface.getDeviceUceEnabled();
2081 } catch (RemoteException e) {
2082 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2083 return -1;
2084 }
2085 if (VDBG) {
2086 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2087 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002088 getOutPrintWriter().println(result);
2089 return 0;
2090 }
2091
James.cf Lin4b784aa2021-01-31 03:25:15 +08002092 private int handleUceSetDeviceEnabledCommand() {
2093 String enabledStr = getNextArg();
2094 if (TextUtils.isEmpty(enabledStr)) {
2095 return -1;
2096 }
2097
2098 try {
2099 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2100 mInterface.setDeviceUceEnabled(isEnabled);
2101 if (VDBG) {
2102 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2103 }
2104 } catch (NumberFormatException | RemoteException e) {
2105 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2106 getErrPrintWriter().println("Exception: " + e.getMessage());
2107 return -1;
2108 }
2109 return 0;
2110 }
2111
Hui Wangbaaee6a2021-02-19 20:45:36 -08002112 private int handleSrcSetTestEnabledCommand() {
2113 String enabledStr = getNextArg();
2114 if (enabledStr == null) {
2115 return -1;
2116 }
2117
2118 try {
2119 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2120 if (VDBG) {
2121 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2122 }
2123 getOutPrintWriter().println("Done");
2124 } catch (NumberFormatException | RemoteException e) {
2125 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2126 getErrPrintWriter().println("Exception: " + e.getMessage());
2127 return -1;
2128 }
2129 return 0;
2130 }
2131
2132 private int handleSrcGetTestEnabledCommand() {
2133 boolean result = false;
2134 try {
2135 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2136 } catch (RemoteException e) {
2137 return -1;
2138 }
2139 if (VDBG) {
2140 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2141 }
2142 getOutPrintWriter().println(result);
2143 return 0;
2144 }
2145
Brad Ebinger14d467f2021-02-12 06:18:28 +00002146 private int handleUceOverridePublishCaps() {
2147 int subId = getSubId("uce override-published-caps");
2148 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2149 return -1;
2150 }
2151 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2152 String operation = getNextArgRequired();
2153 String caps = getNextArg();
2154 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2155 && !"list".equals(operation)) {
2156 getErrPrintWriter().println("Invalid operation: " + operation);
2157 return -1;
2158 }
2159
2160 // add/remove requires capabilities to be specified.
2161 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2162 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2163 + "specified");
2164 return -1;
2165 }
2166
2167 ArraySet<String> capSet = new ArraySet<>();
2168 if (!TextUtils.isEmpty(caps)) {
2169 String[] capArray = caps.split(":");
2170 for (String cap : capArray) {
2171 // Allow unknown tags to be passed in as well.
2172 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2173 }
2174 }
2175
2176 RcsContactUceCapability result = null;
2177 try {
2178 switch (operation) {
2179 case "add":
2180 result = mInterface.addUceRegistrationOverrideShell(subId,
2181 new ArrayList<>(capSet));
2182 break;
2183 case "remove":
2184 result = mInterface.removeUceRegistrationOverrideShell(subId,
2185 new ArrayList<>(capSet));
2186 break;
2187 case "clear":
2188 result = mInterface.clearUceRegistrationOverrideShell(subId);
2189 break;
2190 case "list":
2191 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2192 break;
2193 }
2194 } catch (RemoteException e) {
2195 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2196 getErrPrintWriter().println("Exception: " + e.getMessage());
2197 return -1;
2198 } catch (ServiceSpecificException sse) {
2199 // Reconstruct ImsException
2200 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2201 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2202 getErrPrintWriter().println("Exception: " + imsException);
2203 return -1;
2204 }
2205 if (result == null) {
2206 getErrPrintWriter().println("Service not available");
2207 return -1;
2208 }
2209 getOutPrintWriter().println(result);
2210 return 0;
2211 }
2212
2213 private int handleUceGetPidfXml() {
2214 int subId = getSubId("uce get-last-publish-pidf");
2215 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2216 return -1;
2217 }
2218
2219 String result;
2220 try {
2221 result = mInterface.getLastUcePidfXmlShell(subId);
2222 } catch (RemoteException e) {
2223 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2224 getErrPrintWriter().println("Exception: " + e.getMessage());
2225 return -1;
2226 } catch (ServiceSpecificException sse) {
2227 // Reconstruct ImsException
2228 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2229 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2230 getErrPrintWriter().println("Exception: " + imsException);
2231 return -1;
2232 }
2233 if (result == null) {
2234 getErrPrintWriter().println("Service not available");
2235 return -1;
2236 }
2237 getOutPrintWriter().println(result);
2238 return 0;
2239 }
2240
Hui Wang761a6682020-10-31 05:12:53 +00002241 private int handleSrcSetDeviceEnabledCommand() {
2242 String enabledStr = getNextArg();
2243 if (enabledStr == null) {
2244 return -1;
2245 }
2246
2247 try {
2248 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2249 if (VDBG) {
2250 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2251 }
2252 getOutPrintWriter().println("Done");
2253 } catch (NumberFormatException | RemoteException e) {
2254 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2255 getErrPrintWriter().println("Exception: " + e.getMessage());
2256 return -1;
2257 }
2258 return 0;
2259 }
2260
2261 private int handleSrcGetDeviceEnabledCommand() {
2262 boolean result = false;
2263 try {
2264 result = mInterface.getDeviceSingleRegistrationEnabled();
2265 } catch (RemoteException e) {
2266 return -1;
2267 }
2268 if (VDBG) {
2269 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2270 }
2271 getOutPrintWriter().println(result);
2272 return 0;
2273 }
2274
2275 private int handleSrcSetCarrierEnabledCommand() {
2276 //the release time value could be -1
2277 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2278 : SubscriptionManager.getDefaultSubscriptionId();
2279 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2280 return -1;
2281 }
2282
2283 String enabledStr = getNextArg();
2284 if (enabledStr == null) {
2285 return -1;
2286 }
2287
2288 try {
2289 boolean result =
2290 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2291 if (VDBG) {
2292 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2293 + enabledStr + ", result=" + result);
2294 }
2295 getOutPrintWriter().println(result);
2296 } catch (NumberFormatException | RemoteException e) {
2297 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2298 + enabledStr + ", error" + e.getMessage());
2299 getErrPrintWriter().println("Exception: " + e.getMessage());
2300 return -1;
2301 }
2302 return 0;
2303 }
2304
2305 private int handleSrcGetCarrierEnabledCommand() {
2306 int subId = getSubId("src get-carrier-enabled");
2307 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2308 return -1;
2309 }
2310
2311 boolean result = false;
2312 try {
2313 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2314 } catch (RemoteException e) {
2315 return -1;
2316 }
2317 if (VDBG) {
2318 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2319 }
2320 getOutPrintWriter().println(result);
2321 return 0;
2322 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002323
Hui Wangb647abe2021-02-26 09:33:38 -08002324 private int handleSrcSetFeatureValidationCommand() {
2325 //the release time value could be -1
2326 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2327 : SubscriptionManager.getDefaultSubscriptionId();
2328 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2329 return -1;
2330 }
2331
2332 String enabledStr = getNextArg();
2333 if (enabledStr == null) {
2334 return -1;
2335 }
2336
2337 try {
2338 boolean result =
2339 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2340 if (VDBG) {
2341 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2342 + enabledStr + ", result=" + result);
2343 }
2344 getOutPrintWriter().println(result);
2345 } catch (NumberFormatException | RemoteException e) {
2346 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2347 + enabledStr + ", error" + e.getMessage());
2348 getErrPrintWriter().println("Exception: " + e.getMessage());
2349 return -1;
2350 }
2351 return 0;
2352 }
2353
2354 private int handleSrcGetFeatureValidationCommand() {
2355 int subId = getSubId("src get-feature-validation");
2356 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2357 return -1;
2358 }
2359
2360 Boolean result = false;
2361 try {
2362 result = mInterface.getImsFeatureValidationOverride(subId);
2363 } catch (RemoteException e) {
2364 return -1;
2365 }
2366 if (VDBG) {
2367 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2368 }
2369 getOutPrintWriter().println(result);
2370 return 0;
2371 }
2372
2373
Hall Liuaa4211e2021-01-20 15:43:39 -08002374 private void onHelpCallComposer() {
2375 PrintWriter pw = getOutPrintWriter();
2376 pw.println("Call composer commands");
2377 pw.println(" callcomposer test-mode enable|disable|query");
2378 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2379 pw.println(" upload/download from carrier servers is disabled, and operations are");
2380 pw.println(" performed using emulated local files instead.");
2381 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2382 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2383 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002384 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2385 pw.println(" Enables or disables the user setting for call composer, as set by");
2386 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002387 }
2388
2389 private int handleCallComposerCommand() {
2390 String arg = getNextArg();
2391 if (arg == null) {
2392 onHelpCallComposer();
2393 return 0;
2394 }
2395
2396 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2397 "MODIFY_PHONE_STATE required for call composer shell cmds");
2398 switch (arg) {
2399 case CALL_COMPOSER_TEST_MODE: {
2400 String enabledStr = getNextArg();
2401 if (ENABLE.equals(enabledStr)) {
2402 CallComposerPictureManager.sTestMode = true;
2403 } else if (DISABLE.equals(enabledStr)) {
2404 CallComposerPictureManager.sTestMode = false;
2405 } else if (QUERY.equals(enabledStr)) {
2406 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2407 } else {
2408 onHelpCallComposer();
2409 return 1;
2410 }
2411 break;
2412 }
2413 case CALL_COMPOSER_SIMULATE_CALL: {
2414 int subscriptionId = Integer.valueOf(getNextArg());
2415 String uuidString = getNextArg();
2416 UUID uuid = UUID.fromString(uuidString);
2417 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2418 Binder.withCleanCallingIdentity(() -> {
2419 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2420 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2421 });
2422 try {
2423 Uri uri = storageUriFuture.get();
2424 getOutPrintWriter().println(String.valueOf(uri));
2425 } catch (Exception e) {
2426 throw new RuntimeException(e);
2427 }
2428 break;
2429 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002430 case CALL_COMPOSER_USER_SETTING: {
2431 try {
2432 int subscriptionId = Integer.valueOf(getNextArg());
2433 String enabledStr = getNextArg();
2434 if (ENABLE.equals(enabledStr)) {
2435 mInterface.setCallComposerStatus(subscriptionId,
2436 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2437 } else if (DISABLE.equals(enabledStr)) {
2438 mInterface.setCallComposerStatus(subscriptionId,
2439 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2440 } else if (QUERY.equals(enabledStr)) {
2441 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2442 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2443 } else {
2444 onHelpCallComposer();
2445 return 1;
2446 }
2447 } catch (RemoteException e) {
2448 e.printStackTrace(getOutPrintWriter());
2449 return 1;
2450 }
2451 break;
2452 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002453 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002454 return 0;
2455 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002456
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002457 private int handleHasCarrierPrivilegesCommand() {
2458 String packageName = getNextArgRequired();
2459
2460 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002461 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002462 try {
2463 hasCarrierPrivileges =
2464 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2465 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2466 } catch (RemoteException e) {
2467 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2468 getErrPrintWriter().println("Exception: " + e.getMessage());
2469 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002470 } finally {
2471 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002472 }
2473
2474 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002475 return 0;
2476 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002477}