blob: 7b11c894dea668126f6824dd126d580cfe62d620 [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
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010024import android.content.Context;
Hall Liud892bec2018-11-30 14:51:45 -080025import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010026import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070028import android.os.RemoteException;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000029import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070030import android.provider.BlockedNumberContract;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010031import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.telephony.SubscriptionManager;
Michele Berionne38c1afa2020-12-28 20:23:16 +000033import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080034import android.telephony.emergency.EmergencyNumber;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000035import android.telephony.ims.ImsException;
36import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080037import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080038import android.text.TextUtils;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000039import android.util.ArrayMap;
40import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070041import android.util.Log;
42
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000043import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070044import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080045import com.android.internal.telephony.Phone;
46import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080047import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080048import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080049import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080050import com.android.modules.utils.BasicShellCommandHandler;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070051
52import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080053import java.util.ArrayList;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000054import java.util.Arrays;
55import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010056import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080057import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010058import java.util.Map;
Brad Ebingerd4c5bde2021-02-12 06:18:28 +000059import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010060import java.util.TreeSet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070061
62/**
63 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
64 * permission checks have been done before onCommand was called. Make sure any commands processed
65 * here also contain the appropriate permissions checks.
66 */
67
Hall Liua1548bd2019-12-24 14:14:12 -080068public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070069
70 private static final String LOG_TAG = "TelephonyShellCommand";
71 // Don't commit with this true.
72 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070073 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070074
75 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080076 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
sqian9d4df8b2019-01-15 18:32:07 -080077 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070078 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne38c1afa2020-12-28 20:23:16 +000079 private static final String RESTART_MODEM = "restart-modem";
Michele Berionned9fbae52020-11-13 02:36:59 +000080 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010081 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080082 private static final String DATA_TEST_MODE = "data";
83 private static final String DATA_ENABLE = "enable";
84 private static final String DATA_DISABLE = "disable";
Hall Liud892bec2018-11-30 14:51:45 -080085
Brad Ebinger999d3302020-11-25 14:31:39 -080086 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
87 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
88 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070089 private static final String IMS_ENABLE = "enable";
90 private static final String IMS_DISABLE = "disable";
Tyler Gunn7bcdc742019-10-04 15:56:59 -070091 // Used to disable or enable processing of conference event package data from the network.
92 // This is handy for testing scenarios where CEP data does not exist on a network which does
93 // support CEP data.
94 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070095
Hall Liud892bec2018-11-30 14:51:45 -080096 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -080097 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -080098
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010099 private static final String CC_GET_VALUE = "get-value";
100 private static final String CC_SET_VALUE = "set-value";
101 private static final String CC_CLEAR_VALUES = "clear-values";
102
Hui Wang0866fcc2020-10-12 12:14:23 -0700103 private static final String GBA_SUBCOMMAND = "gba";
104 private static final String GBA_SET_SERVICE = "set-service";
105 private static final String GBA_GET_SERVICE = "get-service";
106 private static final String GBA_SET_RELEASE_TIME = "set-release";
107 private static final String GBA_GET_RELEASE_TIME = "get-release";
108
Hui Wang068ab862020-10-31 05:12:53 +0000109 private static final String SINGLE_REGISTATION_CONFIG = "src";
110 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
111 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
112 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
113 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wang19a21872021-02-19 20:45:36 -0800114 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
115 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangeadb2562021-02-26 09:33:38 -0800116 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
117 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang068ab862020-10-31 05:12:53 +0000118
Tyler Gunn92479152021-01-20 16:30:10 -0800119 private static final String D2D_SUBCOMMAND = "d2d";
120 private static final String D2D_SEND = "send";
121
James.cf Linbcdf8b32021-01-14 16:44:13 +0800122 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800123 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800124 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800125 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
126 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000127 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
128 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800129 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
130 "remove-request-disallowed-status";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800131
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800132 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
133 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
134
Jack Nudelman644b91a2021-03-12 14:09:48 -0800135 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
136 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
137 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
138
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700139 // Take advantage of existing methods that already contain permissions checks when possible.
140 private final ITelephony mInterface;
141
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100142 private SubscriptionManager mSubscriptionManager;
143 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700144 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100145
146 private enum CcType {
147 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
148 STRING_ARRAY, UNKNOWN
149 }
150
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100151 private class CcOptionParseResult {
152 public int mSubId;
153 public boolean mPersistent;
154 }
155
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100156 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
157 // keys by looking at the end of the string which usually tells the type.
158 // For instance: "xxxx_string", "xxxx_string_array", etc.
159 // The carrier config keys in this map does not follow this convention. It is therefore not
160 // possible to infer the type for these keys by looking at the string.
161 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
162 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
163 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
164 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
165 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
166 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
167 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
168 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
169 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
170 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
171 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
172 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
173 CcType.STRING);
174 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
175 CcType.STRING_ARRAY);
176 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
177 CcType.STRING_ARRAY);
178 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
179 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
180 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
181 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
182 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
183 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
184 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
185 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
186 }
187 };
188
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000189 /**
190 * Map from a shorthand string to the feature tags required in registration required in order
191 * for the RCS feature to be considered "capable".
192 */
193 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
194 static {
195 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
196 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
197 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
198 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
199 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
200 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
201 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
202 FeatureTags.FEATURE_TAG_VIDEO)));
203 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
204 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
205 map.put("call_comp",
206 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
207 map.put("call_comp_mmtel",
208 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
209 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
210 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
211 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
212 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
213 // version
214 map.put("chatbot", new ArraySet<>(Arrays.asList(
215 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
216 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
217 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
218 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
219 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
220 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
221 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
222 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
223 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
224 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
225 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
226 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
227 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
228 }
229
230
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100231 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700232 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100233 mCarrierConfigManager =
234 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
235 mSubscriptionManager = (SubscriptionManager)
236 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700237 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700238 }
239
240 @Override
241 public int onCommand(String cmd) {
242 if (cmd == null) {
243 return handleDefaultCommands(null);
244 }
245
246 switch (cmd) {
247 case IMS_SUBCOMMAND: {
248 return handleImsCommand();
249 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800250 case RCS_UCE_COMMAND:
251 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800252 case NUMBER_VERIFICATION_SUBCOMMAND:
253 return handleNumberVerificationCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800254 case EMERGENCY_NUMBER_TEST_MODE:
255 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100256 case CARRIER_CONFIG_SUBCOMMAND: {
257 return handleCcCommand();
258 }
Shuo Qianf5125122019-12-16 17:03:07 -0800259 case DATA_TEST_MODE:
260 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700261 case END_BLOCK_SUPPRESSION:
262 return handleEndBlockSuppressionCommand();
Hui Wang0866fcc2020-10-12 12:14:23 -0700263 case GBA_SUBCOMMAND:
264 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800265 case D2D_SUBCOMMAND:
266 return handleD2dCommand();
Hui Wang068ab862020-10-31 05:12:53 +0000267 case SINGLE_REGISTATION_CONFIG:
268 return handleSingleRegistrationConfigCommand();
Michele Berionne38c1afa2020-12-28 20:23:16 +0000269 case RESTART_MODEM:
270 return handleRestartModemCommand();
Michele Berionned9fbae52020-11-13 02:36:59 +0000271 case UNATTENDED_REBOOT:
272 return handleUnattendedReboot();
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800273 case HAS_CARRIER_PRIVILEGES_COMMAND:
274 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800275 case THERMAL_MITIGATION_COMMAND:
276 return handleThermalMitigationCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700277 default: {
278 return handleDefaultCommands(cmd);
279 }
280 }
281 }
282
283 @Override
284 public void onHelp() {
285 PrintWriter pw = getOutPrintWriter();
286 pw.println("Telephony Commands:");
287 pw.println(" help");
288 pw.println(" Print this help text.");
289 pw.println(" ims");
290 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800291 pw.println(" uce");
292 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800293 pw.println(" emergency-number-test-mode");
294 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700295 pw.println(" end-block-suppression");
296 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800297 pw.println(" data");
298 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100299 pw.println(" cc");
300 pw.println(" Carrier Config Commands.");
Hui Wang0866fcc2020-10-12 12:14:23 -0700301 pw.println(" gba");
302 pw.println(" GBA Commands.");
Hui Wang068ab862020-10-31 05:12:53 +0000303 pw.println(" src");
304 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne38c1afa2020-12-28 20:23:16 +0000305 pw.println(" restart-modem");
306 pw.println(" Restart modem command.");
Michele Berionned9fbae52020-11-13 02:36:59 +0000307 pw.println(" unattended-reboot");
308 pw.println(" Prepare for unattended reboot.");
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800309 pw.println(" has-carrier-privileges [package]");
310 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700311 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800312 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800313 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700314 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800315 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100316 onHelpCc();
Hui Wang0866fcc2020-10-12 12:14:23 -0700317 onHelpGba();
Hui Wang068ab862020-10-31 05:12:53 +0000318 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800319 onHelpD2D();
320 }
321
322 private void onHelpD2D() {
323 PrintWriter pw = getOutPrintWriter();
324 pw.println("D2D Comms Commands:");
325 pw.println(" d2d send TYPE VALUE");
326 pw.println(" Sends a D2D message of specified type and value.");
327 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
328 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
329 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
330 MESSAGE_CALL_AUDIO_CODEC));
331 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
332 + Communicator.messageToString(
333 MESSAGE_DEVICE_BATTERY_STATE));
334 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
335 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700336 }
337
338 private void onHelpIms() {
339 PrintWriter pw = getOutPrintWriter();
340 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800341 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700342 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
343 pw.println(" ImsService. Options are:");
344 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
345 pw.println(" is specified, it will choose the default voice SIM slot.");
346 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
347 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800348 pw.println(" -f: Set the feature that this override if for, if no option is");
349 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700350 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
351 pw.println(" Gets the package name of the currently defined ImsService.");
352 pw.println(" Options are:");
353 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
354 pw.println(" is specified, it will choose the default voice SIM slot.");
355 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000356 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800357 pw.println(" -f: The feature type that the query will be requested for. If none is");
358 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800359 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
360 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
361 pw.println(" configuration overrides. Options are:");
362 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
363 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700364 pw.println(" ims enable [-s SLOT_ID]");
365 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
366 pw.println(" if none is specified.");
367 pw.println(" ims disable [-s SLOT_ID]");
368 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
369 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700370 pw.println(" ims conference-event-package [enable/disable]");
371 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700372 }
373
James.cf Linbcdf8b32021-01-14 16:44:13 +0800374 private void onHelpUce() {
375 PrintWriter pw = getOutPrintWriter();
376 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800377 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
378 pw.println(" Get the EAB contacts from the EAB database.");
379 pw.println(" Options are:");
380 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
381 pw.println(" Expected output format :");
382 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800383 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
384 pw.println(" Remove the EAB contacts from the EAB database.");
385 pw.println(" Options are:");
386 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
387 pw.println(" is specified, it will choose the default voice SIM slot.");
388 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800389 pw.println(" uce get-device-enabled");
390 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
391 pw.println(" uce set-device-enabled true|false");
392 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
393 pw.println(" The value could be true, false.");
Brad Ebingerd4c5bde2021-02-12 06:18:28 +0000394 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
395 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
396 pw.println(" Options are:");
397 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
398 pw.println(" is specified, it will choose the default voice SIM slot.");
399 pw.println(" add [CAPABILITY]: add a new capability");
400 pw.println(" remove [CAPABILITY]: remove a capability");
401 pw.println(" clear: clear all capability overrides");
402 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
403 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
404 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
405 pw.println(" chatbot_sa, chatbot_role] as well as full length");
406 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
407 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
408 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
409 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800410 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
411 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800412 }
413
Hall Liud892bec2018-11-30 14:51:45 -0800414 private void onHelpNumberVerification() {
415 PrintWriter pw = getOutPrintWriter();
416 pw.println("Number verification commands");
417 pw.println(" numverify override-package PACKAGE_NAME;");
418 pw.println(" Set the authorized package for number verification.");
419 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800420 pw.println(" numverify fake-call NUMBER;");
421 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
422 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800423 }
424
Jack Nudelman644b91a2021-03-12 14:09:48 -0800425 private void onHelpThermalMitigation() {
426 PrintWriter pw = getOutPrintWriter();
427 pw.println("Thermal mitigation commands");
428 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
429 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
430 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
431 pw.println(" Remove the package from one of the authorized packages for thermal "
432 + "mitigation.");
433 }
434
Shuo Qianf5125122019-12-16 17:03:07 -0800435 private void onHelpDataTestMode() {
436 PrintWriter pw = getOutPrintWriter();
437 pw.println("Mobile Data Test Mode Commands:");
438 pw.println(" data enable: enable mobile data connectivity");
439 pw.println(" data disable: disable mobile data connectivity");
440 }
441
sqian9d4df8b2019-01-15 18:32:07 -0800442 private void onHelpEmergencyNumber() {
443 PrintWriter pw = getOutPrintWriter();
444 pw.println("Emergency Number Test Mode Commands:");
445 pw.println(" emergency-number-test-mode ");
446 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
447 + " the test mode");
448 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700449 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800450 pw.println(" -c: clear the emergency number list in the test mode.");
451 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700452 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800453 pw.println(" -p: get the full emergency number list in the test mode.");
454 }
455
Shuo Qian489d9282020-07-09 11:30:03 -0700456 private void onHelpEndBlockSupperssion() {
457 PrintWriter pw = getOutPrintWriter();
458 pw.println("End Block Suppression command:");
459 pw.println(" end-block-suppression: disable suppressing blocking by contact");
460 pw.println(" with emergency services.");
461 }
462
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100463 private void onHelpCc() {
464 PrintWriter pw = getOutPrintWriter();
465 pw.println("Carrier Config Commands:");
466 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
467 pw.println(" Print carrier config values.");
468 pw.println(" Options are:");
469 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
470 pw.println(" is specified, it will choose the default voice SIM slot.");
471 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
472 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100473 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100474 pw.println(" Set carrier config KEY to NEW_VALUE.");
475 pw.println(" Options are:");
476 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
477 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100478 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100479 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
480 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
481 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
482 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
483 pw.println(" cc clear-values [-s SLOT_ID]");
484 pw.println(" Clear all carrier override values that has previously been set");
485 pw.println(" with set-value");
486 pw.println(" Options are:");
487 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
488 pw.println(" is specified, it will choose the default voice SIM slot.");
489 }
490
Hui Wang0866fcc2020-10-12 12:14:23 -0700491 private void onHelpGba() {
492 PrintWriter pw = getOutPrintWriter();
493 pw.println("Gba Commands:");
494 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
495 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
496 pw.println(" Options are:");
497 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
498 pw.println(" is specified, it will choose the default voice SIM slot.");
499 pw.println(" gba get-service [-s SLOT_ID]");
500 pw.println(" Gets the package name of the currently defined GbaService.");
501 pw.println(" Options are:");
502 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
503 pw.println(" is specified, it will choose the default voice SIM slot.");
504 pw.println(" gba set-release [-s SLOT_ID] n");
505 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
506 pw.println(" Do not release/unbind if n is -1.");
507 pw.println(" Options are:");
508 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
509 pw.println(" is specified, it will choose the default voice SIM slot.");
510 pw.println(" gba get-release [-s SLOT_ID]");
511 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
512 pw.println(" Options are:");
513 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
514 pw.println(" is specified, it will choose the default voice SIM slot.");
515 }
516
Hui Wang068ab862020-10-31 05:12:53 +0000517 private void onHelpSrc() {
518 PrintWriter pw = getOutPrintWriter();
519 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wang19a21872021-02-19 20:45:36 -0800520 pw.println(" src set-test-enabled true|false");
521 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
522 pw.println(" The value could be true, false, or null(undefined).");
523 pw.println(" src get-test-enabled");
524 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang068ab862020-10-31 05:12:53 +0000525 pw.println(" src set-device-enabled true|false|null");
526 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
527 pw.println(" The value could be true, false, or null(undefined).");
528 pw.println(" src get-device-enabled");
529 pw.println(" Gets the device config for RCS VoLTE single registration.");
530 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
531 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
532 pw.println(" The value could be true, false, or null(undefined).");
533 pw.println(" Options are:");
534 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
535 pw.println(" is specified, it will choose the default voice SIM slot.");
536 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
537 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
538 pw.println(" Options are:");
539 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
540 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangeadb2562021-02-26 09:33:38 -0800541 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
542 pw.println(" Sets ims feature validation result.");
543 pw.println(" The value could be true, false, or null(undefined).");
544 pw.println(" Options are:");
545 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
546 pw.println(" is specified, it will choose the default voice SIM slot.");
547 pw.println(" src get-feature-validation [-s SLOT_ID]");
548 pw.println(" Gets ims feature validation override value.");
549 pw.println(" Options are:");
550 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
551 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang068ab862020-10-31 05:12:53 +0000552 }
553
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700554 private int handleImsCommand() {
555 String arg = getNextArg();
556 if (arg == null) {
557 onHelpIms();
558 return 0;
559 }
560
561 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800562 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700563 return handleImsSetServiceCommand();
564 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800565 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700566 return handleImsGetServiceCommand();
567 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800568 case IMS_CLEAR_SERVICE_OVERRIDE: {
569 return handleImsClearCarrierServiceCommand();
570 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700571 case IMS_ENABLE: {
572 return handleEnableIms();
573 }
574 case IMS_DISABLE: {
575 return handleDisableIms();
576 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700577 case IMS_CEP: {
578 return handleCepChange();
579 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700580 }
581
582 return -1;
583 }
584
Shuo Qianf5125122019-12-16 17:03:07 -0800585 private int handleDataTestModeCommand() {
586 PrintWriter errPw = getErrPrintWriter();
587 String arg = getNextArgRequired();
588 if (arg == null) {
589 onHelpDataTestMode();
590 return 0;
591 }
592 switch (arg) {
593 case DATA_ENABLE: {
594 try {
595 mInterface.enableDataConnectivity();
596 } catch (RemoteException ex) {
597 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
598 errPw.println("Exception: " + ex.getMessage());
599 return -1;
600 }
601 break;
602 }
603 case DATA_DISABLE: {
604 try {
605 mInterface.disableDataConnectivity();
606 } catch (RemoteException ex) {
607 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
608 errPw.println("Exception: " + ex.getMessage());
609 return -1;
610 }
611 break;
612 }
613 default:
614 onHelpDataTestMode();
615 break;
616 }
617 return 0;
618 }
619
sqian9d4df8b2019-01-15 18:32:07 -0800620 private int handleEmergencyNumberTestModeCommand() {
621 PrintWriter errPw = getErrPrintWriter();
622 String opt = getNextOption();
623 if (opt == null) {
624 onHelpEmergencyNumber();
625 return 0;
626 }
627
628 switch (opt) {
629 case "-a": {
630 String emergencyNumberCmd = getNextArgRequired();
631 if (emergencyNumberCmd == null
632 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700633 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800634 + " to be specified after -a in the command ");
635 return -1;
636 }
637 try {
638 mInterface.updateEmergencyNumberListTestMode(
639 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
640 new EmergencyNumber(emergencyNumberCmd, "", "",
641 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
642 new ArrayList<String>(),
643 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
644 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
645 } catch (RemoteException ex) {
646 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
647 + ", error " + ex.getMessage());
648 errPw.println("Exception: " + ex.getMessage());
649 return -1;
650 }
651 break;
652 }
653 case "-c": {
654 try {
655 mInterface.updateEmergencyNumberListTestMode(
656 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
657 } catch (RemoteException ex) {
658 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
659 errPw.println("Exception: " + ex.getMessage());
660 return -1;
661 }
662 break;
663 }
664 case "-r": {
665 String emergencyNumberCmd = getNextArgRequired();
666 if (emergencyNumberCmd == null
667 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700668 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800669 + " to be specified after -r in the command ");
670 return -1;
671 }
672 try {
673 mInterface.updateEmergencyNumberListTestMode(
674 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
675 new EmergencyNumber(emergencyNumberCmd, "", "",
676 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
677 new ArrayList<String>(),
678 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
679 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
680 } catch (RemoteException ex) {
681 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
682 + ", error " + ex.getMessage());
683 errPw.println("Exception: " + ex.getMessage());
684 return -1;
685 }
686 break;
687 }
688 case "-p": {
689 try {
690 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
691 } catch (RemoteException ex) {
692 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
693 errPw.println("Exception: " + ex.getMessage());
694 return -1;
695 }
696 break;
697 }
698 default:
699 onHelpEmergencyNumber();
700 break;
701 }
702 return 0;
703 }
704
Hall Liud892bec2018-11-30 14:51:45 -0800705 private int handleNumberVerificationCommand() {
706 String arg = getNextArg();
707 if (arg == null) {
708 onHelpNumberVerification();
709 return 0;
710 }
711
Hall Liuca5af3a2018-12-04 16:58:23 -0800712 if (!checkShellUid()) {
713 return -1;
714 }
715
Hall Liud892bec2018-11-30 14:51:45 -0800716 switch (arg) {
717 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800718 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
719 return 0;
720 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800721 case NUMBER_VERIFICATION_FAKE_CALL: {
722 boolean val = NumberVerificationManager.getInstance()
723 .checkIncomingCall(getNextArg());
724 getOutPrintWriter().println(val ? "1" : "0");
725 return 0;
726 }
Hall Liud892bec2018-11-30 14:51:45 -0800727 }
728
729 return -1;
730 }
731
Jack Nudelman644b91a2021-03-12 14:09:48 -0800732 private int handleThermalMitigationCommand() {
733 String arg = getNextArg();
734 String packageName = getNextArg();
735 if (arg == null || packageName == null) {
736 onHelpThermalMitigation();
737 return 0;
738 }
739
740 if (!checkShellUid()) {
741 return -1;
742 }
743
744 switch (arg) {
745 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
746 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
747 return 0;
748 }
749 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
750 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
751 mContext);
752 return 0;
753 }
754 default:
755 onHelpThermalMitigation();
756 }
757
758 return -1;
759
760 }
761
Tyler Gunn92479152021-01-20 16:30:10 -0800762 private int handleD2dCommand() {
763 String arg = getNextArg();
764 if (arg == null) {
765 onHelpD2D();
766 return 0;
767 }
768
769 switch (arg) {
770 case D2D_SEND: {
771 return handleD2dSendCommand();
772 }
773 }
774
775 return -1;
776 }
777
778 private int handleD2dSendCommand() {
779 PrintWriter errPw = getErrPrintWriter();
780 String opt;
781 int messageType = -1;
782 int messageValue = -1;
783
784
785 String arg = getNextArg();
786 if (arg == null) {
787 onHelpD2D();
788 return 0;
789 }
790 try {
791 messageType = Integer.parseInt(arg);
792 } catch (NumberFormatException e) {
793 errPw.println("message type must be a valid integer");
794 return -1;
795 }
796
797 arg = getNextArg();
798 if (arg == null) {
799 onHelpD2D();
800 return 0;
801 }
802 try {
803 messageValue = Integer.parseInt(arg);
804 } catch (NumberFormatException e) {
805 errPw.println("message value must be a valid integer");
806 return -1;
807 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -0800808
Tyler Gunn92479152021-01-20 16:30:10 -0800809 try {
810 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
811 } catch (RemoteException e) {
812 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
813 errPw.println("Exception: " + e.getMessage());
814 return -1;
815 }
816
817 return 0;
818 }
819
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700820 // ims set-ims-service
821 private int handleImsSetServiceCommand() {
822 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700823 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700824 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800825 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700826
827 String opt;
828 while ((opt = getNextOption()) != null) {
829 switch (opt) {
830 case "-s": {
831 try {
832 slotId = Integer.parseInt(getNextArgRequired());
833 } catch (NumberFormatException e) {
834 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
835 return -1;
836 }
837 break;
838 }
839 case "-c": {
840 isCarrierService = true;
841 break;
842 }
843 case "-d": {
844 isCarrierService = false;
845 break;
846 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800847 case "-f": {
848 String featureString = getNextArgRequired();
849 String[] features = featureString.split(",");
850 for (int i = 0; i < features.length; i++) {
851 try {
852 Integer result = Integer.parseInt(features[i]);
853 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
854 || result >= ImsFeature.FEATURE_MAX) {
855 errPw.println("ims set-ims-service -f " + result
856 + " is an invalid feature.");
857 return -1;
858 }
859 featuresList.add(result);
860 } catch (NumberFormatException e) {
861 errPw.println("ims set-ims-service -f tried to parse " + features[i]
862 + " as an integer.");
863 return -1;
864 }
865 }
866 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700867 }
868 }
869 // Mandatory param, either -c or -d
870 if (isCarrierService == null) {
871 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
872 return -1;
873 }
874
875 String packageName = getNextArg();
876
877 try {
878 if (packageName == null) {
879 packageName = "";
880 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800881 int[] featureArray = new int[featuresList.size()];
882 for (int i = 0; i < featuresList.size(); i++) {
883 featureArray[i] = featuresList.get(i);
884 }
885 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
886 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700887 if (VDBG) {
888 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800889 + (isCarrierService ? "-c " : "-d ")
890 + "-f " + featuresList + " "
891 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700892 }
893 getOutPrintWriter().println(result);
894 } catch (RemoteException e) {
895 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800896 + (isCarrierService ? "-c " : "-d ")
897 + "-f " + featuresList + " "
898 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700899 errPw.println("Exception: " + e.getMessage());
900 return -1;
901 }
902 return 0;
903 }
904
Brad Ebinger999d3302020-11-25 14:31:39 -0800905 // ims clear-ims-service-override
906 private int handleImsClearCarrierServiceCommand() {
907 PrintWriter errPw = getErrPrintWriter();
908 int slotId = getDefaultSlot();
909
910 String opt;
911 while ((opt = getNextOption()) != null) {
912 switch (opt) {
913 case "-s": {
914 try {
915 slotId = Integer.parseInt(getNextArgRequired());
916 } catch (NumberFormatException e) {
917 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
918 return -1;
919 }
920 break;
921 }
922 }
923 }
924
925 try {
926 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
927 if (VDBG) {
928 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
929 + ", result=" + result);
930 }
931 getOutPrintWriter().println(result);
932 } catch (RemoteException e) {
933 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
934 + ", error" + e.getMessage());
935 errPw.println("Exception: " + e.getMessage());
936 return -1;
937 }
938 return 0;
939 }
940
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700941 // ims get-ims-service
942 private int handleImsGetServiceCommand() {
943 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700944 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700945 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800946 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700947
948 String opt;
949 while ((opt = getNextOption()) != null) {
950 switch (opt) {
951 case "-s": {
952 try {
953 slotId = Integer.parseInt(getNextArgRequired());
954 } catch (NumberFormatException e) {
955 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
956 return -1;
957 }
958 break;
959 }
960 case "-c": {
961 isCarrierService = true;
962 break;
963 }
964 case "-d": {
965 isCarrierService = false;
966 break;
967 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800968 case "-f": {
969 try {
970 featureType = Integer.parseInt(getNextArg());
971 } catch (NumberFormatException e) {
972 errPw.println("ims get-ims-service -f requires valid integer as feature.");
973 return -1;
974 }
975 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
976 || featureType >= ImsFeature.FEATURE_MAX) {
977 errPw.println("ims get-ims-service -f invalid feature.");
978 return -1;
979 }
980 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700981 }
982 }
983 // Mandatory param, either -c or -d
984 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800985 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700986 return -1;
987 }
988
989 String result;
990 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800991 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700992 } catch (RemoteException e) {
993 return -1;
994 }
995 if (VDBG) {
996 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800997 + (isCarrierService ? "-c " : "-d ")
998 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
999 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001000 }
1001 getOutPrintWriter().println(result);
1002 return 0;
1003 }
1004
1005 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001006 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001007 String opt;
1008 while ((opt = getNextOption()) != null) {
1009 switch (opt) {
1010 case "-s": {
1011 try {
1012 slotId = Integer.parseInt(getNextArgRequired());
1013 } catch (NumberFormatException e) {
1014 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1015 return -1;
1016 }
1017 break;
1018 }
1019 }
1020 }
1021 try {
1022 mInterface.enableIms(slotId);
1023 } catch (RemoteException e) {
1024 return -1;
1025 }
1026 if (VDBG) {
1027 Log.v(LOG_TAG, "ims enable -s " + slotId);
1028 }
1029 return 0;
1030 }
1031
1032 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001033 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001034 String opt;
1035 while ((opt = getNextOption()) != null) {
1036 switch (opt) {
1037 case "-s": {
1038 try {
1039 slotId = Integer.parseInt(getNextArgRequired());
1040 } catch (NumberFormatException e) {
1041 getErrPrintWriter().println(
1042 "ims disable requires an integer as a SLOT_ID.");
1043 return -1;
1044 }
1045 break;
1046 }
1047 }
1048 }
1049 try {
1050 mInterface.disableIms(slotId);
1051 } catch (RemoteException e) {
1052 return -1;
1053 }
1054 if (VDBG) {
1055 Log.v(LOG_TAG, "ims disable -s " + slotId);
1056 }
1057 return 0;
1058 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001059
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001060 private int handleCepChange() {
1061 Log.i(LOG_TAG, "handleCepChange");
1062 String opt = getNextArg();
1063 if (opt == null) {
1064 return -1;
1065 }
1066 boolean isCepEnabled = opt.equals("enable");
1067
1068 try {
1069 mInterface.setCepEnabled(isCepEnabled);
1070 } catch (RemoteException e) {
1071 return -1;
1072 }
1073 return 0;
1074 }
1075
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001076 private int getDefaultSlot() {
1077 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1078 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1079 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1080 // If there is no default, default to slot 0.
1081 slotId = DEFAULT_PHONE_ID;
1082 }
1083 return slotId;
1084 }
sqian2fff4a32018-11-05 14:18:37 -08001085
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001086 // Parse options related to Carrier Config Commands.
1087 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001088 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001089 CcOptionParseResult result = new CcOptionParseResult();
1090 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1091 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001092
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001093 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001094 while ((opt = getNextOption()) != null) {
1095 switch (opt) {
1096 case "-s": {
1097 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001098 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1099 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1100 errPw.println(tag + "No valid subscription found.");
1101 return null;
1102 }
1103
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001104 } catch (IllegalArgumentException e) {
1105 // Missing slot id
1106 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001107 return null;
1108 }
1109 break;
1110 }
1111 case "-p": {
1112 if (allowOptionPersistent) {
1113 result.mPersistent = true;
1114 } else {
1115 errPw.println(tag + "Unexpected option " + opt);
1116 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001117 }
1118 break;
1119 }
1120 default: {
1121 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001122 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001123 }
1124 }
1125 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001126 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001127 }
1128
1129 private int slotStringToSubId(String tag, String slotString) {
1130 int slotId = -1;
1131 try {
1132 slotId = Integer.parseInt(slotString);
1133 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001134 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1135 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1136 }
1137
1138 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001139 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1140 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1141 }
1142
Qiong Liuf25799b2020-09-10 10:13:46 +08001143 Phone phone = PhoneFactory.getPhone(slotId);
1144 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001145 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1146 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1147 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001148 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001149 }
1150
Hall Liud892bec2018-11-30 14:51:45 -08001151 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001152 // adb can run as root or as shell, depending on whether the device is rooted.
1153 return Binder.getCallingUid() == Process.SHELL_UID
1154 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001155 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001156
1157 private int handleCcCommand() {
1158 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1159 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001160 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001161 getErrPrintWriter().println("cc: Permission denied.");
1162 return -1;
1163 }
1164
1165 String arg = getNextArg();
1166 if (arg == null) {
1167 onHelpCc();
1168 return 0;
1169 }
1170
1171 switch (arg) {
1172 case CC_GET_VALUE: {
1173 return handleCcGetValue();
1174 }
1175 case CC_SET_VALUE: {
1176 return handleCcSetValue();
1177 }
1178 case CC_CLEAR_VALUES: {
1179 return handleCcClearValues();
1180 }
1181 default: {
1182 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1183 }
1184 }
1185 return -1;
1186 }
1187
1188 // cc get-value
1189 private int handleCcGetValue() {
1190 PrintWriter errPw = getErrPrintWriter();
1191 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1192 String key = null;
1193
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001194 // Parse all options
1195 CcOptionParseResult options = parseCcOptions(tag, false);
1196 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001197 return -1;
1198 }
1199
1200 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001201 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001202 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001203 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001204 return -1;
1205 }
1206
1207 // Get the key.
1208 key = getNextArg();
1209 if (key != null) {
1210 // A key was provided. Verify if it is a valid key
1211 if (!bundle.containsKey(key)) {
1212 errPw.println(tag + key + " is not a valid key.");
1213 return -1;
1214 }
1215
1216 // Print the carrier config value for key.
1217 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1218 } else {
1219 // No key provided. Show all values.
1220 // Iterate over a sorted list of all carrier config keys and print them.
1221 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1222 for (String k : sortedSet) {
1223 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1224 }
1225 }
1226 return 0;
1227 }
1228
1229 // cc set-value
1230 private int handleCcSetValue() {
1231 PrintWriter errPw = getErrPrintWriter();
1232 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1233
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001234 // Parse all options
1235 CcOptionParseResult options = parseCcOptions(tag, true);
1236 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001237 return -1;
1238 }
1239
1240 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001241 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001242 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001243 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001244 return -1;
1245 }
1246
1247 // Get the key.
1248 String key = getNextArg();
1249 if (key == null || key.equals("")) {
1250 errPw.println(tag + "KEY is missing");
1251 return -1;
1252 }
1253
1254 // Verify if the key is valid
1255 if (!originalValues.containsKey(key)) {
1256 errPw.println(tag + key + " is not a valid key.");
1257 return -1;
1258 }
1259
1260 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1261 ArrayList<String> valueList = new ArrayList<String>();
1262 while (peekNextArg() != null) {
1263 valueList.add(getNextArg());
1264 }
1265
1266 // Find the type of the carrier config value
1267 CcType type = getType(tag, key, originalValues);
1268 if (type == CcType.UNKNOWN) {
1269 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1270 return -1;
1271 }
1272
1273 // Create an override bundle containing the key and value that should be overriden.
1274 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1275 if (overrideBundle == null) {
1276 return -1;
1277 }
1278
1279 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001280 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001281
1282 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001283 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001284 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001285 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001286 return -1;
1287 }
1288
1289 // Print the original and new value.
1290 String originalValueString = ccValueToString(key, type, originalValues);
1291 String newValueString = ccValueToString(key, type, newValues);
1292 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1293 getOutPrintWriter().println("New value: \n" + newValueString);
1294
1295 return 0;
1296 }
1297
1298 // cc clear-values
1299 private int handleCcClearValues() {
1300 PrintWriter errPw = getErrPrintWriter();
1301 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1302
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001303 // Parse all options
1304 CcOptionParseResult options = parseCcOptions(tag, false);
1305 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001306 return -1;
1307 }
1308
1309 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001310 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001311 getOutPrintWriter()
1312 .println("All previously set carrier config override values has been cleared");
1313 return 0;
1314 }
1315
1316 private CcType getType(String tag, String key, PersistableBundle bundle) {
1317 // Find the type by checking the type of the current value stored in the bundle.
1318 Object value = bundle.get(key);
1319
1320 if (CC_TYPE_MAP.containsKey(key)) {
1321 return CC_TYPE_MAP.get(key);
1322 } else if (value != null) {
1323 if (value instanceof Boolean) {
1324 return CcType.BOOLEAN;
1325 } else if (value instanceof Double) {
1326 return CcType.DOUBLE;
1327 } else if (value instanceof double[]) {
1328 return CcType.DOUBLE_ARRAY;
1329 } else if (value instanceof Integer) {
1330 return CcType.INT;
1331 } else if (value instanceof int[]) {
1332 return CcType.INT_ARRAY;
1333 } else if (value instanceof Long) {
1334 return CcType.LONG;
1335 } else if (value instanceof long[]) {
1336 return CcType.LONG_ARRAY;
1337 } else if (value instanceof String) {
1338 return CcType.STRING;
1339 } else if (value instanceof String[]) {
1340 return CcType.STRING_ARRAY;
1341 }
1342 } else {
1343 // Current value was null and can therefore not be used in order to find the type.
1344 // Check the name of the key to infer the type. This check is not needed for primitive
1345 // data types (boolean, double, int and long), since they can not be null.
1346 if (key.endsWith("double_array")) {
1347 return CcType.DOUBLE_ARRAY;
1348 }
1349 if (key.endsWith("int_array")) {
1350 return CcType.INT_ARRAY;
1351 }
1352 if (key.endsWith("long_array")) {
1353 return CcType.LONG_ARRAY;
1354 }
1355 if (key.endsWith("string")) {
1356 return CcType.STRING;
1357 }
1358 if (key.endsWith("string_array") || key.endsWith("strings")) {
1359 return CcType.STRING_ARRAY;
1360 }
1361 }
1362
1363 // Not possible to infer the type by looking at the current value or the key.
1364 PrintWriter errPw = getErrPrintWriter();
1365 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1366 return CcType.UNKNOWN;
1367 }
1368
1369 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1370 String result;
1371 StringBuilder valueString = new StringBuilder();
1372 String typeString = type.toString();
1373 Object value = bundle.get(key);
1374
1375 if (value == null) {
1376 valueString.append("null");
1377 } else {
1378 switch (type) {
1379 case DOUBLE_ARRAY: {
1380 // Format the string representation of the int array as value1 value2......
1381 double[] valueArray = (double[]) value;
1382 for (int i = 0; i < valueArray.length; i++) {
1383 if (i != 0) {
1384 valueString.append(" ");
1385 }
1386 valueString.append(valueArray[i]);
1387 }
1388 break;
1389 }
1390 case INT_ARRAY: {
1391 // Format the string representation of the int array as value1 value2......
1392 int[] valueArray = (int[]) value;
1393 for (int i = 0; i < valueArray.length; i++) {
1394 if (i != 0) {
1395 valueString.append(" ");
1396 }
1397 valueString.append(valueArray[i]);
1398 }
1399 break;
1400 }
1401 case LONG_ARRAY: {
1402 // Format the string representation of the int array as value1 value2......
1403 long[] valueArray = (long[]) value;
1404 for (int i = 0; i < valueArray.length; i++) {
1405 if (i != 0) {
1406 valueString.append(" ");
1407 }
1408 valueString.append(valueArray[i]);
1409 }
1410 break;
1411 }
1412 case STRING: {
1413 valueString.append("\"" + value.toString() + "\"");
1414 break;
1415 }
1416 case STRING_ARRAY: {
1417 // Format the string representation of the string array as "value1" "value2"....
1418 String[] valueArray = (String[]) value;
1419 for (int i = 0; i < valueArray.length; i++) {
1420 if (i != 0) {
1421 valueString.append(" ");
1422 }
1423 if (valueArray[i] != null) {
1424 valueString.append("\"" + valueArray[i] + "\"");
1425 } else {
1426 valueString.append("null");
1427 }
1428 }
1429 break;
1430 }
1431 default: {
1432 valueString.append(value.toString());
1433 }
1434 }
1435 }
1436 return String.format("%-70s %-15s %s", key, typeString, valueString);
1437 }
1438
1439 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1440 ArrayList<String> valueList) {
1441 PrintWriter errPw = getErrPrintWriter();
1442 PersistableBundle bundle = new PersistableBundle();
1443
1444 // First verify that a valid number of values has been provided for the type.
1445 switch (type) {
1446 case BOOLEAN:
1447 case DOUBLE:
1448 case INT:
1449 case LONG: {
1450 if (valueList.size() != 1) {
1451 errPw.println(tag + "Expected 1 value for type " + type
1452 + ". Found: " + valueList.size());
1453 return null;
1454 }
1455 break;
1456 }
1457 case STRING: {
1458 if (valueList.size() > 1) {
1459 errPw.println(tag + "Expected 0 or 1 values for type " + type
1460 + ". Found: " + valueList.size());
1461 return null;
1462 }
1463 break;
1464 }
1465 }
1466
1467 // Parse the value according to type and add it to the Bundle.
1468 switch (type) {
1469 case BOOLEAN: {
1470 if ("true".equalsIgnoreCase(valueList.get(0))) {
1471 bundle.putBoolean(key, true);
1472 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1473 bundle.putBoolean(key, false);
1474 } else {
1475 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1476 return null;
1477 }
1478 break;
1479 }
1480 case DOUBLE: {
1481 try {
1482 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1483 } catch (NumberFormatException nfe) {
1484 // Not a valid double
1485 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1486 return null;
1487 }
1488 break;
1489 }
1490 case DOUBLE_ARRAY: {
1491 double[] valueDoubleArray = null;
1492 if (valueList.size() > 0) {
1493 valueDoubleArray = new double[valueList.size()];
1494 for (int i = 0; i < valueList.size(); i++) {
1495 try {
1496 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1497 } catch (NumberFormatException nfe) {
1498 // Not a valid double
1499 errPw.println(
1500 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1501 return null;
1502 }
1503 }
1504 }
1505 bundle.putDoubleArray(key, valueDoubleArray);
1506 break;
1507 }
1508 case INT: {
1509 try {
1510 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1511 } catch (NumberFormatException nfe) {
1512 // Not a valid integer
1513 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1514 return null;
1515 }
1516 break;
1517 }
1518 case INT_ARRAY: {
1519 int[] valueIntArray = null;
1520 if (valueList.size() > 0) {
1521 valueIntArray = new int[valueList.size()];
1522 for (int i = 0; i < valueList.size(); i++) {
1523 try {
1524 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1525 } catch (NumberFormatException nfe) {
1526 // Not a valid integer
1527 errPw.println(tag
1528 + "Unable to parse " + valueList.get(i) + " as an integer.");
1529 return null;
1530 }
1531 }
1532 }
1533 bundle.putIntArray(key, valueIntArray);
1534 break;
1535 }
1536 case LONG: {
1537 try {
1538 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1539 } catch (NumberFormatException nfe) {
1540 // Not a valid long
1541 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1542 return null;
1543 }
1544 break;
1545 }
1546 case LONG_ARRAY: {
1547 long[] valueLongArray = null;
1548 if (valueList.size() > 0) {
1549 valueLongArray = new long[valueList.size()];
1550 for (int i = 0; i < valueList.size(); i++) {
1551 try {
1552 valueLongArray[i] = Long.parseLong(valueList.get(i));
1553 } catch (NumberFormatException nfe) {
1554 // Not a valid long
1555 errPw.println(
1556 tag + "Unable to parse " + valueList.get(i) + " as a long");
1557 return null;
1558 }
1559 }
1560 }
1561 bundle.putLongArray(key, valueLongArray);
1562 break;
1563 }
1564 case STRING: {
1565 String value = null;
1566 if (valueList.size() > 0) {
1567 value = valueList.get(0);
1568 }
1569 bundle.putString(key, value);
1570 break;
1571 }
1572 case STRING_ARRAY: {
1573 String[] valueStringArray = null;
1574 if (valueList.size() > 0) {
1575 valueStringArray = new String[valueList.size()];
1576 valueList.toArray(valueStringArray);
1577 }
1578 bundle.putStringArray(key, valueStringArray);
1579 break;
1580 }
1581 }
1582 return bundle;
1583 }
Shuo Qian489d9282020-07-09 11:30:03 -07001584
1585 private int handleEndBlockSuppressionCommand() {
1586 if (!checkShellUid()) {
1587 return -1;
1588 }
1589
1590 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1591 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1592 }
1593 return 0;
1594 }
Hui Wang0866fcc2020-10-12 12:14:23 -07001595
Michele Berionne38c1afa2020-12-28 20:23:16 +00001596 private int handleRestartModemCommand() {
1597 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1598 // non user build.
1599 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1600 getErrPrintWriter().println("RestartModem: Permission denied.");
1601 return -1;
1602 }
1603
1604 boolean result = TelephonyManager.getDefault().rebootRadio();
1605 getOutPrintWriter().println(result);
1606
1607 return result ? 0 : -1;
1608 }
1609
Michele Berionned9fbae52020-11-13 02:36:59 +00001610 private int handleUnattendedReboot() {
1611 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1612 // non user build.
1613 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1614 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1615 return -1;
1616 }
1617
1618 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1619 getOutPrintWriter().println("result: " + result);
1620
1621 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1622 }
1623
Hui Wang0866fcc2020-10-12 12:14:23 -07001624 private int handleGbaCommand() {
1625 String arg = getNextArg();
1626 if (arg == null) {
1627 onHelpGba();
1628 return 0;
1629 }
1630
1631 switch (arg) {
1632 case GBA_SET_SERVICE: {
1633 return handleGbaSetServiceCommand();
1634 }
1635 case GBA_GET_SERVICE: {
1636 return handleGbaGetServiceCommand();
1637 }
1638 case GBA_SET_RELEASE_TIME: {
1639 return handleGbaSetReleaseCommand();
1640 }
1641 case GBA_GET_RELEASE_TIME: {
1642 return handleGbaGetReleaseCommand();
1643 }
1644 }
1645
1646 return -1;
1647 }
1648
1649 private int getSubId(String cmd) {
1650 int slotId = getDefaultSlot();
1651 String opt = getNextOption();
1652 if (opt != null && opt.equals("-s")) {
1653 try {
1654 slotId = Integer.parseInt(getNextArgRequired());
1655 } catch (NumberFormatException e) {
1656 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1657 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1658 }
1659 }
1660 int[] subIds = SubscriptionManager.getSubId(slotId);
1661 return subIds[0];
1662 }
1663
1664 private int handleGbaSetServiceCommand() {
1665 int subId = getSubId("gba set-service");
1666 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1667 return -1;
1668 }
1669
1670 String packageName = getNextArg();
1671 try {
1672 if (packageName == null) {
1673 packageName = "";
1674 }
1675 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1676 if (VDBG) {
1677 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1678 + packageName + ", result=" + result);
1679 }
1680 getOutPrintWriter().println(result);
1681 } catch (RemoteException e) {
1682 Log.w(LOG_TAG, "gba set-service " + subId + " "
1683 + packageName + ", error" + e.getMessage());
1684 getErrPrintWriter().println("Exception: " + e.getMessage());
1685 return -1;
1686 }
1687 return 0;
1688 }
1689
1690 private int handleGbaGetServiceCommand() {
1691 String result;
1692
1693 int subId = getSubId("gba get-service");
1694 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1695 return -1;
1696 }
1697
1698 try {
1699 result = mInterface.getBoundGbaService(subId);
1700 } catch (RemoteException e) {
1701 return -1;
1702 }
1703 if (VDBG) {
1704 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1705 }
1706 getOutPrintWriter().println(result);
1707 return 0;
1708 }
1709
1710 private int handleGbaSetReleaseCommand() {
1711 //the release time value could be -1
1712 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1713 : SubscriptionManager.getDefaultSubscriptionId();
1714 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1715 return -1;
1716 }
1717
1718 String intervalStr = getNextArg();
1719 if (intervalStr == null) {
1720 return -1;
1721 }
1722
1723 try {
1724 int interval = Integer.parseInt(intervalStr);
1725 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1726 if (VDBG) {
1727 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1728 + intervalStr + ", result=" + result);
1729 }
1730 getOutPrintWriter().println(result);
1731 } catch (NumberFormatException | RemoteException e) {
1732 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1733 + intervalStr + ", error" + e.getMessage());
1734 getErrPrintWriter().println("Exception: " + e.getMessage());
1735 return -1;
1736 }
1737 return 0;
1738 }
1739
1740 private int handleGbaGetReleaseCommand() {
1741 int subId = getSubId("gba get-release");
1742 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1743 return -1;
1744 }
1745
1746 int result = 0;
1747 try {
1748 result = mInterface.getGbaReleaseTime(subId);
1749 } catch (RemoteException e) {
1750 return -1;
1751 }
1752 if (VDBG) {
1753 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1754 }
1755 getOutPrintWriter().println(result);
1756 return 0;
1757 }
Hui Wang068ab862020-10-31 05:12:53 +00001758
1759 private int handleSingleRegistrationConfigCommand() {
1760 String arg = getNextArg();
1761 if (arg == null) {
1762 onHelpSrc();
1763 return 0;
1764 }
1765
1766 switch (arg) {
Hui Wang19a21872021-02-19 20:45:36 -08001767 case SRC_SET_TEST_ENABLED: {
1768 return handleSrcSetTestEnabledCommand();
1769 }
1770 case SRC_GET_TEST_ENABLED: {
1771 return handleSrcGetTestEnabledCommand();
1772 }
Hui Wang068ab862020-10-31 05:12:53 +00001773 case SRC_SET_DEVICE_ENABLED: {
1774 return handleSrcSetDeviceEnabledCommand();
1775 }
1776 case SRC_GET_DEVICE_ENABLED: {
1777 return handleSrcGetDeviceEnabledCommand();
1778 }
1779 case SRC_SET_CARRIER_ENABLED: {
1780 return handleSrcSetCarrierEnabledCommand();
1781 }
1782 case SRC_GET_CARRIER_ENABLED: {
1783 return handleSrcGetCarrierEnabledCommand();
1784 }
Hui Wangeadb2562021-02-26 09:33:38 -08001785 case SRC_SET_FEATURE_ENABLED: {
1786 return handleSrcSetFeatureValidationCommand();
1787 }
1788 case SRC_GET_FEATURE_ENABLED: {
1789 return handleSrcGetFeatureValidationCommand();
1790 }
Hui Wang068ab862020-10-31 05:12:53 +00001791 }
1792
1793 return -1;
1794 }
1795
James.cf Linbcdf8b32021-01-14 16:44:13 +08001796 private int handleRcsUceCommand() {
1797 String arg = getNextArg();
1798 if (arg == null) {
Brad Ebingerd4c5bde2021-02-12 06:18:28 +00001799 onHelpUce();
1800 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001801 }
1802
1803 switch (arg) {
1804 case UCE_REMOVE_EAB_CONTACT:
1805 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001806 case UCE_GET_EAB_CONTACT:
1807 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001808 case UCE_GET_DEVICE_ENABLED:
1809 return handleUceGetDeviceEnabledCommand();
1810 case UCE_SET_DEVICE_ENABLED:
1811 return handleUceSetDeviceEnabledCommand();
Brad Ebingerd4c5bde2021-02-12 06:18:28 +00001812 case UCE_OVERRIDE_PUBLISH_CAPS:
1813 return handleUceOverridePublishCaps();
1814 case UCE_GET_LAST_PIDF_XML:
1815 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08001816 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
1817 return handleUceRemoveRequestDisallowedStatus();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001818 }
1819 return -1;
1820 }
1821
1822 private int handleRemovingEabContactCommand() {
1823 int subId = getSubId("uce remove-eab-contact");
1824 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1825 return -1;
1826 }
1827
1828 String phoneNumber = getNextArgRequired();
1829 if (TextUtils.isEmpty(phoneNumber)) {
1830 return -1;
1831 }
1832 int result = 0;
1833 try {
1834 result = mInterface.removeContactFromEab(subId, phoneNumber);
1835 } catch (RemoteException e) {
1836 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1837 getErrPrintWriter().println("Exception: " + e.getMessage());
1838 return -1;
1839 }
1840
1841 if (VDBG) {
1842 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1843 }
calvinpan293ea1b2021-02-04 17:52:13 +08001844 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001845 }
1846
calvinpane4a8a1d2021-01-25 13:51:18 +08001847 private int handleGettingEabContactCommand() {
1848 String phoneNumber = getNextArgRequired();
1849 if (TextUtils.isEmpty(phoneNumber)) {
1850 return -1;
1851 }
1852 String result = "";
1853 try {
1854 result = mInterface.getContactFromEab(phoneNumber);
1855
1856 } catch (RemoteException e) {
1857 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1858 getErrPrintWriter().println("Exception: " + e.getMessage());
1859 return -1;
1860 }
1861
1862 if (VDBG) {
1863 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1864 }
calvinpan293ea1b2021-02-04 17:52:13 +08001865 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001866 return 0;
1867 }
1868
1869 private int handleUceGetDeviceEnabledCommand() {
1870 boolean result = false;
1871 try {
1872 result = mInterface.getDeviceUceEnabled();
1873 } catch (RemoteException e) {
1874 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1875 return -1;
1876 }
1877 if (VDBG) {
1878 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1879 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001880 getOutPrintWriter().println(result);
1881 return 0;
1882 }
1883
James.cf Lin4b784aa2021-01-31 03:25:15 +08001884 private int handleUceSetDeviceEnabledCommand() {
1885 String enabledStr = getNextArg();
1886 if (TextUtils.isEmpty(enabledStr)) {
1887 return -1;
1888 }
1889
1890 try {
1891 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1892 mInterface.setDeviceUceEnabled(isEnabled);
1893 if (VDBG) {
1894 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1895 }
1896 } catch (NumberFormatException | RemoteException e) {
1897 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1898 getErrPrintWriter().println("Exception: " + e.getMessage());
1899 return -1;
1900 }
1901 return 0;
1902 }
1903
James.cf Line8713a42021-04-29 16:04:26 +08001904 private int handleUceRemoveRequestDisallowedStatus() {
1905 int subId = getSubId("uce remove-request-disallowed-status");
1906 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1907 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
1908 return -1;
1909 }
1910 boolean result;
1911 try {
1912 result = mInterface.removeUceRequestDisallowedStatus(subId);
1913 } catch (RemoteException e) {
1914 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
1915 return -1;
1916 }
1917 if (VDBG) {
1918 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
1919 }
1920 getOutPrintWriter().println(result);
1921 return 0;
1922 }
1923
Hui Wang19a21872021-02-19 20:45:36 -08001924 private int handleSrcSetTestEnabledCommand() {
1925 String enabledStr = getNextArg();
1926 if (enabledStr == null) {
1927 return -1;
1928 }
1929
1930 try {
1931 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1932 if (VDBG) {
1933 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1934 }
1935 getOutPrintWriter().println("Done");
1936 } catch (NumberFormatException | RemoteException e) {
1937 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1938 getErrPrintWriter().println("Exception: " + e.getMessage());
1939 return -1;
1940 }
1941 return 0;
1942 }
1943
1944 private int handleSrcGetTestEnabledCommand() {
1945 boolean result = false;
1946 try {
1947 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1948 } catch (RemoteException e) {
1949 return -1;
1950 }
1951 if (VDBG) {
1952 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1953 }
1954 getOutPrintWriter().println(result);
1955 return 0;
1956 }
1957
Brad Ebingerd4c5bde2021-02-12 06:18:28 +00001958 private int handleUceOverridePublishCaps() {
1959 int subId = getSubId("uce override-published-caps");
1960 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1961 return -1;
1962 }
1963 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
1964 String operation = getNextArgRequired();
1965 String caps = getNextArg();
1966 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
1967 && !"list".equals(operation)) {
1968 getErrPrintWriter().println("Invalid operation: " + operation);
1969 return -1;
1970 }
1971
1972 // add/remove requires capabilities to be specified.
1973 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
1974 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
1975 + "specified");
1976 return -1;
1977 }
1978
1979 ArraySet<String> capSet = new ArraySet<>();
1980 if (!TextUtils.isEmpty(caps)) {
1981 String[] capArray = caps.split(":");
1982 for (String cap : capArray) {
1983 // Allow unknown tags to be passed in as well.
1984 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
1985 }
1986 }
1987
1988 RcsContactUceCapability result = null;
1989 try {
1990 switch (operation) {
1991 case "add":
1992 result = mInterface.addUceRegistrationOverrideShell(subId,
1993 new ArrayList<>(capSet));
1994 break;
1995 case "remove":
1996 result = mInterface.removeUceRegistrationOverrideShell(subId,
1997 new ArrayList<>(capSet));
1998 break;
1999 case "clear":
2000 result = mInterface.clearUceRegistrationOverrideShell(subId);
2001 break;
2002 case "list":
2003 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2004 break;
2005 }
2006 } catch (RemoteException e) {
2007 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2008 getErrPrintWriter().println("Exception: " + e.getMessage());
2009 return -1;
2010 } catch (ServiceSpecificException sse) {
2011 // Reconstruct ImsException
2012 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2013 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2014 getErrPrintWriter().println("Exception: " + imsException);
2015 return -1;
2016 }
2017 if (result == null) {
2018 getErrPrintWriter().println("Service not available");
2019 return -1;
2020 }
2021 getOutPrintWriter().println(result);
2022 return 0;
2023 }
2024
2025 private int handleUceGetPidfXml() {
2026 int subId = getSubId("uce get-last-publish-pidf");
2027 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2028 return -1;
2029 }
2030
2031 String result;
2032 try {
2033 result = mInterface.getLastUcePidfXmlShell(subId);
2034 } catch (RemoteException e) {
2035 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2036 getErrPrintWriter().println("Exception: " + e.getMessage());
2037 return -1;
2038 } catch (ServiceSpecificException sse) {
2039 // Reconstruct ImsException
2040 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2041 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2042 getErrPrintWriter().println("Exception: " + imsException);
2043 return -1;
2044 }
2045 if (result == null) {
2046 getErrPrintWriter().println("Service not available");
2047 return -1;
2048 }
2049 getOutPrintWriter().println(result);
2050 return 0;
2051 }
2052
Hui Wang068ab862020-10-31 05:12:53 +00002053 private int handleSrcSetDeviceEnabledCommand() {
2054 String enabledStr = getNextArg();
2055 if (enabledStr == null) {
2056 return -1;
2057 }
2058
2059 try {
2060 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2061 if (VDBG) {
2062 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2063 }
2064 getOutPrintWriter().println("Done");
2065 } catch (NumberFormatException | RemoteException e) {
2066 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2067 getErrPrintWriter().println("Exception: " + e.getMessage());
2068 return -1;
2069 }
2070 return 0;
2071 }
2072
2073 private int handleSrcGetDeviceEnabledCommand() {
2074 boolean result = false;
2075 try {
2076 result = mInterface.getDeviceSingleRegistrationEnabled();
2077 } catch (RemoteException e) {
2078 return -1;
2079 }
2080 if (VDBG) {
2081 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2082 }
2083 getOutPrintWriter().println(result);
2084 return 0;
2085 }
2086
2087 private int handleSrcSetCarrierEnabledCommand() {
2088 //the release time value could be -1
2089 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2090 : SubscriptionManager.getDefaultSubscriptionId();
2091 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2092 return -1;
2093 }
2094
2095 String enabledStr = getNextArg();
2096 if (enabledStr == null) {
2097 return -1;
2098 }
2099
2100 try {
2101 boolean result =
2102 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2103 if (VDBG) {
2104 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2105 + enabledStr + ", result=" + result);
2106 }
2107 getOutPrintWriter().println(result);
2108 } catch (NumberFormatException | RemoteException e) {
2109 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2110 + enabledStr + ", error" + e.getMessage());
2111 getErrPrintWriter().println("Exception: " + e.getMessage());
2112 return -1;
2113 }
2114 return 0;
2115 }
2116
2117 private int handleSrcGetCarrierEnabledCommand() {
2118 int subId = getSubId("src get-carrier-enabled");
2119 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2120 return -1;
2121 }
2122
2123 boolean result = false;
2124 try {
2125 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2126 } catch (RemoteException e) {
2127 return -1;
2128 }
2129 if (VDBG) {
2130 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2131 }
2132 getOutPrintWriter().println(result);
2133 return 0;
2134 }
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -08002135
Hui Wangeadb2562021-02-26 09:33:38 -08002136 private int handleSrcSetFeatureValidationCommand() {
2137 //the release time value could be -1
2138 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2139 : SubscriptionManager.getDefaultSubscriptionId();
2140 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2141 return -1;
2142 }
2143
2144 String enabledStr = getNextArg();
2145 if (enabledStr == null) {
2146 return -1;
2147 }
2148
2149 try {
2150 boolean result =
2151 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2152 if (VDBG) {
2153 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2154 + enabledStr + ", result=" + result);
2155 }
2156 getOutPrintWriter().println(result);
2157 } catch (NumberFormatException | RemoteException e) {
2158 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2159 + enabledStr + ", error" + e.getMessage());
2160 getErrPrintWriter().println("Exception: " + e.getMessage());
2161 return -1;
2162 }
2163 return 0;
2164 }
2165
2166 private int handleSrcGetFeatureValidationCommand() {
2167 int subId = getSubId("src get-feature-validation");
2168 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2169 return -1;
2170 }
2171
2172 Boolean result = false;
2173 try {
2174 result = mInterface.getImsFeatureValidationOverride(subId);
2175 } catch (RemoteException e) {
2176 return -1;
2177 }
2178 if (VDBG) {
2179 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2180 }
2181 getOutPrintWriter().println(result);
2182 return 0;
2183 }
2184
Hunter Knepshield18d0a6b2021-03-02 13:07:53 -08002185 private int handleHasCarrierPrivilegesCommand() {
2186 String packageName = getNextArgRequired();
2187
2188 boolean hasCarrierPrivileges;
2189 try {
2190 hasCarrierPrivileges =
2191 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2192 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2193 } catch (RemoteException e) {
2194 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2195 getErrPrintWriter().println("Exception: " + e.getMessage());
2196 return -1;
2197 }
2198
2199 getOutPrintWriter().println(hasCarrierPrivileges);
2200 return 0;
2201 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002202}