blob: aae0373dc6ba9693b68107121e42ed5d9c152630 [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;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010033import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070034import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070035import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000036import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080037import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000038import android.telephony.ims.ImsException;
39import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080040import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080041import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000042import android.util.ArrayMap;
43import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070044import android.util.Log;
45
Brad Ebinger14d467f2021-02-12 06:18:28 +000046import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070047import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080048import com.android.internal.telephony.Phone;
49import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080050import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080051import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080052import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080053import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080054import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070055
56import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080057import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000058import java.util.Arrays;
59import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010060import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080061import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010062import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000063import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010064import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080065import java.util.UUID;
66import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070067
68/**
69 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
70 * permission checks have been done before onCommand was called. Make sure any commands processed
71 * here also contain the appropriate permissions checks.
72 */
73
Hall Liua1548bd2019-12-24 14:14:12 -080074public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070075
76 private static final String LOG_TAG = "TelephonyShellCommand";
77 // Don't commit with this true.
78 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070079 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070080
Hall Liuaa4211e2021-01-20 15:43:39 -080081 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070082 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080083 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080084 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080085 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070086 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000087 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000088 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010089 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080090 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080091 private static final String ENABLE = "enable";
92 private static final String DISABLE = "disable";
93 private static final String QUERY = "query";
94
Hall Liu7135e502021-02-04 16:58:17 -080095 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080096 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -080097 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -080098
Brad Ebinger999d3302020-11-25 14:31:39 -080099 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
100 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
101 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700102 // Used to disable or enable processing of conference event package data from the network.
103 // This is handy for testing scenarios where CEP data does not exist on a network which does
104 // support CEP data.
105 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700106
Hall Liud892bec2018-11-30 14:51:45 -0800107 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800108 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800109
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100110 private static final String CC_GET_VALUE = "get-value";
111 private static final String CC_SET_VALUE = "set-value";
112 private static final String CC_CLEAR_VALUES = "clear-values";
113
Hui Wang641e81c2020-10-12 12:14:23 -0700114 private static final String GBA_SUBCOMMAND = "gba";
115 private static final String GBA_SET_SERVICE = "set-service";
116 private static final String GBA_GET_SERVICE = "get-service";
117 private static final String GBA_SET_RELEASE_TIME = "set-release";
118 private static final String GBA_GET_RELEASE_TIME = "get-release";
119
Hui Wang761a6682020-10-31 05:12:53 +0000120 private static final String SINGLE_REGISTATION_CONFIG = "src";
121 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
122 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
123 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
124 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800125 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
126 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800127 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
128 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000129
Tyler Gunn92479152021-01-20 16:30:10 -0800130 private static final String D2D_SUBCOMMAND = "d2d";
131 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800132 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800133
James.cf Linbcdf8b32021-01-14 16:44:13 +0800134 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800135 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800136 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800137 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
138 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000139 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
140 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800141
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800142 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
143 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
144
Jordan Liu0ccee222021-04-27 11:55:13 -0700145 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
146 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
147
Jack Nudelman644b91a2021-03-12 14:09:48 -0800148 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
149 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
150 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
151
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700152 // Take advantage of existing methods that already contain permissions checks when possible.
153 private final ITelephony mInterface;
154
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100155 private SubscriptionManager mSubscriptionManager;
156 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700157 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100158
159 private enum CcType {
160 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
161 STRING_ARRAY, UNKNOWN
162 }
163
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100164 private class CcOptionParseResult {
165 public int mSubId;
166 public boolean mPersistent;
167 }
168
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100169 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
170 // keys by looking at the end of the string which usually tells the type.
171 // For instance: "xxxx_string", "xxxx_string_array", etc.
172 // The carrier config keys in this map does not follow this convention. It is therefore not
173 // possible to infer the type for these keys by looking at the string.
174 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
175 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
176 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
177 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
178 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
179 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
180 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
181 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
182 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
183 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
184 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
185 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
186 CcType.STRING);
187 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
188 CcType.STRING_ARRAY);
189 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
190 CcType.STRING_ARRAY);
191 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
192 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
193 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
194 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
195 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
196 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
197 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
198 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
199 }
200 };
201
Brad Ebinger14d467f2021-02-12 06:18:28 +0000202 /**
203 * Map from a shorthand string to the feature tags required in registration required in order
204 * for the RCS feature to be considered "capable".
205 */
206 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
207 static {
208 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
209 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
210 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
211 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
212 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
213 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
214 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
215 FeatureTags.FEATURE_TAG_VIDEO)));
216 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
217 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
218 map.put("call_comp",
219 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
220 map.put("call_comp_mmtel",
221 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
222 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
223 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
224 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
225 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
226 // version
227 map.put("chatbot", new ArraySet<>(Arrays.asList(
228 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
229 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
230 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
231 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
232 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
233 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
234 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
235 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
236 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
237 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
238 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
239 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
240 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
241 }
242
243
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100244 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700245 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100246 mCarrierConfigManager =
247 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
248 mSubscriptionManager = (SubscriptionManager)
249 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700250 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700251 }
252
253 @Override
254 public int onCommand(String cmd) {
255 if (cmd == null) {
256 return handleDefaultCommands(null);
257 }
258
259 switch (cmd) {
260 case IMS_SUBCOMMAND: {
261 return handleImsCommand();
262 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800263 case RCS_UCE_COMMAND:
264 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800265 case NUMBER_VERIFICATION_SUBCOMMAND:
266 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800267 case EMERGENCY_CALLBACK_MODE:
268 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800269 case EMERGENCY_NUMBER_TEST_MODE:
270 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100271 case CARRIER_CONFIG_SUBCOMMAND: {
272 return handleCcCommand();
273 }
Shuo Qianf5125122019-12-16 17:03:07 -0800274 case DATA_TEST_MODE:
275 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700276 case END_BLOCK_SUPPRESSION:
277 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700278 case GBA_SUBCOMMAND:
279 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800280 case D2D_SUBCOMMAND:
281 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000282 case SINGLE_REGISTATION_CONFIG:
283 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000284 case RESTART_MODEM:
285 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800286 case CALL_COMPOSER_SUBCOMMAND:
287 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000288 case UNATTENDED_REBOOT:
289 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800290 case HAS_CARRIER_PRIVILEGES_COMMAND:
291 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800292 case THERMAL_MITIGATION_COMMAND:
293 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700294 case DISABLE_PHYSICAL_SUBSCRIPTION:
295 return handleEnablePhysicalSubscription(false);
296 case ENABLE_PHYSICAL_SUBSCRIPTION:
297 return handleEnablePhysicalSubscription(true);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700298 default: {
299 return handleDefaultCommands(cmd);
300 }
301 }
302 }
303
304 @Override
305 public void onHelp() {
306 PrintWriter pw = getOutPrintWriter();
307 pw.println("Telephony Commands:");
308 pw.println(" help");
309 pw.println(" Print this help text.");
310 pw.println(" ims");
311 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800312 pw.println(" uce");
313 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800314 pw.println(" emergency-number-test-mode");
315 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700316 pw.println(" end-block-suppression");
317 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800318 pw.println(" data");
319 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100320 pw.println(" cc");
321 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700322 pw.println(" gba");
323 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000324 pw.println(" src");
325 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000326 pw.println(" restart-modem");
327 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000328 pw.println(" unattended-reboot");
329 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800330 pw.println(" has-carrier-privileges [package]");
331 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700332 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800333 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800334 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700335 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800336 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100337 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700338 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000339 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800340 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700341 onHelpDisableOrEnablePhysicalSubscription();
Tyler Gunn92479152021-01-20 16:30:10 -0800342 }
343
344 private void onHelpD2D() {
345 PrintWriter pw = getOutPrintWriter();
346 pw.println("D2D Comms Commands:");
347 pw.println(" d2d send TYPE VALUE");
348 pw.println(" Sends a D2D message of specified type and value.");
349 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
350 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
351 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
352 MESSAGE_CALL_AUDIO_CODEC));
353 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
354 + Communicator.messageToString(
355 MESSAGE_DEVICE_BATTERY_STATE));
356 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
357 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800358 pw.println(" d2d transport TYPE");
359 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
360 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700361 }
362
363 private void onHelpIms() {
364 PrintWriter pw = getOutPrintWriter();
365 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800366 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700367 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
368 pw.println(" ImsService. Options are:");
369 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
370 pw.println(" is specified, it will choose the default voice SIM slot.");
371 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
372 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800373 pw.println(" -f: Set the feature that this override if for, if no option is");
374 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700375 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
376 pw.println(" Gets the package name of the currently defined ImsService.");
377 pw.println(" Options are:");
378 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
379 pw.println(" is specified, it will choose the default voice SIM slot.");
380 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000381 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800382 pw.println(" -f: The feature type that the query will be requested for. If none is");
383 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800384 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
385 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
386 pw.println(" configuration overrides. Options are:");
387 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
388 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700389 pw.println(" ims enable [-s SLOT_ID]");
390 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
391 pw.println(" if none is specified.");
392 pw.println(" ims disable [-s SLOT_ID]");
393 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
394 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700395 pw.println(" ims conference-event-package [enable/disable]");
396 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700397 }
398
James.cf Linbcdf8b32021-01-14 16:44:13 +0800399 private void onHelpUce() {
400 PrintWriter pw = getOutPrintWriter();
401 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800402 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
403 pw.println(" Get the EAB contacts from the EAB database.");
404 pw.println(" Options are:");
405 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
406 pw.println(" Expected output format :");
407 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800408 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
409 pw.println(" Remove the EAB contacts from the EAB database.");
410 pw.println(" Options are:");
411 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
412 pw.println(" is specified, it will choose the default voice SIM slot.");
413 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800414 pw.println(" uce get-device-enabled");
415 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
416 pw.println(" uce set-device-enabled true|false");
417 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
418 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000419 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
420 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
421 pw.println(" Options are:");
422 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
423 pw.println(" is specified, it will choose the default voice SIM slot.");
424 pw.println(" add [CAPABILITY]: add a new capability");
425 pw.println(" remove [CAPABILITY]: remove a capability");
426 pw.println(" clear: clear all capability overrides");
427 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
428 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
429 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
430 pw.println(" chatbot_sa, chatbot_role] as well as full length");
431 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
432 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
433 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
434 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800435 }
436
Hall Liud892bec2018-11-30 14:51:45 -0800437 private void onHelpNumberVerification() {
438 PrintWriter pw = getOutPrintWriter();
439 pw.println("Number verification commands");
440 pw.println(" numverify override-package PACKAGE_NAME;");
441 pw.println(" Set the authorized package for number verification.");
442 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800443 pw.println(" numverify fake-call NUMBER;");
444 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
445 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800446 }
447
Jack Nudelman644b91a2021-03-12 14:09:48 -0800448 private void onHelpThermalMitigation() {
449 PrintWriter pw = getOutPrintWriter();
450 pw.println("Thermal mitigation commands");
451 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
452 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
453 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
454 pw.println(" Remove the package from one of the authorized packages for thermal "
455 + "mitigation.");
456 }
457
Jordan Liu0ccee222021-04-27 11:55:13 -0700458 private void onHelpDisableOrEnablePhysicalSubscription() {
459 PrintWriter pw = getOutPrintWriter();
460 pw.println("Disable or enable a physical subscription");
461 pw.println(" disable-physical-subscription SUB_ID");
462 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
463 pw.println(" enable-physical-subscription SUB_ID");
464 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
465 }
466
Shuo Qianf5125122019-12-16 17:03:07 -0800467 private void onHelpDataTestMode() {
468 PrintWriter pw = getOutPrintWriter();
469 pw.println("Mobile Data Test Mode Commands:");
470 pw.println(" data enable: enable mobile data connectivity");
471 pw.println(" data disable: disable mobile data connectivity");
472 }
473
sqian9d4df8b2019-01-15 18:32:07 -0800474 private void onHelpEmergencyNumber() {
475 PrintWriter pw = getOutPrintWriter();
476 pw.println("Emergency Number Test Mode Commands:");
477 pw.println(" emergency-number-test-mode ");
478 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
479 + " the test mode");
480 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700481 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800482 pw.println(" -c: clear the emergency number list in the test mode.");
483 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700484 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800485 pw.println(" -p: get the full emergency number list in the test mode.");
486 }
487
Shuo Qian489d9282020-07-09 11:30:03 -0700488 private void onHelpEndBlockSupperssion() {
489 PrintWriter pw = getOutPrintWriter();
490 pw.println("End Block Suppression command:");
491 pw.println(" end-block-suppression: disable suppressing blocking by contact");
492 pw.println(" with emergency services.");
493 }
494
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100495 private void onHelpCc() {
496 PrintWriter pw = getOutPrintWriter();
497 pw.println("Carrier Config Commands:");
498 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
499 pw.println(" Print carrier config values.");
500 pw.println(" Options are:");
501 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
502 pw.println(" is specified, it will choose the default voice SIM slot.");
503 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
504 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100505 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100506 pw.println(" Set carrier config KEY to NEW_VALUE.");
507 pw.println(" Options are:");
508 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
509 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100510 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100511 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
512 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
513 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
514 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
515 pw.println(" cc clear-values [-s SLOT_ID]");
516 pw.println(" Clear all carrier override values that has previously been set");
517 pw.println(" with set-value");
518 pw.println(" Options are:");
519 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
520 pw.println(" is specified, it will choose the default voice SIM slot.");
521 }
522
Hui Wang641e81c2020-10-12 12:14:23 -0700523 private void onHelpGba() {
524 PrintWriter pw = getOutPrintWriter();
525 pw.println("Gba Commands:");
526 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
527 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
528 pw.println(" Options are:");
529 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
530 pw.println(" is specified, it will choose the default voice SIM slot.");
531 pw.println(" gba get-service [-s SLOT_ID]");
532 pw.println(" Gets the package name of the currently defined GbaService.");
533 pw.println(" Options are:");
534 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
535 pw.println(" is specified, it will choose the default voice SIM slot.");
536 pw.println(" gba set-release [-s SLOT_ID] n");
537 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
538 pw.println(" Do not release/unbind if n is -1.");
539 pw.println(" Options are:");
540 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
541 pw.println(" is specified, it will choose the default voice SIM slot.");
542 pw.println(" gba get-release [-s SLOT_ID]");
543 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
544 pw.println(" Options are:");
545 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
546 pw.println(" is specified, it will choose the default voice SIM slot.");
547 }
548
Hui Wang761a6682020-10-31 05:12:53 +0000549 private void onHelpSrc() {
550 PrintWriter pw = getOutPrintWriter();
551 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800552 pw.println(" src set-test-enabled true|false");
553 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
554 pw.println(" The value could be true, false, or null(undefined).");
555 pw.println(" src get-test-enabled");
556 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000557 pw.println(" src set-device-enabled true|false|null");
558 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
559 pw.println(" The value could be true, false, or null(undefined).");
560 pw.println(" src get-device-enabled");
561 pw.println(" Gets the device config for RCS VoLTE single registration.");
562 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
563 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
564 pw.println(" The value could be true, false, or null(undefined).");
565 pw.println(" Options are:");
566 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
567 pw.println(" is specified, it will choose the default voice SIM slot.");
568 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
569 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
570 pw.println(" Options are:");
571 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
572 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800573 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
574 pw.println(" Sets ims feature validation result.");
575 pw.println(" The value could be true, false, or null(undefined).");
576 pw.println(" Options are:");
577 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
578 pw.println(" is specified, it will choose the default voice SIM slot.");
579 pw.println(" src get-feature-validation [-s SLOT_ID]");
580 pw.println(" Gets ims feature validation override value.");
581 pw.println(" Options are:");
582 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
583 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000584 }
585
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700586 private int handleImsCommand() {
587 String arg = getNextArg();
588 if (arg == null) {
589 onHelpIms();
590 return 0;
591 }
592
593 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800594 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700595 return handleImsSetServiceCommand();
596 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800597 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700598 return handleImsGetServiceCommand();
599 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800600 case IMS_CLEAR_SERVICE_OVERRIDE: {
601 return handleImsClearCarrierServiceCommand();
602 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800603 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700604 return handleEnableIms();
605 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800606 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700607 return handleDisableIms();
608 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700609 case IMS_CEP: {
610 return handleCepChange();
611 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700612 }
613
614 return -1;
615 }
616
Shuo Qianf5125122019-12-16 17:03:07 -0800617 private int handleDataTestModeCommand() {
618 PrintWriter errPw = getErrPrintWriter();
619 String arg = getNextArgRequired();
620 if (arg == null) {
621 onHelpDataTestMode();
622 return 0;
623 }
624 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800625 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800626 try {
627 mInterface.enableDataConnectivity();
628 } catch (RemoteException ex) {
629 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
630 errPw.println("Exception: " + ex.getMessage());
631 return -1;
632 }
633 break;
634 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800635 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800636 try {
637 mInterface.disableDataConnectivity();
638 } catch (RemoteException ex) {
639 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
640 errPw.println("Exception: " + ex.getMessage());
641 return -1;
642 }
643 break;
644 }
645 default:
646 onHelpDataTestMode();
647 break;
648 }
649 return 0;
650 }
651
Shuo Qianccbaf742021-02-22 18:32:21 -0800652 private int handleEmergencyCallbackModeCommand() {
653 PrintWriter errPw = getErrPrintWriter();
654 try {
655 mInterface.startEmergencyCallbackMode();
656 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
657 } catch (RemoteException ex) {
658 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
659 errPw.println("Exception: " + ex.getMessage());
660 return -1;
661 }
662 return 0;
663 }
664
sqian9d4df8b2019-01-15 18:32:07 -0800665 private int handleEmergencyNumberTestModeCommand() {
666 PrintWriter errPw = getErrPrintWriter();
667 String opt = getNextOption();
668 if (opt == null) {
669 onHelpEmergencyNumber();
670 return 0;
671 }
672
673 switch (opt) {
674 case "-a": {
675 String emergencyNumberCmd = getNextArgRequired();
676 if (emergencyNumberCmd == null
677 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700678 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800679 + " to be specified after -a in the command ");
680 return -1;
681 }
682 try {
683 mInterface.updateEmergencyNumberListTestMode(
684 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
685 new EmergencyNumber(emergencyNumberCmd, "", "",
686 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
687 new ArrayList<String>(),
688 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
689 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
690 } catch (RemoteException ex) {
691 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
692 + ", error " + ex.getMessage());
693 errPw.println("Exception: " + ex.getMessage());
694 return -1;
695 }
696 break;
697 }
698 case "-c": {
699 try {
700 mInterface.updateEmergencyNumberListTestMode(
701 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
702 } catch (RemoteException ex) {
703 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
704 errPw.println("Exception: " + ex.getMessage());
705 return -1;
706 }
707 break;
708 }
709 case "-r": {
710 String emergencyNumberCmd = getNextArgRequired();
711 if (emergencyNumberCmd == null
712 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700713 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800714 + " to be specified after -r in the command ");
715 return -1;
716 }
717 try {
718 mInterface.updateEmergencyNumberListTestMode(
719 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
720 new EmergencyNumber(emergencyNumberCmd, "", "",
721 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
722 new ArrayList<String>(),
723 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
724 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
725 } catch (RemoteException ex) {
726 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
727 + ", error " + ex.getMessage());
728 errPw.println("Exception: " + ex.getMessage());
729 return -1;
730 }
731 break;
732 }
733 case "-p": {
734 try {
735 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
736 } catch (RemoteException ex) {
737 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
738 errPw.println("Exception: " + ex.getMessage());
739 return -1;
740 }
741 break;
742 }
743 default:
744 onHelpEmergencyNumber();
745 break;
746 }
747 return 0;
748 }
749
Hall Liud892bec2018-11-30 14:51:45 -0800750 private int handleNumberVerificationCommand() {
751 String arg = getNextArg();
752 if (arg == null) {
753 onHelpNumberVerification();
754 return 0;
755 }
756
Hall Liuca5af3a2018-12-04 16:58:23 -0800757 if (!checkShellUid()) {
758 return -1;
759 }
760
Hall Liud892bec2018-11-30 14:51:45 -0800761 switch (arg) {
762 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800763 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
764 return 0;
765 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800766 case NUMBER_VERIFICATION_FAKE_CALL: {
767 boolean val = NumberVerificationManager.getInstance()
768 .checkIncomingCall(getNextArg());
769 getOutPrintWriter().println(val ? "1" : "0");
770 return 0;
771 }
Hall Liud892bec2018-11-30 14:51:45 -0800772 }
773
774 return -1;
775 }
776
Jordan Liu0ccee222021-04-27 11:55:13 -0700777 private boolean subIsEsim(int subId) {
778 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
779 if (info != null) {
780 return info.isEmbedded();
781 }
782 return false;
783 }
784
785 private int handleEnablePhysicalSubscription(boolean enable) {
786 PrintWriter errPw = getErrPrintWriter();
787 int subId = 0;
788 try {
789 subId = Integer.parseInt(getNextArgRequired());
790 } catch (NumberFormatException e) {
791 errPw.println((enable ? "enable" : "disable")
792 + "-physical-subscription requires an integer as a subId.");
793 return -1;
794 }
795 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
796 // non user build.
797 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
798 errPw.println("cc: Permission denied.");
799 return -1;
800 }
801 // Verify that the subId represents a physical sub
802 if (subIsEsim(subId)) {
803 errPw.println("SubId " + subId + " is not for a physical subscription");
804 return -1;
805 }
806 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
807 + " physical subscription with subId=" + subId);
808 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
809 return 0;
810 }
811
Jack Nudelman644b91a2021-03-12 14:09:48 -0800812 private int handleThermalMitigationCommand() {
813 String arg = getNextArg();
814 String packageName = getNextArg();
815 if (arg == null || packageName == null) {
816 onHelpThermalMitigation();
817 return 0;
818 }
819
820 if (!checkShellUid()) {
821 return -1;
822 }
823
824 switch (arg) {
825 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
826 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
827 return 0;
828 }
829 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
830 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
831 mContext);
832 return 0;
833 }
834 default:
835 onHelpThermalMitigation();
836 }
837
838 return -1;
839
840 }
841
Tyler Gunn92479152021-01-20 16:30:10 -0800842 private int handleD2dCommand() {
843 String arg = getNextArg();
844 if (arg == null) {
845 onHelpD2D();
846 return 0;
847 }
848
849 switch (arg) {
850 case D2D_SEND: {
851 return handleD2dSendCommand();
852 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800853 case D2D_TRANSPORT: {
854 return handleD2dTransportCommand();
855 }
Tyler Gunn92479152021-01-20 16:30:10 -0800856 }
857
858 return -1;
859 }
860
861 private int handleD2dSendCommand() {
862 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800863 int messageType = -1;
864 int messageValue = -1;
865
Tyler Gunn92479152021-01-20 16:30:10 -0800866 String arg = getNextArg();
867 if (arg == null) {
868 onHelpD2D();
869 return 0;
870 }
871 try {
872 messageType = Integer.parseInt(arg);
873 } catch (NumberFormatException e) {
874 errPw.println("message type must be a valid integer");
875 return -1;
876 }
877
878 arg = getNextArg();
879 if (arg == null) {
880 onHelpD2D();
881 return 0;
882 }
883 try {
884 messageValue = Integer.parseInt(arg);
885 } catch (NumberFormatException e) {
886 errPw.println("message value must be a valid integer");
887 return -1;
888 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800889
Tyler Gunn92479152021-01-20 16:30:10 -0800890 try {
891 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
892 } catch (RemoteException e) {
893 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
894 errPw.println("Exception: " + e.getMessage());
895 return -1;
896 }
897
898 return 0;
899 }
900
Tyler Gunnbabbda02021-02-10 11:05:02 -0800901 private int handleD2dTransportCommand() {
902 PrintWriter errPw = getErrPrintWriter();
903
904 String arg = getNextArg();
905 if (arg == null) {
906 onHelpD2D();
907 return 0;
908 }
909
910 try {
911 mInterface.setActiveDeviceToDeviceTransport(arg);
912 } catch (RemoteException e) {
913 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
914 errPw.println("Exception: " + e.getMessage());
915 return -1;
916 }
917 return 0;
918 }
919
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700920 // ims set-ims-service
921 private int handleImsSetServiceCommand() {
922 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700923 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700924 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800925 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700926
927 String opt;
928 while ((opt = getNextOption()) != null) {
929 switch (opt) {
930 case "-s": {
931 try {
932 slotId = Integer.parseInt(getNextArgRequired());
933 } catch (NumberFormatException e) {
934 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
935 return -1;
936 }
937 break;
938 }
939 case "-c": {
940 isCarrierService = true;
941 break;
942 }
943 case "-d": {
944 isCarrierService = false;
945 break;
946 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800947 case "-f": {
948 String featureString = getNextArgRequired();
949 String[] features = featureString.split(",");
950 for (int i = 0; i < features.length; i++) {
951 try {
952 Integer result = Integer.parseInt(features[i]);
953 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
954 || result >= ImsFeature.FEATURE_MAX) {
955 errPw.println("ims set-ims-service -f " + result
956 + " is an invalid feature.");
957 return -1;
958 }
959 featuresList.add(result);
960 } catch (NumberFormatException e) {
961 errPw.println("ims set-ims-service -f tried to parse " + features[i]
962 + " as an integer.");
963 return -1;
964 }
965 }
966 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700967 }
968 }
969 // Mandatory param, either -c or -d
970 if (isCarrierService == null) {
971 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
972 return -1;
973 }
974
975 String packageName = getNextArg();
976
977 try {
978 if (packageName == null) {
979 packageName = "";
980 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800981 int[] featureArray = new int[featuresList.size()];
982 for (int i = 0; i < featuresList.size(); i++) {
983 featureArray[i] = featuresList.get(i);
984 }
985 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
986 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700987 if (VDBG) {
988 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800989 + (isCarrierService ? "-c " : "-d ")
990 + "-f " + featuresList + " "
991 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700992 }
993 getOutPrintWriter().println(result);
994 } catch (RemoteException e) {
995 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800996 + (isCarrierService ? "-c " : "-d ")
997 + "-f " + featuresList + " "
998 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700999 errPw.println("Exception: " + e.getMessage());
1000 return -1;
1001 }
1002 return 0;
1003 }
1004
Brad Ebinger999d3302020-11-25 14:31:39 -08001005 // ims clear-ims-service-override
1006 private int handleImsClearCarrierServiceCommand() {
1007 PrintWriter errPw = getErrPrintWriter();
1008 int slotId = getDefaultSlot();
1009
1010 String opt;
1011 while ((opt = getNextOption()) != null) {
1012 switch (opt) {
1013 case "-s": {
1014 try {
1015 slotId = Integer.parseInt(getNextArgRequired());
1016 } catch (NumberFormatException e) {
1017 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1018 return -1;
1019 }
1020 break;
1021 }
1022 }
1023 }
1024
1025 try {
1026 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1027 if (VDBG) {
1028 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1029 + ", result=" + result);
1030 }
1031 getOutPrintWriter().println(result);
1032 } catch (RemoteException e) {
1033 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1034 + ", error" + e.getMessage());
1035 errPw.println("Exception: " + e.getMessage());
1036 return -1;
1037 }
1038 return 0;
1039 }
1040
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001041 // ims get-ims-service
1042 private int handleImsGetServiceCommand() {
1043 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001044 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001045 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001046 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001047
1048 String opt;
1049 while ((opt = getNextOption()) != null) {
1050 switch (opt) {
1051 case "-s": {
1052 try {
1053 slotId = Integer.parseInt(getNextArgRequired());
1054 } catch (NumberFormatException e) {
1055 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1056 return -1;
1057 }
1058 break;
1059 }
1060 case "-c": {
1061 isCarrierService = true;
1062 break;
1063 }
1064 case "-d": {
1065 isCarrierService = false;
1066 break;
1067 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001068 case "-f": {
1069 try {
1070 featureType = Integer.parseInt(getNextArg());
1071 } catch (NumberFormatException e) {
1072 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1073 return -1;
1074 }
1075 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1076 || featureType >= ImsFeature.FEATURE_MAX) {
1077 errPw.println("ims get-ims-service -f invalid feature.");
1078 return -1;
1079 }
1080 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001081 }
1082 }
1083 // Mandatory param, either -c or -d
1084 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001085 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001086 return -1;
1087 }
1088
1089 String result;
1090 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001091 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001092 } catch (RemoteException e) {
1093 return -1;
1094 }
1095 if (VDBG) {
1096 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001097 + (isCarrierService ? "-c " : "-d ")
1098 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1099 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001100 }
1101 getOutPrintWriter().println(result);
1102 return 0;
1103 }
1104
1105 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001106 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001107 String opt;
1108 while ((opt = getNextOption()) != null) {
1109 switch (opt) {
1110 case "-s": {
1111 try {
1112 slotId = Integer.parseInt(getNextArgRequired());
1113 } catch (NumberFormatException e) {
1114 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1115 return -1;
1116 }
1117 break;
1118 }
1119 }
1120 }
1121 try {
1122 mInterface.enableIms(slotId);
1123 } catch (RemoteException e) {
1124 return -1;
1125 }
1126 if (VDBG) {
1127 Log.v(LOG_TAG, "ims enable -s " + slotId);
1128 }
1129 return 0;
1130 }
1131
1132 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001133 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001134 String opt;
1135 while ((opt = getNextOption()) != null) {
1136 switch (opt) {
1137 case "-s": {
1138 try {
1139 slotId = Integer.parseInt(getNextArgRequired());
1140 } catch (NumberFormatException e) {
1141 getErrPrintWriter().println(
1142 "ims disable requires an integer as a SLOT_ID.");
1143 return -1;
1144 }
1145 break;
1146 }
1147 }
1148 }
1149 try {
1150 mInterface.disableIms(slotId);
1151 } catch (RemoteException e) {
1152 return -1;
1153 }
1154 if (VDBG) {
1155 Log.v(LOG_TAG, "ims disable -s " + slotId);
1156 }
1157 return 0;
1158 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001159
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001160 private int handleCepChange() {
1161 Log.i(LOG_TAG, "handleCepChange");
1162 String opt = getNextArg();
1163 if (opt == null) {
1164 return -1;
1165 }
1166 boolean isCepEnabled = opt.equals("enable");
1167
1168 try {
1169 mInterface.setCepEnabled(isCepEnabled);
1170 } catch (RemoteException e) {
1171 return -1;
1172 }
1173 return 0;
1174 }
1175
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001176 private int getDefaultSlot() {
1177 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1178 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1179 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1180 // If there is no default, default to slot 0.
1181 slotId = DEFAULT_PHONE_ID;
1182 }
1183 return slotId;
1184 }
sqian2fff4a32018-11-05 14:18:37 -08001185
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001186 // Parse options related to Carrier Config Commands.
1187 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001188 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001189 CcOptionParseResult result = new CcOptionParseResult();
1190 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1191 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001192
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001193 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001194 while ((opt = getNextOption()) != null) {
1195 switch (opt) {
1196 case "-s": {
1197 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001198 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1199 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1200 errPw.println(tag + "No valid subscription found.");
1201 return null;
1202 }
1203
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001204 } catch (IllegalArgumentException e) {
1205 // Missing slot id
1206 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001207 return null;
1208 }
1209 break;
1210 }
1211 case "-p": {
1212 if (allowOptionPersistent) {
1213 result.mPersistent = true;
1214 } else {
1215 errPw.println(tag + "Unexpected option " + opt);
1216 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001217 }
1218 break;
1219 }
1220 default: {
1221 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001222 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001223 }
1224 }
1225 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001226 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001227 }
1228
1229 private int slotStringToSubId(String tag, String slotString) {
1230 int slotId = -1;
1231 try {
1232 slotId = Integer.parseInt(slotString);
1233 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001234 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1235 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1236 }
1237
1238 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001239 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1240 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1241 }
1242
Qiong Liuf25799b2020-09-10 10:13:46 +08001243 Phone phone = PhoneFactory.getPhone(slotId);
1244 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001245 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1246 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1247 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001248 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001249 }
1250
Hall Liud892bec2018-11-30 14:51:45 -08001251 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001252 // adb can run as root or as shell, depending on whether the device is rooted.
1253 return Binder.getCallingUid() == Process.SHELL_UID
1254 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001255 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001256
1257 private int handleCcCommand() {
1258 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1259 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001260 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001261 getErrPrintWriter().println("cc: Permission denied.");
1262 return -1;
1263 }
1264
1265 String arg = getNextArg();
1266 if (arg == null) {
1267 onHelpCc();
1268 return 0;
1269 }
1270
1271 switch (arg) {
1272 case CC_GET_VALUE: {
1273 return handleCcGetValue();
1274 }
1275 case CC_SET_VALUE: {
1276 return handleCcSetValue();
1277 }
1278 case CC_CLEAR_VALUES: {
1279 return handleCcClearValues();
1280 }
1281 default: {
1282 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1283 }
1284 }
1285 return -1;
1286 }
1287
1288 // cc get-value
1289 private int handleCcGetValue() {
1290 PrintWriter errPw = getErrPrintWriter();
1291 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1292 String key = null;
1293
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001294 // Parse all options
1295 CcOptionParseResult options = parseCcOptions(tag, false);
1296 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001297 return -1;
1298 }
1299
1300 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001301 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001302 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001303 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001304 return -1;
1305 }
1306
1307 // Get the key.
1308 key = getNextArg();
1309 if (key != null) {
1310 // A key was provided. Verify if it is a valid key
1311 if (!bundle.containsKey(key)) {
1312 errPw.println(tag + key + " is not a valid key.");
1313 return -1;
1314 }
1315
1316 // Print the carrier config value for key.
1317 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1318 } else {
1319 // No key provided. Show all values.
1320 // Iterate over a sorted list of all carrier config keys and print them.
1321 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1322 for (String k : sortedSet) {
1323 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1324 }
1325 }
1326 return 0;
1327 }
1328
1329 // cc set-value
1330 private int handleCcSetValue() {
1331 PrintWriter errPw = getErrPrintWriter();
1332 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1333
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001334 // Parse all options
1335 CcOptionParseResult options = parseCcOptions(tag, true);
1336 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001337 return -1;
1338 }
1339
1340 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001341 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001342 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001343 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001344 return -1;
1345 }
1346
1347 // Get the key.
1348 String key = getNextArg();
1349 if (key == null || key.equals("")) {
1350 errPw.println(tag + "KEY is missing");
1351 return -1;
1352 }
1353
1354 // Verify if the key is valid
1355 if (!originalValues.containsKey(key)) {
1356 errPw.println(tag + key + " is not a valid key.");
1357 return -1;
1358 }
1359
1360 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1361 ArrayList<String> valueList = new ArrayList<String>();
1362 while (peekNextArg() != null) {
1363 valueList.add(getNextArg());
1364 }
1365
1366 // Find the type of the carrier config value
1367 CcType type = getType(tag, key, originalValues);
1368 if (type == CcType.UNKNOWN) {
1369 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1370 return -1;
1371 }
1372
1373 // Create an override bundle containing the key and value that should be overriden.
1374 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1375 if (overrideBundle == null) {
1376 return -1;
1377 }
1378
1379 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001380 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001381
1382 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001383 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001384 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001385 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001386 return -1;
1387 }
1388
1389 // Print the original and new value.
1390 String originalValueString = ccValueToString(key, type, originalValues);
1391 String newValueString = ccValueToString(key, type, newValues);
1392 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1393 getOutPrintWriter().println("New value: \n" + newValueString);
1394
1395 return 0;
1396 }
1397
1398 // cc clear-values
1399 private int handleCcClearValues() {
1400 PrintWriter errPw = getErrPrintWriter();
1401 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1402
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001403 // Parse all options
1404 CcOptionParseResult options = parseCcOptions(tag, false);
1405 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001406 return -1;
1407 }
1408
1409 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001410 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001411 getOutPrintWriter()
1412 .println("All previously set carrier config override values has been cleared");
1413 return 0;
1414 }
1415
1416 private CcType getType(String tag, String key, PersistableBundle bundle) {
1417 // Find the type by checking the type of the current value stored in the bundle.
1418 Object value = bundle.get(key);
1419
1420 if (CC_TYPE_MAP.containsKey(key)) {
1421 return CC_TYPE_MAP.get(key);
1422 } else if (value != null) {
1423 if (value instanceof Boolean) {
1424 return CcType.BOOLEAN;
1425 } else if (value instanceof Double) {
1426 return CcType.DOUBLE;
1427 } else if (value instanceof double[]) {
1428 return CcType.DOUBLE_ARRAY;
1429 } else if (value instanceof Integer) {
1430 return CcType.INT;
1431 } else if (value instanceof int[]) {
1432 return CcType.INT_ARRAY;
1433 } else if (value instanceof Long) {
1434 return CcType.LONG;
1435 } else if (value instanceof long[]) {
1436 return CcType.LONG_ARRAY;
1437 } else if (value instanceof String) {
1438 return CcType.STRING;
1439 } else if (value instanceof String[]) {
1440 return CcType.STRING_ARRAY;
1441 }
1442 } else {
1443 // Current value was null and can therefore not be used in order to find the type.
1444 // Check the name of the key to infer the type. This check is not needed for primitive
1445 // data types (boolean, double, int and long), since they can not be null.
1446 if (key.endsWith("double_array")) {
1447 return CcType.DOUBLE_ARRAY;
1448 }
1449 if (key.endsWith("int_array")) {
1450 return CcType.INT_ARRAY;
1451 }
1452 if (key.endsWith("long_array")) {
1453 return CcType.LONG_ARRAY;
1454 }
1455 if (key.endsWith("string")) {
1456 return CcType.STRING;
1457 }
1458 if (key.endsWith("string_array") || key.endsWith("strings")) {
1459 return CcType.STRING_ARRAY;
1460 }
1461 }
1462
1463 // Not possible to infer the type by looking at the current value or the key.
1464 PrintWriter errPw = getErrPrintWriter();
1465 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1466 return CcType.UNKNOWN;
1467 }
1468
1469 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1470 String result;
1471 StringBuilder valueString = new StringBuilder();
1472 String typeString = type.toString();
1473 Object value = bundle.get(key);
1474
1475 if (value == null) {
1476 valueString.append("null");
1477 } else {
1478 switch (type) {
1479 case DOUBLE_ARRAY: {
1480 // Format the string representation of the int array as value1 value2......
1481 double[] valueArray = (double[]) value;
1482 for (int i = 0; i < valueArray.length; i++) {
1483 if (i != 0) {
1484 valueString.append(" ");
1485 }
1486 valueString.append(valueArray[i]);
1487 }
1488 break;
1489 }
1490 case INT_ARRAY: {
1491 // Format the string representation of the int array as value1 value2......
1492 int[] valueArray = (int[]) value;
1493 for (int i = 0; i < valueArray.length; i++) {
1494 if (i != 0) {
1495 valueString.append(" ");
1496 }
1497 valueString.append(valueArray[i]);
1498 }
1499 break;
1500 }
1501 case LONG_ARRAY: {
1502 // Format the string representation of the int array as value1 value2......
1503 long[] valueArray = (long[]) value;
1504 for (int i = 0; i < valueArray.length; i++) {
1505 if (i != 0) {
1506 valueString.append(" ");
1507 }
1508 valueString.append(valueArray[i]);
1509 }
1510 break;
1511 }
1512 case STRING: {
1513 valueString.append("\"" + value.toString() + "\"");
1514 break;
1515 }
1516 case STRING_ARRAY: {
1517 // Format the string representation of the string array as "value1" "value2"....
1518 String[] valueArray = (String[]) value;
1519 for (int i = 0; i < valueArray.length; i++) {
1520 if (i != 0) {
1521 valueString.append(" ");
1522 }
1523 if (valueArray[i] != null) {
1524 valueString.append("\"" + valueArray[i] + "\"");
1525 } else {
1526 valueString.append("null");
1527 }
1528 }
1529 break;
1530 }
1531 default: {
1532 valueString.append(value.toString());
1533 }
1534 }
1535 }
1536 return String.format("%-70s %-15s %s", key, typeString, valueString);
1537 }
1538
1539 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1540 ArrayList<String> valueList) {
1541 PrintWriter errPw = getErrPrintWriter();
1542 PersistableBundle bundle = new PersistableBundle();
1543
1544 // First verify that a valid number of values has been provided for the type.
1545 switch (type) {
1546 case BOOLEAN:
1547 case DOUBLE:
1548 case INT:
1549 case LONG: {
1550 if (valueList.size() != 1) {
1551 errPw.println(tag + "Expected 1 value for type " + type
1552 + ". Found: " + valueList.size());
1553 return null;
1554 }
1555 break;
1556 }
1557 case STRING: {
1558 if (valueList.size() > 1) {
1559 errPw.println(tag + "Expected 0 or 1 values for type " + type
1560 + ". Found: " + valueList.size());
1561 return null;
1562 }
1563 break;
1564 }
1565 }
1566
1567 // Parse the value according to type and add it to the Bundle.
1568 switch (type) {
1569 case BOOLEAN: {
1570 if ("true".equalsIgnoreCase(valueList.get(0))) {
1571 bundle.putBoolean(key, true);
1572 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1573 bundle.putBoolean(key, false);
1574 } else {
1575 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1576 return null;
1577 }
1578 break;
1579 }
1580 case DOUBLE: {
1581 try {
1582 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1583 } catch (NumberFormatException nfe) {
1584 // Not a valid double
1585 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1586 return null;
1587 }
1588 break;
1589 }
1590 case DOUBLE_ARRAY: {
1591 double[] valueDoubleArray = null;
1592 if (valueList.size() > 0) {
1593 valueDoubleArray = new double[valueList.size()];
1594 for (int i = 0; i < valueList.size(); i++) {
1595 try {
1596 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1597 } catch (NumberFormatException nfe) {
1598 // Not a valid double
1599 errPw.println(
1600 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1601 return null;
1602 }
1603 }
1604 }
1605 bundle.putDoubleArray(key, valueDoubleArray);
1606 break;
1607 }
1608 case INT: {
1609 try {
1610 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1611 } catch (NumberFormatException nfe) {
1612 // Not a valid integer
1613 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1614 return null;
1615 }
1616 break;
1617 }
1618 case INT_ARRAY: {
1619 int[] valueIntArray = null;
1620 if (valueList.size() > 0) {
1621 valueIntArray = new int[valueList.size()];
1622 for (int i = 0; i < valueList.size(); i++) {
1623 try {
1624 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1625 } catch (NumberFormatException nfe) {
1626 // Not a valid integer
1627 errPw.println(tag
1628 + "Unable to parse " + valueList.get(i) + " as an integer.");
1629 return null;
1630 }
1631 }
1632 }
1633 bundle.putIntArray(key, valueIntArray);
1634 break;
1635 }
1636 case LONG: {
1637 try {
1638 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1639 } catch (NumberFormatException nfe) {
1640 // Not a valid long
1641 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1642 return null;
1643 }
1644 break;
1645 }
1646 case LONG_ARRAY: {
1647 long[] valueLongArray = null;
1648 if (valueList.size() > 0) {
1649 valueLongArray = new long[valueList.size()];
1650 for (int i = 0; i < valueList.size(); i++) {
1651 try {
1652 valueLongArray[i] = Long.parseLong(valueList.get(i));
1653 } catch (NumberFormatException nfe) {
1654 // Not a valid long
1655 errPw.println(
1656 tag + "Unable to parse " + valueList.get(i) + " as a long");
1657 return null;
1658 }
1659 }
1660 }
1661 bundle.putLongArray(key, valueLongArray);
1662 break;
1663 }
1664 case STRING: {
1665 String value = null;
1666 if (valueList.size() > 0) {
1667 value = valueList.get(0);
1668 }
1669 bundle.putString(key, value);
1670 break;
1671 }
1672 case STRING_ARRAY: {
1673 String[] valueStringArray = null;
1674 if (valueList.size() > 0) {
1675 valueStringArray = new String[valueList.size()];
1676 valueList.toArray(valueStringArray);
1677 }
1678 bundle.putStringArray(key, valueStringArray);
1679 break;
1680 }
1681 }
1682 return bundle;
1683 }
Shuo Qian489d9282020-07-09 11:30:03 -07001684
1685 private int handleEndBlockSuppressionCommand() {
1686 if (!checkShellUid()) {
1687 return -1;
1688 }
1689
1690 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1691 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1692 }
1693 return 0;
1694 }
Hui Wang641e81c2020-10-12 12:14:23 -07001695
Michele Berionne54af4632020-12-28 20:23:16 +00001696 private int handleRestartModemCommand() {
1697 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1698 // non user build.
1699 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1700 getErrPrintWriter().println("RestartModem: Permission denied.");
1701 return -1;
1702 }
1703
1704 boolean result = TelephonyManager.getDefault().rebootRadio();
1705 getOutPrintWriter().println(result);
1706
1707 return result ? 0 : -1;
1708 }
1709
Michele Berionne5e411512020-11-13 02:36:59 +00001710 private int handleUnattendedReboot() {
1711 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1712 // non user build.
1713 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1714 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1715 return -1;
1716 }
1717
1718 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1719 getOutPrintWriter().println("result: " + result);
1720
1721 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1722 }
1723
Hui Wang641e81c2020-10-12 12:14:23 -07001724 private int handleGbaCommand() {
1725 String arg = getNextArg();
1726 if (arg == null) {
1727 onHelpGba();
1728 return 0;
1729 }
1730
1731 switch (arg) {
1732 case GBA_SET_SERVICE: {
1733 return handleGbaSetServiceCommand();
1734 }
1735 case GBA_GET_SERVICE: {
1736 return handleGbaGetServiceCommand();
1737 }
1738 case GBA_SET_RELEASE_TIME: {
1739 return handleGbaSetReleaseCommand();
1740 }
1741 case GBA_GET_RELEASE_TIME: {
1742 return handleGbaGetReleaseCommand();
1743 }
1744 }
1745
1746 return -1;
1747 }
1748
1749 private int getSubId(String cmd) {
1750 int slotId = getDefaultSlot();
1751 String opt = getNextOption();
1752 if (opt != null && opt.equals("-s")) {
1753 try {
1754 slotId = Integer.parseInt(getNextArgRequired());
1755 } catch (NumberFormatException e) {
1756 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1757 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1758 }
1759 }
1760 int[] subIds = SubscriptionManager.getSubId(slotId);
1761 return subIds[0];
1762 }
1763
1764 private int handleGbaSetServiceCommand() {
1765 int subId = getSubId("gba set-service");
1766 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1767 return -1;
1768 }
1769
1770 String packageName = getNextArg();
1771 try {
1772 if (packageName == null) {
1773 packageName = "";
1774 }
1775 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1776 if (VDBG) {
1777 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1778 + packageName + ", result=" + result);
1779 }
1780 getOutPrintWriter().println(result);
1781 } catch (RemoteException e) {
1782 Log.w(LOG_TAG, "gba set-service " + subId + " "
1783 + packageName + ", error" + e.getMessage());
1784 getErrPrintWriter().println("Exception: " + e.getMessage());
1785 return -1;
1786 }
1787 return 0;
1788 }
1789
1790 private int handleGbaGetServiceCommand() {
1791 String result;
1792
1793 int subId = getSubId("gba get-service");
1794 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1795 return -1;
1796 }
1797
1798 try {
1799 result = mInterface.getBoundGbaService(subId);
1800 } catch (RemoteException e) {
1801 return -1;
1802 }
1803 if (VDBG) {
1804 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1805 }
1806 getOutPrintWriter().println(result);
1807 return 0;
1808 }
1809
1810 private int handleGbaSetReleaseCommand() {
1811 //the release time value could be -1
1812 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1813 : SubscriptionManager.getDefaultSubscriptionId();
1814 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1815 return -1;
1816 }
1817
1818 String intervalStr = getNextArg();
1819 if (intervalStr == null) {
1820 return -1;
1821 }
1822
1823 try {
1824 int interval = Integer.parseInt(intervalStr);
1825 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1826 if (VDBG) {
1827 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1828 + intervalStr + ", result=" + result);
1829 }
1830 getOutPrintWriter().println(result);
1831 } catch (NumberFormatException | RemoteException e) {
1832 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1833 + intervalStr + ", error" + e.getMessage());
1834 getErrPrintWriter().println("Exception: " + e.getMessage());
1835 return -1;
1836 }
1837 return 0;
1838 }
1839
1840 private int handleGbaGetReleaseCommand() {
1841 int subId = getSubId("gba get-release");
1842 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1843 return -1;
1844 }
1845
1846 int result = 0;
1847 try {
1848 result = mInterface.getGbaReleaseTime(subId);
1849 } catch (RemoteException e) {
1850 return -1;
1851 }
1852 if (VDBG) {
1853 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1854 }
1855 getOutPrintWriter().println(result);
1856 return 0;
1857 }
Hui Wang761a6682020-10-31 05:12:53 +00001858
1859 private int handleSingleRegistrationConfigCommand() {
1860 String arg = getNextArg();
1861 if (arg == null) {
1862 onHelpSrc();
1863 return 0;
1864 }
1865
1866 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001867 case SRC_SET_TEST_ENABLED: {
1868 return handleSrcSetTestEnabledCommand();
1869 }
1870 case SRC_GET_TEST_ENABLED: {
1871 return handleSrcGetTestEnabledCommand();
1872 }
Hui Wang761a6682020-10-31 05:12:53 +00001873 case SRC_SET_DEVICE_ENABLED: {
1874 return handleSrcSetDeviceEnabledCommand();
1875 }
1876 case SRC_GET_DEVICE_ENABLED: {
1877 return handleSrcGetDeviceEnabledCommand();
1878 }
1879 case SRC_SET_CARRIER_ENABLED: {
1880 return handleSrcSetCarrierEnabledCommand();
1881 }
1882 case SRC_GET_CARRIER_ENABLED: {
1883 return handleSrcGetCarrierEnabledCommand();
1884 }
Hui Wangb647abe2021-02-26 09:33:38 -08001885 case SRC_SET_FEATURE_ENABLED: {
1886 return handleSrcSetFeatureValidationCommand();
1887 }
1888 case SRC_GET_FEATURE_ENABLED: {
1889 return handleSrcGetFeatureValidationCommand();
1890 }
Hui Wang761a6682020-10-31 05:12:53 +00001891 }
1892
1893 return -1;
1894 }
1895
James.cf Linbcdf8b32021-01-14 16:44:13 +08001896 private int handleRcsUceCommand() {
1897 String arg = getNextArg();
1898 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00001899 onHelpUce();
1900 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001901 }
1902
1903 switch (arg) {
1904 case UCE_REMOVE_EAB_CONTACT:
1905 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001906 case UCE_GET_EAB_CONTACT:
1907 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001908 case UCE_GET_DEVICE_ENABLED:
1909 return handleUceGetDeviceEnabledCommand();
1910 case UCE_SET_DEVICE_ENABLED:
1911 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00001912 case UCE_OVERRIDE_PUBLISH_CAPS:
1913 return handleUceOverridePublishCaps();
1914 case UCE_GET_LAST_PIDF_XML:
1915 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001916 }
1917 return -1;
1918 }
1919
1920 private int handleRemovingEabContactCommand() {
1921 int subId = getSubId("uce remove-eab-contact");
1922 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1923 return -1;
1924 }
1925
1926 String phoneNumber = getNextArgRequired();
1927 if (TextUtils.isEmpty(phoneNumber)) {
1928 return -1;
1929 }
1930 int result = 0;
1931 try {
1932 result = mInterface.removeContactFromEab(subId, phoneNumber);
1933 } catch (RemoteException e) {
1934 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1935 getErrPrintWriter().println("Exception: " + e.getMessage());
1936 return -1;
1937 }
1938
1939 if (VDBG) {
1940 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1941 }
calvinpan293ea1b2021-02-04 17:52:13 +08001942 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001943 }
1944
calvinpane4a8a1d2021-01-25 13:51:18 +08001945 private int handleGettingEabContactCommand() {
1946 String phoneNumber = getNextArgRequired();
1947 if (TextUtils.isEmpty(phoneNumber)) {
1948 return -1;
1949 }
1950 String result = "";
1951 try {
1952 result = mInterface.getContactFromEab(phoneNumber);
1953
1954 } catch (RemoteException e) {
1955 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1956 getErrPrintWriter().println("Exception: " + e.getMessage());
1957 return -1;
1958 }
1959
1960 if (VDBG) {
1961 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1962 }
calvinpan293ea1b2021-02-04 17:52:13 +08001963 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001964 return 0;
1965 }
1966
1967 private int handleUceGetDeviceEnabledCommand() {
1968 boolean result = false;
1969 try {
1970 result = mInterface.getDeviceUceEnabled();
1971 } catch (RemoteException e) {
1972 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1973 return -1;
1974 }
1975 if (VDBG) {
1976 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1977 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001978 getOutPrintWriter().println(result);
1979 return 0;
1980 }
1981
James.cf Lin4b784aa2021-01-31 03:25:15 +08001982 private int handleUceSetDeviceEnabledCommand() {
1983 String enabledStr = getNextArg();
1984 if (TextUtils.isEmpty(enabledStr)) {
1985 return -1;
1986 }
1987
1988 try {
1989 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1990 mInterface.setDeviceUceEnabled(isEnabled);
1991 if (VDBG) {
1992 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1993 }
1994 } catch (NumberFormatException | RemoteException e) {
1995 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1996 getErrPrintWriter().println("Exception: " + e.getMessage());
1997 return -1;
1998 }
1999 return 0;
2000 }
2001
Hui Wangbaaee6a2021-02-19 20:45:36 -08002002 private int handleSrcSetTestEnabledCommand() {
2003 String enabledStr = getNextArg();
2004 if (enabledStr == null) {
2005 return -1;
2006 }
2007
2008 try {
2009 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2010 if (VDBG) {
2011 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2012 }
2013 getOutPrintWriter().println("Done");
2014 } catch (NumberFormatException | RemoteException e) {
2015 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2016 getErrPrintWriter().println("Exception: " + e.getMessage());
2017 return -1;
2018 }
2019 return 0;
2020 }
2021
2022 private int handleSrcGetTestEnabledCommand() {
2023 boolean result = false;
2024 try {
2025 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2026 } catch (RemoteException e) {
2027 return -1;
2028 }
2029 if (VDBG) {
2030 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2031 }
2032 getOutPrintWriter().println(result);
2033 return 0;
2034 }
2035
Brad Ebinger14d467f2021-02-12 06:18:28 +00002036 private int handleUceOverridePublishCaps() {
2037 int subId = getSubId("uce override-published-caps");
2038 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2039 return -1;
2040 }
2041 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2042 String operation = getNextArgRequired();
2043 String caps = getNextArg();
2044 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2045 && !"list".equals(operation)) {
2046 getErrPrintWriter().println("Invalid operation: " + operation);
2047 return -1;
2048 }
2049
2050 // add/remove requires capabilities to be specified.
2051 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2052 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2053 + "specified");
2054 return -1;
2055 }
2056
2057 ArraySet<String> capSet = new ArraySet<>();
2058 if (!TextUtils.isEmpty(caps)) {
2059 String[] capArray = caps.split(":");
2060 for (String cap : capArray) {
2061 // Allow unknown tags to be passed in as well.
2062 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2063 }
2064 }
2065
2066 RcsContactUceCapability result = null;
2067 try {
2068 switch (operation) {
2069 case "add":
2070 result = mInterface.addUceRegistrationOverrideShell(subId,
2071 new ArrayList<>(capSet));
2072 break;
2073 case "remove":
2074 result = mInterface.removeUceRegistrationOverrideShell(subId,
2075 new ArrayList<>(capSet));
2076 break;
2077 case "clear":
2078 result = mInterface.clearUceRegistrationOverrideShell(subId);
2079 break;
2080 case "list":
2081 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2082 break;
2083 }
2084 } catch (RemoteException e) {
2085 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2086 getErrPrintWriter().println("Exception: " + e.getMessage());
2087 return -1;
2088 } catch (ServiceSpecificException sse) {
2089 // Reconstruct ImsException
2090 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2091 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2092 getErrPrintWriter().println("Exception: " + imsException);
2093 return -1;
2094 }
2095 if (result == null) {
2096 getErrPrintWriter().println("Service not available");
2097 return -1;
2098 }
2099 getOutPrintWriter().println(result);
2100 return 0;
2101 }
2102
2103 private int handleUceGetPidfXml() {
2104 int subId = getSubId("uce get-last-publish-pidf");
2105 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2106 return -1;
2107 }
2108
2109 String result;
2110 try {
2111 result = mInterface.getLastUcePidfXmlShell(subId);
2112 } catch (RemoteException e) {
2113 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2114 getErrPrintWriter().println("Exception: " + e.getMessage());
2115 return -1;
2116 } catch (ServiceSpecificException sse) {
2117 // Reconstruct ImsException
2118 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2119 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2120 getErrPrintWriter().println("Exception: " + imsException);
2121 return -1;
2122 }
2123 if (result == null) {
2124 getErrPrintWriter().println("Service not available");
2125 return -1;
2126 }
2127 getOutPrintWriter().println(result);
2128 return 0;
2129 }
2130
Hui Wang761a6682020-10-31 05:12:53 +00002131 private int handleSrcSetDeviceEnabledCommand() {
2132 String enabledStr = getNextArg();
2133 if (enabledStr == null) {
2134 return -1;
2135 }
2136
2137 try {
2138 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2139 if (VDBG) {
2140 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2141 }
2142 getOutPrintWriter().println("Done");
2143 } catch (NumberFormatException | RemoteException e) {
2144 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2145 getErrPrintWriter().println("Exception: " + e.getMessage());
2146 return -1;
2147 }
2148 return 0;
2149 }
2150
2151 private int handleSrcGetDeviceEnabledCommand() {
2152 boolean result = false;
2153 try {
2154 result = mInterface.getDeviceSingleRegistrationEnabled();
2155 } catch (RemoteException e) {
2156 return -1;
2157 }
2158 if (VDBG) {
2159 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2160 }
2161 getOutPrintWriter().println(result);
2162 return 0;
2163 }
2164
2165 private int handleSrcSetCarrierEnabledCommand() {
2166 //the release time value could be -1
2167 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2168 : SubscriptionManager.getDefaultSubscriptionId();
2169 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2170 return -1;
2171 }
2172
2173 String enabledStr = getNextArg();
2174 if (enabledStr == null) {
2175 return -1;
2176 }
2177
2178 try {
2179 boolean result =
2180 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2181 if (VDBG) {
2182 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2183 + enabledStr + ", result=" + result);
2184 }
2185 getOutPrintWriter().println(result);
2186 } catch (NumberFormatException | RemoteException e) {
2187 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2188 + enabledStr + ", error" + e.getMessage());
2189 getErrPrintWriter().println("Exception: " + e.getMessage());
2190 return -1;
2191 }
2192 return 0;
2193 }
2194
2195 private int handleSrcGetCarrierEnabledCommand() {
2196 int subId = getSubId("src get-carrier-enabled");
2197 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2198 return -1;
2199 }
2200
2201 boolean result = false;
2202 try {
2203 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2204 } catch (RemoteException e) {
2205 return -1;
2206 }
2207 if (VDBG) {
2208 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2209 }
2210 getOutPrintWriter().println(result);
2211 return 0;
2212 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002213
Hui Wangb647abe2021-02-26 09:33:38 -08002214 private int handleSrcSetFeatureValidationCommand() {
2215 //the release time value could be -1
2216 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2217 : SubscriptionManager.getDefaultSubscriptionId();
2218 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2219 return -1;
2220 }
2221
2222 String enabledStr = getNextArg();
2223 if (enabledStr == null) {
2224 return -1;
2225 }
2226
2227 try {
2228 boolean result =
2229 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2230 if (VDBG) {
2231 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2232 + enabledStr + ", result=" + result);
2233 }
2234 getOutPrintWriter().println(result);
2235 } catch (NumberFormatException | RemoteException e) {
2236 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2237 + enabledStr + ", error" + e.getMessage());
2238 getErrPrintWriter().println("Exception: " + e.getMessage());
2239 return -1;
2240 }
2241 return 0;
2242 }
2243
2244 private int handleSrcGetFeatureValidationCommand() {
2245 int subId = getSubId("src get-feature-validation");
2246 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2247 return -1;
2248 }
2249
2250 Boolean result = false;
2251 try {
2252 result = mInterface.getImsFeatureValidationOverride(subId);
2253 } catch (RemoteException e) {
2254 return -1;
2255 }
2256 if (VDBG) {
2257 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2258 }
2259 getOutPrintWriter().println(result);
2260 return 0;
2261 }
2262
2263
Hall Liuaa4211e2021-01-20 15:43:39 -08002264 private void onHelpCallComposer() {
2265 PrintWriter pw = getOutPrintWriter();
2266 pw.println("Call composer commands");
2267 pw.println(" callcomposer test-mode enable|disable|query");
2268 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2269 pw.println(" upload/download from carrier servers is disabled, and operations are");
2270 pw.println(" performed using emulated local files instead.");
2271 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2272 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2273 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002274 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2275 pw.println(" Enables or disables the user setting for call composer, as set by");
2276 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002277 }
2278
2279 private int handleCallComposerCommand() {
2280 String arg = getNextArg();
2281 if (arg == null) {
2282 onHelpCallComposer();
2283 return 0;
2284 }
2285
2286 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2287 "MODIFY_PHONE_STATE required for call composer shell cmds");
2288 switch (arg) {
2289 case CALL_COMPOSER_TEST_MODE: {
2290 String enabledStr = getNextArg();
2291 if (ENABLE.equals(enabledStr)) {
2292 CallComposerPictureManager.sTestMode = true;
2293 } else if (DISABLE.equals(enabledStr)) {
2294 CallComposerPictureManager.sTestMode = false;
2295 } else if (QUERY.equals(enabledStr)) {
2296 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2297 } else {
2298 onHelpCallComposer();
2299 return 1;
2300 }
2301 break;
2302 }
2303 case CALL_COMPOSER_SIMULATE_CALL: {
2304 int subscriptionId = Integer.valueOf(getNextArg());
2305 String uuidString = getNextArg();
2306 UUID uuid = UUID.fromString(uuidString);
2307 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2308 Binder.withCleanCallingIdentity(() -> {
2309 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2310 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2311 });
2312 try {
2313 Uri uri = storageUriFuture.get();
2314 getOutPrintWriter().println(String.valueOf(uri));
2315 } catch (Exception e) {
2316 throw new RuntimeException(e);
2317 }
2318 break;
2319 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002320 case CALL_COMPOSER_USER_SETTING: {
2321 try {
2322 int subscriptionId = Integer.valueOf(getNextArg());
2323 String enabledStr = getNextArg();
2324 if (ENABLE.equals(enabledStr)) {
2325 mInterface.setCallComposerStatus(subscriptionId,
2326 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2327 } else if (DISABLE.equals(enabledStr)) {
2328 mInterface.setCallComposerStatus(subscriptionId,
2329 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2330 } else if (QUERY.equals(enabledStr)) {
2331 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2332 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2333 } else {
2334 onHelpCallComposer();
2335 return 1;
2336 }
2337 } catch (RemoteException e) {
2338 e.printStackTrace(getOutPrintWriter());
2339 return 1;
2340 }
2341 break;
2342 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002343 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002344 return 0;
2345 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002346
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002347 private int handleHasCarrierPrivilegesCommand() {
2348 String packageName = getNextArgRequired();
2349
2350 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002351 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002352 try {
2353 hasCarrierPrivileges =
2354 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2355 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2356 } catch (RemoteException e) {
2357 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2358 getErrPrintWriter().println("Exception: " + e.getMessage());
2359 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002360 } finally {
2361 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002362 }
2363
2364 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002365 return 0;
2366 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002367}