blob: 9e9b6659673e4fff6629ab4f8965201e5bbebe7f [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 Gunnd4575212021-05-03 14:46:49 -0700133 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800134
James.cf Linbcdf8b32021-01-14 16:44:13 +0800135 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800136 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800137 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800138 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
139 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000140 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
141 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800142
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800143 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
144 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
145
Jordan Liu0ccee222021-04-27 11:55:13 -0700146 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
147 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
148
Jack Nudelman644b91a2021-03-12 14:09:48 -0800149 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
150 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
151 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
152
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700153 // Take advantage of existing methods that already contain permissions checks when possible.
154 private final ITelephony mInterface;
155
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100156 private SubscriptionManager mSubscriptionManager;
157 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700158 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100159
160 private enum CcType {
161 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
162 STRING_ARRAY, UNKNOWN
163 }
164
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100165 private class CcOptionParseResult {
166 public int mSubId;
167 public boolean mPersistent;
168 }
169
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100170 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
171 // keys by looking at the end of the string which usually tells the type.
172 // For instance: "xxxx_string", "xxxx_string_array", etc.
173 // The carrier config keys in this map does not follow this convention. It is therefore not
174 // possible to infer the type for these keys by looking at the string.
175 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
176 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
177 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
178 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
179 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
180 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
181 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
182 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
183 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
184 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
185 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
186 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
187 CcType.STRING);
188 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
189 CcType.STRING_ARRAY);
190 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
191 CcType.STRING_ARRAY);
192 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
193 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
194 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
195 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
196 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
197 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
198 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
199 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
200 }
201 };
202
Brad Ebinger14d467f2021-02-12 06:18:28 +0000203 /**
204 * Map from a shorthand string to the feature tags required in registration required in order
205 * for the RCS feature to be considered "capable".
206 */
207 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
208 static {
209 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
210 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
211 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
212 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
213 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
214 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
215 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
216 FeatureTags.FEATURE_TAG_VIDEO)));
217 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
218 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
219 map.put("call_comp",
220 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
221 map.put("call_comp_mmtel",
222 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
223 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
224 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
225 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
226 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
227 // version
228 map.put("chatbot", new ArraySet<>(Arrays.asList(
229 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
230 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
231 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
232 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
233 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
234 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
235 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
236 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
237 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
238 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
239 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
240 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
241 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
242 }
243
244
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100245 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700246 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100247 mCarrierConfigManager =
248 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
249 mSubscriptionManager = (SubscriptionManager)
250 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700251 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700252 }
253
254 @Override
255 public int onCommand(String cmd) {
256 if (cmd == null) {
257 return handleDefaultCommands(null);
258 }
259
260 switch (cmd) {
261 case IMS_SUBCOMMAND: {
262 return handleImsCommand();
263 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800264 case RCS_UCE_COMMAND:
265 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800266 case NUMBER_VERIFICATION_SUBCOMMAND:
267 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800268 case EMERGENCY_CALLBACK_MODE:
269 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800270 case EMERGENCY_NUMBER_TEST_MODE:
271 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100272 case CARRIER_CONFIG_SUBCOMMAND: {
273 return handleCcCommand();
274 }
Shuo Qianf5125122019-12-16 17:03:07 -0800275 case DATA_TEST_MODE:
276 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700277 case END_BLOCK_SUPPRESSION:
278 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700279 case GBA_SUBCOMMAND:
280 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800281 case D2D_SUBCOMMAND:
282 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000283 case SINGLE_REGISTATION_CONFIG:
284 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000285 case RESTART_MODEM:
286 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800287 case CALL_COMPOSER_SUBCOMMAND:
288 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000289 case UNATTENDED_REBOOT:
290 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800291 case HAS_CARRIER_PRIVILEGES_COMMAND:
292 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800293 case THERMAL_MITIGATION_COMMAND:
294 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700295 case DISABLE_PHYSICAL_SUBSCRIPTION:
296 return handleEnablePhysicalSubscription(false);
297 case ENABLE_PHYSICAL_SUBSCRIPTION:
298 return handleEnablePhysicalSubscription(true);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700299 default: {
300 return handleDefaultCommands(cmd);
301 }
302 }
303 }
304
305 @Override
306 public void onHelp() {
307 PrintWriter pw = getOutPrintWriter();
308 pw.println("Telephony Commands:");
309 pw.println(" help");
310 pw.println(" Print this help text.");
311 pw.println(" ims");
312 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800313 pw.println(" uce");
314 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800315 pw.println(" emergency-number-test-mode");
316 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700317 pw.println(" end-block-suppression");
318 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800319 pw.println(" data");
320 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100321 pw.println(" cc");
322 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700323 pw.println(" gba");
324 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000325 pw.println(" src");
326 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000327 pw.println(" restart-modem");
328 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000329 pw.println(" unattended-reboot");
330 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800331 pw.println(" has-carrier-privileges [package]");
332 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700333 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800334 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800335 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700336 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800337 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100338 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700339 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000340 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800341 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700342 onHelpDisableOrEnablePhysicalSubscription();
Tyler Gunn92479152021-01-20 16:30:10 -0800343 }
344
345 private void onHelpD2D() {
346 PrintWriter pw = getOutPrintWriter();
347 pw.println("D2D Comms Commands:");
348 pw.println(" d2d send TYPE VALUE");
349 pw.println(" Sends a D2D message of specified type and value.");
350 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
351 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
352 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
353 MESSAGE_CALL_AUDIO_CODEC));
354 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
355 + Communicator.messageToString(
356 MESSAGE_DEVICE_BATTERY_STATE));
357 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
358 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800359 pw.println(" d2d transport TYPE");
360 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
361 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700362 pw.println(" d2d set-device-support true/default");
363 pw.println(" true - forces device support to be enabled for D2D.");
364 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
365 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700366 }
367
368 private void onHelpIms() {
369 PrintWriter pw = getOutPrintWriter();
370 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800371 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700372 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
373 pw.println(" ImsService. Options are:");
374 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
375 pw.println(" is specified, it will choose the default voice SIM slot.");
376 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
377 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800378 pw.println(" -f: Set the feature that this override if for, if no option is");
379 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700380 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
381 pw.println(" Gets the package name of the currently defined ImsService.");
382 pw.println(" Options are:");
383 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
384 pw.println(" is specified, it will choose the default voice SIM slot.");
385 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000386 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800387 pw.println(" -f: The feature type that the query will be requested for. If none is");
388 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800389 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
390 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
391 pw.println(" configuration overrides. Options are:");
392 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
393 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700394 pw.println(" ims enable [-s SLOT_ID]");
395 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
396 pw.println(" if none is specified.");
397 pw.println(" ims disable [-s SLOT_ID]");
398 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
399 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700400 pw.println(" ims conference-event-package [enable/disable]");
401 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700402 }
403
James.cf Linbcdf8b32021-01-14 16:44:13 +0800404 private void onHelpUce() {
405 PrintWriter pw = getOutPrintWriter();
406 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800407 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
408 pw.println(" Get the EAB contacts from the EAB database.");
409 pw.println(" Options are:");
410 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
411 pw.println(" Expected output format :");
412 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800413 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
414 pw.println(" Remove the EAB contacts from the EAB database.");
415 pw.println(" Options are:");
416 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
417 pw.println(" is specified, it will choose the default voice SIM slot.");
418 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800419 pw.println(" uce get-device-enabled");
420 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
421 pw.println(" uce set-device-enabled true|false");
422 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
423 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000424 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
425 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
426 pw.println(" Options are:");
427 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
428 pw.println(" is specified, it will choose the default voice SIM slot.");
429 pw.println(" add [CAPABILITY]: add a new capability");
430 pw.println(" remove [CAPABILITY]: remove a capability");
431 pw.println(" clear: clear all capability overrides");
432 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
433 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
434 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
435 pw.println(" chatbot_sa, chatbot_role] as well as full length");
436 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
437 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
438 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
439 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800440 }
441
Hall Liud892bec2018-11-30 14:51:45 -0800442 private void onHelpNumberVerification() {
443 PrintWriter pw = getOutPrintWriter();
444 pw.println("Number verification commands");
445 pw.println(" numverify override-package PACKAGE_NAME;");
446 pw.println(" Set the authorized package for number verification.");
447 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800448 pw.println(" numverify fake-call NUMBER;");
449 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
450 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800451 }
452
Jack Nudelman644b91a2021-03-12 14:09:48 -0800453 private void onHelpThermalMitigation() {
454 PrintWriter pw = getOutPrintWriter();
455 pw.println("Thermal mitigation commands");
456 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
457 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
458 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
459 pw.println(" Remove the package from one of the authorized packages for thermal "
460 + "mitigation.");
461 }
462
Jordan Liu0ccee222021-04-27 11:55:13 -0700463 private void onHelpDisableOrEnablePhysicalSubscription() {
464 PrintWriter pw = getOutPrintWriter();
465 pw.println("Disable or enable a physical subscription");
466 pw.println(" disable-physical-subscription SUB_ID");
467 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
468 pw.println(" enable-physical-subscription SUB_ID");
469 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
470 }
471
Shuo Qianf5125122019-12-16 17:03:07 -0800472 private void onHelpDataTestMode() {
473 PrintWriter pw = getOutPrintWriter();
474 pw.println("Mobile Data Test Mode Commands:");
475 pw.println(" data enable: enable mobile data connectivity");
476 pw.println(" data disable: disable mobile data connectivity");
477 }
478
sqian9d4df8b2019-01-15 18:32:07 -0800479 private void onHelpEmergencyNumber() {
480 PrintWriter pw = getOutPrintWriter();
481 pw.println("Emergency Number Test Mode Commands:");
482 pw.println(" emergency-number-test-mode ");
483 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
484 + " the test mode");
485 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700486 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800487 pw.println(" -c: clear the emergency number list in the test mode.");
488 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700489 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800490 pw.println(" -p: get the full emergency number list in the test mode.");
491 }
492
Shuo Qian489d9282020-07-09 11:30:03 -0700493 private void onHelpEndBlockSupperssion() {
494 PrintWriter pw = getOutPrintWriter();
495 pw.println("End Block Suppression command:");
496 pw.println(" end-block-suppression: disable suppressing blocking by contact");
497 pw.println(" with emergency services.");
498 }
499
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100500 private void onHelpCc() {
501 PrintWriter pw = getOutPrintWriter();
502 pw.println("Carrier Config Commands:");
503 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
504 pw.println(" Print carrier config values.");
505 pw.println(" Options are:");
506 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
507 pw.println(" is specified, it will choose the default voice SIM slot.");
508 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
509 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100510 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100511 pw.println(" Set carrier config KEY to NEW_VALUE.");
512 pw.println(" Options are:");
513 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
514 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100515 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100516 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
517 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
518 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
519 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
520 pw.println(" cc clear-values [-s SLOT_ID]");
521 pw.println(" Clear all carrier override values that has previously been set");
522 pw.println(" with set-value");
523 pw.println(" Options are:");
524 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
525 pw.println(" is specified, it will choose the default voice SIM slot.");
526 }
527
Hui Wang641e81c2020-10-12 12:14:23 -0700528 private void onHelpGba() {
529 PrintWriter pw = getOutPrintWriter();
530 pw.println("Gba Commands:");
531 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
532 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
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 get-service [-s SLOT_ID]");
537 pw.println(" Gets the package name of the currently defined GbaService.");
538 pw.println(" Options are:");
539 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
540 pw.println(" is specified, it will choose the default voice SIM slot.");
541 pw.println(" gba set-release [-s SLOT_ID] n");
542 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
543 pw.println(" Do not release/unbind if n is -1.");
544 pw.println(" Options are:");
545 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
546 pw.println(" is specified, it will choose the default voice SIM slot.");
547 pw.println(" gba get-release [-s SLOT_ID]");
548 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
549 pw.println(" Options are:");
550 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
551 pw.println(" is specified, it will choose the default voice SIM slot.");
552 }
553
Hui Wang761a6682020-10-31 05:12:53 +0000554 private void onHelpSrc() {
555 PrintWriter pw = getOutPrintWriter();
556 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800557 pw.println(" src set-test-enabled true|false");
558 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
559 pw.println(" The value could be true, false, or null(undefined).");
560 pw.println(" src get-test-enabled");
561 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000562 pw.println(" src set-device-enabled true|false|null");
563 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
564 pw.println(" The value could be true, false, or null(undefined).");
565 pw.println(" src get-device-enabled");
566 pw.println(" Gets the device config for RCS VoLTE single registration.");
567 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
568 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
569 pw.println(" The value could be true, false, or null(undefined).");
570 pw.println(" Options are:");
571 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
572 pw.println(" is specified, it will choose the default voice SIM slot.");
573 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
574 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
575 pw.println(" Options are:");
576 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
577 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800578 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
579 pw.println(" Sets ims feature validation result.");
580 pw.println(" The value could be true, false, or null(undefined).");
581 pw.println(" Options are:");
582 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
583 pw.println(" is specified, it will choose the default voice SIM slot.");
584 pw.println(" src get-feature-validation [-s SLOT_ID]");
585 pw.println(" Gets ims feature validation override value.");
586 pw.println(" Options are:");
587 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
588 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000589 }
590
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700591 private int handleImsCommand() {
592 String arg = getNextArg();
593 if (arg == null) {
594 onHelpIms();
595 return 0;
596 }
597
598 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800599 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700600 return handleImsSetServiceCommand();
601 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800602 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700603 return handleImsGetServiceCommand();
604 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800605 case IMS_CLEAR_SERVICE_OVERRIDE: {
606 return handleImsClearCarrierServiceCommand();
607 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800608 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700609 return handleEnableIms();
610 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800611 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700612 return handleDisableIms();
613 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700614 case IMS_CEP: {
615 return handleCepChange();
616 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700617 }
618
619 return -1;
620 }
621
Shuo Qianf5125122019-12-16 17:03:07 -0800622 private int handleDataTestModeCommand() {
623 PrintWriter errPw = getErrPrintWriter();
624 String arg = getNextArgRequired();
625 if (arg == null) {
626 onHelpDataTestMode();
627 return 0;
628 }
629 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800630 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800631 try {
632 mInterface.enableDataConnectivity();
633 } catch (RemoteException ex) {
634 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
635 errPw.println("Exception: " + ex.getMessage());
636 return -1;
637 }
638 break;
639 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800640 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800641 try {
642 mInterface.disableDataConnectivity();
643 } catch (RemoteException ex) {
644 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
645 errPw.println("Exception: " + ex.getMessage());
646 return -1;
647 }
648 break;
649 }
650 default:
651 onHelpDataTestMode();
652 break;
653 }
654 return 0;
655 }
656
Shuo Qianccbaf742021-02-22 18:32:21 -0800657 private int handleEmergencyCallbackModeCommand() {
658 PrintWriter errPw = getErrPrintWriter();
659 try {
660 mInterface.startEmergencyCallbackMode();
661 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
662 } catch (RemoteException ex) {
663 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
664 errPw.println("Exception: " + ex.getMessage());
665 return -1;
666 }
667 return 0;
668 }
669
sqian9d4df8b2019-01-15 18:32:07 -0800670 private int handleEmergencyNumberTestModeCommand() {
671 PrintWriter errPw = getErrPrintWriter();
672 String opt = getNextOption();
673 if (opt == null) {
674 onHelpEmergencyNumber();
675 return 0;
676 }
677
678 switch (opt) {
679 case "-a": {
680 String emergencyNumberCmd = getNextArgRequired();
681 if (emergencyNumberCmd == null
682 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700683 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800684 + " to be specified after -a in the command ");
685 return -1;
686 }
687 try {
688 mInterface.updateEmergencyNumberListTestMode(
689 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
690 new EmergencyNumber(emergencyNumberCmd, "", "",
691 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
692 new ArrayList<String>(),
693 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
694 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
695 } catch (RemoteException ex) {
696 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
697 + ", error " + ex.getMessage());
698 errPw.println("Exception: " + ex.getMessage());
699 return -1;
700 }
701 break;
702 }
703 case "-c": {
704 try {
705 mInterface.updateEmergencyNumberListTestMode(
706 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
707 } catch (RemoteException ex) {
708 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
709 errPw.println("Exception: " + ex.getMessage());
710 return -1;
711 }
712 break;
713 }
714 case "-r": {
715 String emergencyNumberCmd = getNextArgRequired();
716 if (emergencyNumberCmd == null
717 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700718 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800719 + " to be specified after -r in the command ");
720 return -1;
721 }
722 try {
723 mInterface.updateEmergencyNumberListTestMode(
724 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
725 new EmergencyNumber(emergencyNumberCmd, "", "",
726 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
727 new ArrayList<String>(),
728 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
729 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
730 } catch (RemoteException ex) {
731 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
732 + ", error " + ex.getMessage());
733 errPw.println("Exception: " + ex.getMessage());
734 return -1;
735 }
736 break;
737 }
738 case "-p": {
739 try {
740 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
741 } catch (RemoteException ex) {
742 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
743 errPw.println("Exception: " + ex.getMessage());
744 return -1;
745 }
746 break;
747 }
748 default:
749 onHelpEmergencyNumber();
750 break;
751 }
752 return 0;
753 }
754
Hall Liud892bec2018-11-30 14:51:45 -0800755 private int handleNumberVerificationCommand() {
756 String arg = getNextArg();
757 if (arg == null) {
758 onHelpNumberVerification();
759 return 0;
760 }
761
Hall Liuca5af3a2018-12-04 16:58:23 -0800762 if (!checkShellUid()) {
763 return -1;
764 }
765
Hall Liud892bec2018-11-30 14:51:45 -0800766 switch (arg) {
767 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800768 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
769 return 0;
770 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800771 case NUMBER_VERIFICATION_FAKE_CALL: {
772 boolean val = NumberVerificationManager.getInstance()
773 .checkIncomingCall(getNextArg());
774 getOutPrintWriter().println(val ? "1" : "0");
775 return 0;
776 }
Hall Liud892bec2018-11-30 14:51:45 -0800777 }
778
779 return -1;
780 }
781
Jordan Liu0ccee222021-04-27 11:55:13 -0700782 private boolean subIsEsim(int subId) {
783 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
784 if (info != null) {
785 return info.isEmbedded();
786 }
787 return false;
788 }
789
790 private int handleEnablePhysicalSubscription(boolean enable) {
791 PrintWriter errPw = getErrPrintWriter();
792 int subId = 0;
793 try {
794 subId = Integer.parseInt(getNextArgRequired());
795 } catch (NumberFormatException e) {
796 errPw.println((enable ? "enable" : "disable")
797 + "-physical-subscription requires an integer as a subId.");
798 return -1;
799 }
800 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
801 // non user build.
802 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
803 errPw.println("cc: Permission denied.");
804 return -1;
805 }
806 // Verify that the subId represents a physical sub
807 if (subIsEsim(subId)) {
808 errPw.println("SubId " + subId + " is not for a physical subscription");
809 return -1;
810 }
811 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
812 + " physical subscription with subId=" + subId);
813 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
814 return 0;
815 }
816
Jack Nudelman644b91a2021-03-12 14:09:48 -0800817 private int handleThermalMitigationCommand() {
818 String arg = getNextArg();
819 String packageName = getNextArg();
820 if (arg == null || packageName == null) {
821 onHelpThermalMitigation();
822 return 0;
823 }
824
825 if (!checkShellUid()) {
826 return -1;
827 }
828
829 switch (arg) {
830 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
831 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
832 return 0;
833 }
834 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
835 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
836 mContext);
837 return 0;
838 }
839 default:
840 onHelpThermalMitigation();
841 }
842
843 return -1;
844
845 }
846
Tyler Gunn92479152021-01-20 16:30:10 -0800847 private int handleD2dCommand() {
848 String arg = getNextArg();
849 if (arg == null) {
850 onHelpD2D();
851 return 0;
852 }
853
854 switch (arg) {
855 case D2D_SEND: {
856 return handleD2dSendCommand();
857 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800858 case D2D_TRANSPORT: {
859 return handleD2dTransportCommand();
860 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700861 case D2D_SET_DEVICE_SUPPORT: {
862 return handleD2dDeviceSupportedCommand();
863 }
Tyler Gunn92479152021-01-20 16:30:10 -0800864 }
865
866 return -1;
867 }
868
869 private int handleD2dSendCommand() {
870 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800871 int messageType = -1;
872 int messageValue = -1;
873
Tyler Gunn92479152021-01-20 16:30:10 -0800874 String arg = getNextArg();
875 if (arg == null) {
876 onHelpD2D();
877 return 0;
878 }
879 try {
880 messageType = Integer.parseInt(arg);
881 } catch (NumberFormatException e) {
882 errPw.println("message type must be a valid integer");
883 return -1;
884 }
885
886 arg = getNextArg();
887 if (arg == null) {
888 onHelpD2D();
889 return 0;
890 }
891 try {
892 messageValue = Integer.parseInt(arg);
893 } catch (NumberFormatException e) {
894 errPw.println("message value must be a valid integer");
895 return -1;
896 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800897
Tyler Gunn92479152021-01-20 16:30:10 -0800898 try {
899 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
900 } catch (RemoteException e) {
901 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
902 errPw.println("Exception: " + e.getMessage());
903 return -1;
904 }
905
906 return 0;
907 }
908
Tyler Gunnbabbda02021-02-10 11:05:02 -0800909 private int handleD2dTransportCommand() {
910 PrintWriter errPw = getErrPrintWriter();
911
912 String arg = getNextArg();
913 if (arg == null) {
914 onHelpD2D();
915 return 0;
916 }
917
918 try {
919 mInterface.setActiveDeviceToDeviceTransport(arg);
920 } catch (RemoteException e) {
921 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
922 errPw.println("Exception: " + e.getMessage());
923 return -1;
924 }
925 return 0;
926 }
927
Tyler Gunnd4575212021-05-03 14:46:49 -0700928 private int handleD2dDeviceSupportedCommand() {
929 PrintWriter errPw = getErrPrintWriter();
930
931 String arg = getNextArg();
932 if (arg == null) {
933 onHelpD2D();
934 return 0;
935 }
936
937 boolean isEnabled = "true".equals(arg.toLowerCase());
938 try {
939 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
940 } catch (RemoteException e) {
941 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
942 errPw.println("Exception: " + e.getMessage());
943 return -1;
944 }
945 return 0;
946 }
947
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700948 // ims set-ims-service
949 private int handleImsSetServiceCommand() {
950 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700951 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700952 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800953 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700954
955 String opt;
956 while ((opt = getNextOption()) != null) {
957 switch (opt) {
958 case "-s": {
959 try {
960 slotId = Integer.parseInt(getNextArgRequired());
961 } catch (NumberFormatException e) {
962 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
963 return -1;
964 }
965 break;
966 }
967 case "-c": {
968 isCarrierService = true;
969 break;
970 }
971 case "-d": {
972 isCarrierService = false;
973 break;
974 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800975 case "-f": {
976 String featureString = getNextArgRequired();
977 String[] features = featureString.split(",");
978 for (int i = 0; i < features.length; i++) {
979 try {
980 Integer result = Integer.parseInt(features[i]);
981 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
982 || result >= ImsFeature.FEATURE_MAX) {
983 errPw.println("ims set-ims-service -f " + result
984 + " is an invalid feature.");
985 return -1;
986 }
987 featuresList.add(result);
988 } catch (NumberFormatException e) {
989 errPw.println("ims set-ims-service -f tried to parse " + features[i]
990 + " as an integer.");
991 return -1;
992 }
993 }
994 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700995 }
996 }
997 // Mandatory param, either -c or -d
998 if (isCarrierService == null) {
999 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1000 return -1;
1001 }
1002
1003 String packageName = getNextArg();
1004
1005 try {
1006 if (packageName == null) {
1007 packageName = "";
1008 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001009 int[] featureArray = new int[featuresList.size()];
1010 for (int i = 0; i < featuresList.size(); i++) {
1011 featureArray[i] = featuresList.get(i);
1012 }
1013 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1014 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001015 if (VDBG) {
1016 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001017 + (isCarrierService ? "-c " : "-d ")
1018 + "-f " + featuresList + " "
1019 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001020 }
1021 getOutPrintWriter().println(result);
1022 } catch (RemoteException e) {
1023 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001024 + (isCarrierService ? "-c " : "-d ")
1025 + "-f " + featuresList + " "
1026 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001027 errPw.println("Exception: " + e.getMessage());
1028 return -1;
1029 }
1030 return 0;
1031 }
1032
Brad Ebinger999d3302020-11-25 14:31:39 -08001033 // ims clear-ims-service-override
1034 private int handleImsClearCarrierServiceCommand() {
1035 PrintWriter errPw = getErrPrintWriter();
1036 int slotId = getDefaultSlot();
1037
1038 String opt;
1039 while ((opt = getNextOption()) != null) {
1040 switch (opt) {
1041 case "-s": {
1042 try {
1043 slotId = Integer.parseInt(getNextArgRequired());
1044 } catch (NumberFormatException e) {
1045 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1046 return -1;
1047 }
1048 break;
1049 }
1050 }
1051 }
1052
1053 try {
1054 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1055 if (VDBG) {
1056 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1057 + ", result=" + result);
1058 }
1059 getOutPrintWriter().println(result);
1060 } catch (RemoteException e) {
1061 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1062 + ", error" + e.getMessage());
1063 errPw.println("Exception: " + e.getMessage());
1064 return -1;
1065 }
1066 return 0;
1067 }
1068
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001069 // ims get-ims-service
1070 private int handleImsGetServiceCommand() {
1071 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001072 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001073 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001074 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001075
1076 String opt;
1077 while ((opt = getNextOption()) != null) {
1078 switch (opt) {
1079 case "-s": {
1080 try {
1081 slotId = Integer.parseInt(getNextArgRequired());
1082 } catch (NumberFormatException e) {
1083 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1084 return -1;
1085 }
1086 break;
1087 }
1088 case "-c": {
1089 isCarrierService = true;
1090 break;
1091 }
1092 case "-d": {
1093 isCarrierService = false;
1094 break;
1095 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001096 case "-f": {
1097 try {
1098 featureType = Integer.parseInt(getNextArg());
1099 } catch (NumberFormatException e) {
1100 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1101 return -1;
1102 }
1103 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1104 || featureType >= ImsFeature.FEATURE_MAX) {
1105 errPw.println("ims get-ims-service -f invalid feature.");
1106 return -1;
1107 }
1108 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001109 }
1110 }
1111 // Mandatory param, either -c or -d
1112 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001113 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001114 return -1;
1115 }
1116
1117 String result;
1118 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001119 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001120 } catch (RemoteException e) {
1121 return -1;
1122 }
1123 if (VDBG) {
1124 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001125 + (isCarrierService ? "-c " : "-d ")
1126 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1127 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001128 }
1129 getOutPrintWriter().println(result);
1130 return 0;
1131 }
1132
1133 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001134 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001135 String opt;
1136 while ((opt = getNextOption()) != null) {
1137 switch (opt) {
1138 case "-s": {
1139 try {
1140 slotId = Integer.parseInt(getNextArgRequired());
1141 } catch (NumberFormatException e) {
1142 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1143 return -1;
1144 }
1145 break;
1146 }
1147 }
1148 }
1149 try {
1150 mInterface.enableIms(slotId);
1151 } catch (RemoteException e) {
1152 return -1;
1153 }
1154 if (VDBG) {
1155 Log.v(LOG_TAG, "ims enable -s " + slotId);
1156 }
1157 return 0;
1158 }
1159
1160 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001161 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001162 String opt;
1163 while ((opt = getNextOption()) != null) {
1164 switch (opt) {
1165 case "-s": {
1166 try {
1167 slotId = Integer.parseInt(getNextArgRequired());
1168 } catch (NumberFormatException e) {
1169 getErrPrintWriter().println(
1170 "ims disable requires an integer as a SLOT_ID.");
1171 return -1;
1172 }
1173 break;
1174 }
1175 }
1176 }
1177 try {
1178 mInterface.disableIms(slotId);
1179 } catch (RemoteException e) {
1180 return -1;
1181 }
1182 if (VDBG) {
1183 Log.v(LOG_TAG, "ims disable -s " + slotId);
1184 }
1185 return 0;
1186 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001187
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001188 private int handleCepChange() {
1189 Log.i(LOG_TAG, "handleCepChange");
1190 String opt = getNextArg();
1191 if (opt == null) {
1192 return -1;
1193 }
1194 boolean isCepEnabled = opt.equals("enable");
1195
1196 try {
1197 mInterface.setCepEnabled(isCepEnabled);
1198 } catch (RemoteException e) {
1199 return -1;
1200 }
1201 return 0;
1202 }
1203
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001204 private int getDefaultSlot() {
1205 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1206 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1207 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1208 // If there is no default, default to slot 0.
1209 slotId = DEFAULT_PHONE_ID;
1210 }
1211 return slotId;
1212 }
sqian2fff4a32018-11-05 14:18:37 -08001213
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001214 // Parse options related to Carrier Config Commands.
1215 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001216 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001217 CcOptionParseResult result = new CcOptionParseResult();
1218 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1219 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001220
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001221 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001222 while ((opt = getNextOption()) != null) {
1223 switch (opt) {
1224 case "-s": {
1225 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001226 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1227 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1228 errPw.println(tag + "No valid subscription found.");
1229 return null;
1230 }
1231
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001232 } catch (IllegalArgumentException e) {
1233 // Missing slot id
1234 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001235 return null;
1236 }
1237 break;
1238 }
1239 case "-p": {
1240 if (allowOptionPersistent) {
1241 result.mPersistent = true;
1242 } else {
1243 errPw.println(tag + "Unexpected option " + opt);
1244 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001245 }
1246 break;
1247 }
1248 default: {
1249 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001250 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001251 }
1252 }
1253 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001254 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001255 }
1256
1257 private int slotStringToSubId(String tag, String slotString) {
1258 int slotId = -1;
1259 try {
1260 slotId = Integer.parseInt(slotString);
1261 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001262 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1263 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1264 }
1265
1266 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001267 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1268 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1269 }
1270
Qiong Liuf25799b2020-09-10 10:13:46 +08001271 Phone phone = PhoneFactory.getPhone(slotId);
1272 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001273 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1274 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1275 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001276 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001277 }
1278
Hall Liud892bec2018-11-30 14:51:45 -08001279 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001280 // adb can run as root or as shell, depending on whether the device is rooted.
1281 return Binder.getCallingUid() == Process.SHELL_UID
1282 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001283 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001284
1285 private int handleCcCommand() {
1286 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1287 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001288 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001289 getErrPrintWriter().println("cc: Permission denied.");
1290 return -1;
1291 }
1292
1293 String arg = getNextArg();
1294 if (arg == null) {
1295 onHelpCc();
1296 return 0;
1297 }
1298
1299 switch (arg) {
1300 case CC_GET_VALUE: {
1301 return handleCcGetValue();
1302 }
1303 case CC_SET_VALUE: {
1304 return handleCcSetValue();
1305 }
1306 case CC_CLEAR_VALUES: {
1307 return handleCcClearValues();
1308 }
1309 default: {
1310 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1311 }
1312 }
1313 return -1;
1314 }
1315
1316 // cc get-value
1317 private int handleCcGetValue() {
1318 PrintWriter errPw = getErrPrintWriter();
1319 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1320 String key = null;
1321
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001322 // Parse all options
1323 CcOptionParseResult options = parseCcOptions(tag, false);
1324 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001325 return -1;
1326 }
1327
1328 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001329 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001330 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001331 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001332 return -1;
1333 }
1334
1335 // Get the key.
1336 key = getNextArg();
1337 if (key != null) {
1338 // A key was provided. Verify if it is a valid key
1339 if (!bundle.containsKey(key)) {
1340 errPw.println(tag + key + " is not a valid key.");
1341 return -1;
1342 }
1343
1344 // Print the carrier config value for key.
1345 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1346 } else {
1347 // No key provided. Show all values.
1348 // Iterate over a sorted list of all carrier config keys and print them.
1349 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1350 for (String k : sortedSet) {
1351 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1352 }
1353 }
1354 return 0;
1355 }
1356
1357 // cc set-value
1358 private int handleCcSetValue() {
1359 PrintWriter errPw = getErrPrintWriter();
1360 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1361
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001362 // Parse all options
1363 CcOptionParseResult options = parseCcOptions(tag, true);
1364 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001365 return -1;
1366 }
1367
1368 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001369 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001370 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001371 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001372 return -1;
1373 }
1374
1375 // Get the key.
1376 String key = getNextArg();
1377 if (key == null || key.equals("")) {
1378 errPw.println(tag + "KEY is missing");
1379 return -1;
1380 }
1381
1382 // Verify if the key is valid
1383 if (!originalValues.containsKey(key)) {
1384 errPw.println(tag + key + " is not a valid key.");
1385 return -1;
1386 }
1387
1388 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1389 ArrayList<String> valueList = new ArrayList<String>();
1390 while (peekNextArg() != null) {
1391 valueList.add(getNextArg());
1392 }
1393
1394 // Find the type of the carrier config value
1395 CcType type = getType(tag, key, originalValues);
1396 if (type == CcType.UNKNOWN) {
1397 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1398 return -1;
1399 }
1400
1401 // Create an override bundle containing the key and value that should be overriden.
1402 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1403 if (overrideBundle == null) {
1404 return -1;
1405 }
1406
1407 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001408 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001409
1410 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001411 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001412 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001413 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001414 return -1;
1415 }
1416
1417 // Print the original and new value.
1418 String originalValueString = ccValueToString(key, type, originalValues);
1419 String newValueString = ccValueToString(key, type, newValues);
1420 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1421 getOutPrintWriter().println("New value: \n" + newValueString);
1422
1423 return 0;
1424 }
1425
1426 // cc clear-values
1427 private int handleCcClearValues() {
1428 PrintWriter errPw = getErrPrintWriter();
1429 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1430
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001431 // Parse all options
1432 CcOptionParseResult options = parseCcOptions(tag, false);
1433 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001434 return -1;
1435 }
1436
1437 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001438 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001439 getOutPrintWriter()
1440 .println("All previously set carrier config override values has been cleared");
1441 return 0;
1442 }
1443
1444 private CcType getType(String tag, String key, PersistableBundle bundle) {
1445 // Find the type by checking the type of the current value stored in the bundle.
1446 Object value = bundle.get(key);
1447
1448 if (CC_TYPE_MAP.containsKey(key)) {
1449 return CC_TYPE_MAP.get(key);
1450 } else if (value != null) {
1451 if (value instanceof Boolean) {
1452 return CcType.BOOLEAN;
1453 } else if (value instanceof Double) {
1454 return CcType.DOUBLE;
1455 } else if (value instanceof double[]) {
1456 return CcType.DOUBLE_ARRAY;
1457 } else if (value instanceof Integer) {
1458 return CcType.INT;
1459 } else if (value instanceof int[]) {
1460 return CcType.INT_ARRAY;
1461 } else if (value instanceof Long) {
1462 return CcType.LONG;
1463 } else if (value instanceof long[]) {
1464 return CcType.LONG_ARRAY;
1465 } else if (value instanceof String) {
1466 return CcType.STRING;
1467 } else if (value instanceof String[]) {
1468 return CcType.STRING_ARRAY;
1469 }
1470 } else {
1471 // Current value was null and can therefore not be used in order to find the type.
1472 // Check the name of the key to infer the type. This check is not needed for primitive
1473 // data types (boolean, double, int and long), since they can not be null.
1474 if (key.endsWith("double_array")) {
1475 return CcType.DOUBLE_ARRAY;
1476 }
1477 if (key.endsWith("int_array")) {
1478 return CcType.INT_ARRAY;
1479 }
1480 if (key.endsWith("long_array")) {
1481 return CcType.LONG_ARRAY;
1482 }
1483 if (key.endsWith("string")) {
1484 return CcType.STRING;
1485 }
1486 if (key.endsWith("string_array") || key.endsWith("strings")) {
1487 return CcType.STRING_ARRAY;
1488 }
1489 }
1490
1491 // Not possible to infer the type by looking at the current value or the key.
1492 PrintWriter errPw = getErrPrintWriter();
1493 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1494 return CcType.UNKNOWN;
1495 }
1496
1497 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1498 String result;
1499 StringBuilder valueString = new StringBuilder();
1500 String typeString = type.toString();
1501 Object value = bundle.get(key);
1502
1503 if (value == null) {
1504 valueString.append("null");
1505 } else {
1506 switch (type) {
1507 case DOUBLE_ARRAY: {
1508 // Format the string representation of the int array as value1 value2......
1509 double[] valueArray = (double[]) value;
1510 for (int i = 0; i < valueArray.length; i++) {
1511 if (i != 0) {
1512 valueString.append(" ");
1513 }
1514 valueString.append(valueArray[i]);
1515 }
1516 break;
1517 }
1518 case INT_ARRAY: {
1519 // Format the string representation of the int array as value1 value2......
1520 int[] valueArray = (int[]) value;
1521 for (int i = 0; i < valueArray.length; i++) {
1522 if (i != 0) {
1523 valueString.append(" ");
1524 }
1525 valueString.append(valueArray[i]);
1526 }
1527 break;
1528 }
1529 case LONG_ARRAY: {
1530 // Format the string representation of the int array as value1 value2......
1531 long[] valueArray = (long[]) value;
1532 for (int i = 0; i < valueArray.length; i++) {
1533 if (i != 0) {
1534 valueString.append(" ");
1535 }
1536 valueString.append(valueArray[i]);
1537 }
1538 break;
1539 }
1540 case STRING: {
1541 valueString.append("\"" + value.toString() + "\"");
1542 break;
1543 }
1544 case STRING_ARRAY: {
1545 // Format the string representation of the string array as "value1" "value2"....
1546 String[] valueArray = (String[]) value;
1547 for (int i = 0; i < valueArray.length; i++) {
1548 if (i != 0) {
1549 valueString.append(" ");
1550 }
1551 if (valueArray[i] != null) {
1552 valueString.append("\"" + valueArray[i] + "\"");
1553 } else {
1554 valueString.append("null");
1555 }
1556 }
1557 break;
1558 }
1559 default: {
1560 valueString.append(value.toString());
1561 }
1562 }
1563 }
1564 return String.format("%-70s %-15s %s", key, typeString, valueString);
1565 }
1566
1567 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1568 ArrayList<String> valueList) {
1569 PrintWriter errPw = getErrPrintWriter();
1570 PersistableBundle bundle = new PersistableBundle();
1571
1572 // First verify that a valid number of values has been provided for the type.
1573 switch (type) {
1574 case BOOLEAN:
1575 case DOUBLE:
1576 case INT:
1577 case LONG: {
1578 if (valueList.size() != 1) {
1579 errPw.println(tag + "Expected 1 value for type " + type
1580 + ". Found: " + valueList.size());
1581 return null;
1582 }
1583 break;
1584 }
1585 case STRING: {
1586 if (valueList.size() > 1) {
1587 errPw.println(tag + "Expected 0 or 1 values for type " + type
1588 + ". Found: " + valueList.size());
1589 return null;
1590 }
1591 break;
1592 }
1593 }
1594
1595 // Parse the value according to type and add it to the Bundle.
1596 switch (type) {
1597 case BOOLEAN: {
1598 if ("true".equalsIgnoreCase(valueList.get(0))) {
1599 bundle.putBoolean(key, true);
1600 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1601 bundle.putBoolean(key, false);
1602 } else {
1603 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1604 return null;
1605 }
1606 break;
1607 }
1608 case DOUBLE: {
1609 try {
1610 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1611 } catch (NumberFormatException nfe) {
1612 // Not a valid double
1613 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1614 return null;
1615 }
1616 break;
1617 }
1618 case DOUBLE_ARRAY: {
1619 double[] valueDoubleArray = null;
1620 if (valueList.size() > 0) {
1621 valueDoubleArray = new double[valueList.size()];
1622 for (int i = 0; i < valueList.size(); i++) {
1623 try {
1624 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1625 } catch (NumberFormatException nfe) {
1626 // Not a valid double
1627 errPw.println(
1628 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1629 return null;
1630 }
1631 }
1632 }
1633 bundle.putDoubleArray(key, valueDoubleArray);
1634 break;
1635 }
1636 case INT: {
1637 try {
1638 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1639 } catch (NumberFormatException nfe) {
1640 // Not a valid integer
1641 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1642 return null;
1643 }
1644 break;
1645 }
1646 case INT_ARRAY: {
1647 int[] valueIntArray = null;
1648 if (valueList.size() > 0) {
1649 valueIntArray = new int[valueList.size()];
1650 for (int i = 0; i < valueList.size(); i++) {
1651 try {
1652 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1653 } catch (NumberFormatException nfe) {
1654 // Not a valid integer
1655 errPw.println(tag
1656 + "Unable to parse " + valueList.get(i) + " as an integer.");
1657 return null;
1658 }
1659 }
1660 }
1661 bundle.putIntArray(key, valueIntArray);
1662 break;
1663 }
1664 case LONG: {
1665 try {
1666 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1667 } catch (NumberFormatException nfe) {
1668 // Not a valid long
1669 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1670 return null;
1671 }
1672 break;
1673 }
1674 case LONG_ARRAY: {
1675 long[] valueLongArray = null;
1676 if (valueList.size() > 0) {
1677 valueLongArray = new long[valueList.size()];
1678 for (int i = 0; i < valueList.size(); i++) {
1679 try {
1680 valueLongArray[i] = Long.parseLong(valueList.get(i));
1681 } catch (NumberFormatException nfe) {
1682 // Not a valid long
1683 errPw.println(
1684 tag + "Unable to parse " + valueList.get(i) + " as a long");
1685 return null;
1686 }
1687 }
1688 }
1689 bundle.putLongArray(key, valueLongArray);
1690 break;
1691 }
1692 case STRING: {
1693 String value = null;
1694 if (valueList.size() > 0) {
1695 value = valueList.get(0);
1696 }
1697 bundle.putString(key, value);
1698 break;
1699 }
1700 case STRING_ARRAY: {
1701 String[] valueStringArray = null;
1702 if (valueList.size() > 0) {
1703 valueStringArray = new String[valueList.size()];
1704 valueList.toArray(valueStringArray);
1705 }
1706 bundle.putStringArray(key, valueStringArray);
1707 break;
1708 }
1709 }
1710 return bundle;
1711 }
Shuo Qian489d9282020-07-09 11:30:03 -07001712
1713 private int handleEndBlockSuppressionCommand() {
1714 if (!checkShellUid()) {
1715 return -1;
1716 }
1717
1718 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1719 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1720 }
1721 return 0;
1722 }
Hui Wang641e81c2020-10-12 12:14:23 -07001723
Michele Berionne54af4632020-12-28 20:23:16 +00001724 private int handleRestartModemCommand() {
1725 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1726 // non user build.
1727 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1728 getErrPrintWriter().println("RestartModem: Permission denied.");
1729 return -1;
1730 }
1731
1732 boolean result = TelephonyManager.getDefault().rebootRadio();
1733 getOutPrintWriter().println(result);
1734
1735 return result ? 0 : -1;
1736 }
1737
Michele Berionne5e411512020-11-13 02:36:59 +00001738 private int handleUnattendedReboot() {
1739 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1740 // non user build.
1741 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1742 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1743 return -1;
1744 }
1745
1746 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1747 getOutPrintWriter().println("result: " + result);
1748
1749 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1750 }
1751
Hui Wang641e81c2020-10-12 12:14:23 -07001752 private int handleGbaCommand() {
1753 String arg = getNextArg();
1754 if (arg == null) {
1755 onHelpGba();
1756 return 0;
1757 }
1758
1759 switch (arg) {
1760 case GBA_SET_SERVICE: {
1761 return handleGbaSetServiceCommand();
1762 }
1763 case GBA_GET_SERVICE: {
1764 return handleGbaGetServiceCommand();
1765 }
1766 case GBA_SET_RELEASE_TIME: {
1767 return handleGbaSetReleaseCommand();
1768 }
1769 case GBA_GET_RELEASE_TIME: {
1770 return handleGbaGetReleaseCommand();
1771 }
1772 }
1773
1774 return -1;
1775 }
1776
1777 private int getSubId(String cmd) {
1778 int slotId = getDefaultSlot();
1779 String opt = getNextOption();
1780 if (opt != null && opt.equals("-s")) {
1781 try {
1782 slotId = Integer.parseInt(getNextArgRequired());
1783 } catch (NumberFormatException e) {
1784 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1785 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1786 }
1787 }
1788 int[] subIds = SubscriptionManager.getSubId(slotId);
1789 return subIds[0];
1790 }
1791
1792 private int handleGbaSetServiceCommand() {
1793 int subId = getSubId("gba set-service");
1794 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1795 return -1;
1796 }
1797
1798 String packageName = getNextArg();
1799 try {
1800 if (packageName == null) {
1801 packageName = "";
1802 }
1803 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1804 if (VDBG) {
1805 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1806 + packageName + ", result=" + result);
1807 }
1808 getOutPrintWriter().println(result);
1809 } catch (RemoteException e) {
1810 Log.w(LOG_TAG, "gba set-service " + subId + " "
1811 + packageName + ", error" + e.getMessage());
1812 getErrPrintWriter().println("Exception: " + e.getMessage());
1813 return -1;
1814 }
1815 return 0;
1816 }
1817
1818 private int handleGbaGetServiceCommand() {
1819 String result;
1820
1821 int subId = getSubId("gba get-service");
1822 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1823 return -1;
1824 }
1825
1826 try {
1827 result = mInterface.getBoundGbaService(subId);
1828 } catch (RemoteException e) {
1829 return -1;
1830 }
1831 if (VDBG) {
1832 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1833 }
1834 getOutPrintWriter().println(result);
1835 return 0;
1836 }
1837
1838 private int handleGbaSetReleaseCommand() {
1839 //the release time value could be -1
1840 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1841 : SubscriptionManager.getDefaultSubscriptionId();
1842 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1843 return -1;
1844 }
1845
1846 String intervalStr = getNextArg();
1847 if (intervalStr == null) {
1848 return -1;
1849 }
1850
1851 try {
1852 int interval = Integer.parseInt(intervalStr);
1853 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1854 if (VDBG) {
1855 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1856 + intervalStr + ", result=" + result);
1857 }
1858 getOutPrintWriter().println(result);
1859 } catch (NumberFormatException | RemoteException e) {
1860 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1861 + intervalStr + ", error" + e.getMessage());
1862 getErrPrintWriter().println("Exception: " + e.getMessage());
1863 return -1;
1864 }
1865 return 0;
1866 }
1867
1868 private int handleGbaGetReleaseCommand() {
1869 int subId = getSubId("gba get-release");
1870 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1871 return -1;
1872 }
1873
1874 int result = 0;
1875 try {
1876 result = mInterface.getGbaReleaseTime(subId);
1877 } catch (RemoteException e) {
1878 return -1;
1879 }
1880 if (VDBG) {
1881 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1882 }
1883 getOutPrintWriter().println(result);
1884 return 0;
1885 }
Hui Wang761a6682020-10-31 05:12:53 +00001886
1887 private int handleSingleRegistrationConfigCommand() {
1888 String arg = getNextArg();
1889 if (arg == null) {
1890 onHelpSrc();
1891 return 0;
1892 }
1893
1894 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001895 case SRC_SET_TEST_ENABLED: {
1896 return handleSrcSetTestEnabledCommand();
1897 }
1898 case SRC_GET_TEST_ENABLED: {
1899 return handleSrcGetTestEnabledCommand();
1900 }
Hui Wang761a6682020-10-31 05:12:53 +00001901 case SRC_SET_DEVICE_ENABLED: {
1902 return handleSrcSetDeviceEnabledCommand();
1903 }
1904 case SRC_GET_DEVICE_ENABLED: {
1905 return handleSrcGetDeviceEnabledCommand();
1906 }
1907 case SRC_SET_CARRIER_ENABLED: {
1908 return handleSrcSetCarrierEnabledCommand();
1909 }
1910 case SRC_GET_CARRIER_ENABLED: {
1911 return handleSrcGetCarrierEnabledCommand();
1912 }
Hui Wangb647abe2021-02-26 09:33:38 -08001913 case SRC_SET_FEATURE_ENABLED: {
1914 return handleSrcSetFeatureValidationCommand();
1915 }
1916 case SRC_GET_FEATURE_ENABLED: {
1917 return handleSrcGetFeatureValidationCommand();
1918 }
Hui Wang761a6682020-10-31 05:12:53 +00001919 }
1920
1921 return -1;
1922 }
1923
James.cf Linbcdf8b32021-01-14 16:44:13 +08001924 private int handleRcsUceCommand() {
1925 String arg = getNextArg();
1926 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00001927 onHelpUce();
1928 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001929 }
1930
1931 switch (arg) {
1932 case UCE_REMOVE_EAB_CONTACT:
1933 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001934 case UCE_GET_EAB_CONTACT:
1935 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001936 case UCE_GET_DEVICE_ENABLED:
1937 return handleUceGetDeviceEnabledCommand();
1938 case UCE_SET_DEVICE_ENABLED:
1939 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00001940 case UCE_OVERRIDE_PUBLISH_CAPS:
1941 return handleUceOverridePublishCaps();
1942 case UCE_GET_LAST_PIDF_XML:
1943 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001944 }
1945 return -1;
1946 }
1947
1948 private int handleRemovingEabContactCommand() {
1949 int subId = getSubId("uce remove-eab-contact");
1950 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1951 return -1;
1952 }
1953
1954 String phoneNumber = getNextArgRequired();
1955 if (TextUtils.isEmpty(phoneNumber)) {
1956 return -1;
1957 }
1958 int result = 0;
1959 try {
1960 result = mInterface.removeContactFromEab(subId, phoneNumber);
1961 } catch (RemoteException e) {
1962 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1963 getErrPrintWriter().println("Exception: " + e.getMessage());
1964 return -1;
1965 }
1966
1967 if (VDBG) {
1968 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1969 }
calvinpan293ea1b2021-02-04 17:52:13 +08001970 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001971 }
1972
calvinpane4a8a1d2021-01-25 13:51:18 +08001973 private int handleGettingEabContactCommand() {
1974 String phoneNumber = getNextArgRequired();
1975 if (TextUtils.isEmpty(phoneNumber)) {
1976 return -1;
1977 }
1978 String result = "";
1979 try {
1980 result = mInterface.getContactFromEab(phoneNumber);
1981
1982 } catch (RemoteException e) {
1983 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1984 getErrPrintWriter().println("Exception: " + e.getMessage());
1985 return -1;
1986 }
1987
1988 if (VDBG) {
1989 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1990 }
calvinpan293ea1b2021-02-04 17:52:13 +08001991 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001992 return 0;
1993 }
1994
1995 private int handleUceGetDeviceEnabledCommand() {
1996 boolean result = false;
1997 try {
1998 result = mInterface.getDeviceUceEnabled();
1999 } catch (RemoteException e) {
2000 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2001 return -1;
2002 }
2003 if (VDBG) {
2004 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2005 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002006 getOutPrintWriter().println(result);
2007 return 0;
2008 }
2009
James.cf Lin4b784aa2021-01-31 03:25:15 +08002010 private int handleUceSetDeviceEnabledCommand() {
2011 String enabledStr = getNextArg();
2012 if (TextUtils.isEmpty(enabledStr)) {
2013 return -1;
2014 }
2015
2016 try {
2017 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2018 mInterface.setDeviceUceEnabled(isEnabled);
2019 if (VDBG) {
2020 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2021 }
2022 } catch (NumberFormatException | RemoteException e) {
2023 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2024 getErrPrintWriter().println("Exception: " + e.getMessage());
2025 return -1;
2026 }
2027 return 0;
2028 }
2029
Hui Wangbaaee6a2021-02-19 20:45:36 -08002030 private int handleSrcSetTestEnabledCommand() {
2031 String enabledStr = getNextArg();
2032 if (enabledStr == null) {
2033 return -1;
2034 }
2035
2036 try {
2037 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2038 if (VDBG) {
2039 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2040 }
2041 getOutPrintWriter().println("Done");
2042 } catch (NumberFormatException | RemoteException e) {
2043 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2044 getErrPrintWriter().println("Exception: " + e.getMessage());
2045 return -1;
2046 }
2047 return 0;
2048 }
2049
2050 private int handleSrcGetTestEnabledCommand() {
2051 boolean result = false;
2052 try {
2053 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2054 } catch (RemoteException e) {
2055 return -1;
2056 }
2057 if (VDBG) {
2058 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2059 }
2060 getOutPrintWriter().println(result);
2061 return 0;
2062 }
2063
Brad Ebinger14d467f2021-02-12 06:18:28 +00002064 private int handleUceOverridePublishCaps() {
2065 int subId = getSubId("uce override-published-caps");
2066 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2067 return -1;
2068 }
2069 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2070 String operation = getNextArgRequired();
2071 String caps = getNextArg();
2072 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2073 && !"list".equals(operation)) {
2074 getErrPrintWriter().println("Invalid operation: " + operation);
2075 return -1;
2076 }
2077
2078 // add/remove requires capabilities to be specified.
2079 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2080 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2081 + "specified");
2082 return -1;
2083 }
2084
2085 ArraySet<String> capSet = new ArraySet<>();
2086 if (!TextUtils.isEmpty(caps)) {
2087 String[] capArray = caps.split(":");
2088 for (String cap : capArray) {
2089 // Allow unknown tags to be passed in as well.
2090 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2091 }
2092 }
2093
2094 RcsContactUceCapability result = null;
2095 try {
2096 switch (operation) {
2097 case "add":
2098 result = mInterface.addUceRegistrationOverrideShell(subId,
2099 new ArrayList<>(capSet));
2100 break;
2101 case "remove":
2102 result = mInterface.removeUceRegistrationOverrideShell(subId,
2103 new ArrayList<>(capSet));
2104 break;
2105 case "clear":
2106 result = mInterface.clearUceRegistrationOverrideShell(subId);
2107 break;
2108 case "list":
2109 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2110 break;
2111 }
2112 } catch (RemoteException e) {
2113 Log.w(LOG_TAG, "uce override-published-caps, 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 override-published-caps, 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
2131 private int handleUceGetPidfXml() {
2132 int subId = getSubId("uce get-last-publish-pidf");
2133 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2134 return -1;
2135 }
2136
2137 String result;
2138 try {
2139 result = mInterface.getLastUcePidfXmlShell(subId);
2140 } catch (RemoteException e) {
2141 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2142 getErrPrintWriter().println("Exception: " + e.getMessage());
2143 return -1;
2144 } catch (ServiceSpecificException sse) {
2145 // Reconstruct ImsException
2146 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2147 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2148 getErrPrintWriter().println("Exception: " + imsException);
2149 return -1;
2150 }
2151 if (result == null) {
2152 getErrPrintWriter().println("Service not available");
2153 return -1;
2154 }
2155 getOutPrintWriter().println(result);
2156 return 0;
2157 }
2158
Hui Wang761a6682020-10-31 05:12:53 +00002159 private int handleSrcSetDeviceEnabledCommand() {
2160 String enabledStr = getNextArg();
2161 if (enabledStr == null) {
2162 return -1;
2163 }
2164
2165 try {
2166 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2167 if (VDBG) {
2168 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2169 }
2170 getOutPrintWriter().println("Done");
2171 } catch (NumberFormatException | RemoteException e) {
2172 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2173 getErrPrintWriter().println("Exception: " + e.getMessage());
2174 return -1;
2175 }
2176 return 0;
2177 }
2178
2179 private int handleSrcGetDeviceEnabledCommand() {
2180 boolean result = false;
2181 try {
2182 result = mInterface.getDeviceSingleRegistrationEnabled();
2183 } catch (RemoteException e) {
2184 return -1;
2185 }
2186 if (VDBG) {
2187 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2188 }
2189 getOutPrintWriter().println(result);
2190 return 0;
2191 }
2192
2193 private int handleSrcSetCarrierEnabledCommand() {
2194 //the release time value could be -1
2195 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2196 : SubscriptionManager.getDefaultSubscriptionId();
2197 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2198 return -1;
2199 }
2200
2201 String enabledStr = getNextArg();
2202 if (enabledStr == null) {
2203 return -1;
2204 }
2205
2206 try {
2207 boolean result =
2208 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2209 if (VDBG) {
2210 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2211 + enabledStr + ", result=" + result);
2212 }
2213 getOutPrintWriter().println(result);
2214 } catch (NumberFormatException | RemoteException e) {
2215 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2216 + enabledStr + ", error" + e.getMessage());
2217 getErrPrintWriter().println("Exception: " + e.getMessage());
2218 return -1;
2219 }
2220 return 0;
2221 }
2222
2223 private int handleSrcGetCarrierEnabledCommand() {
2224 int subId = getSubId("src get-carrier-enabled");
2225 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2226 return -1;
2227 }
2228
2229 boolean result = false;
2230 try {
2231 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2232 } catch (RemoteException e) {
2233 return -1;
2234 }
2235 if (VDBG) {
2236 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2237 }
2238 getOutPrintWriter().println(result);
2239 return 0;
2240 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002241
Hui Wangb647abe2021-02-26 09:33:38 -08002242 private int handleSrcSetFeatureValidationCommand() {
2243 //the release time value could be -1
2244 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2245 : SubscriptionManager.getDefaultSubscriptionId();
2246 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2247 return -1;
2248 }
2249
2250 String enabledStr = getNextArg();
2251 if (enabledStr == null) {
2252 return -1;
2253 }
2254
2255 try {
2256 boolean result =
2257 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2258 if (VDBG) {
2259 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2260 + enabledStr + ", result=" + result);
2261 }
2262 getOutPrintWriter().println(result);
2263 } catch (NumberFormatException | RemoteException e) {
2264 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2265 + enabledStr + ", error" + e.getMessage());
2266 getErrPrintWriter().println("Exception: " + e.getMessage());
2267 return -1;
2268 }
2269 return 0;
2270 }
2271
2272 private int handleSrcGetFeatureValidationCommand() {
2273 int subId = getSubId("src get-feature-validation");
2274 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2275 return -1;
2276 }
2277
2278 Boolean result = false;
2279 try {
2280 result = mInterface.getImsFeatureValidationOverride(subId);
2281 } catch (RemoteException e) {
2282 return -1;
2283 }
2284 if (VDBG) {
2285 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2286 }
2287 getOutPrintWriter().println(result);
2288 return 0;
2289 }
2290
2291
Hall Liuaa4211e2021-01-20 15:43:39 -08002292 private void onHelpCallComposer() {
2293 PrintWriter pw = getOutPrintWriter();
2294 pw.println("Call composer commands");
2295 pw.println(" callcomposer test-mode enable|disable|query");
2296 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2297 pw.println(" upload/download from carrier servers is disabled, and operations are");
2298 pw.println(" performed using emulated local files instead.");
2299 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2300 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2301 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002302 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2303 pw.println(" Enables or disables the user setting for call composer, as set by");
2304 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002305 }
2306
2307 private int handleCallComposerCommand() {
2308 String arg = getNextArg();
2309 if (arg == null) {
2310 onHelpCallComposer();
2311 return 0;
2312 }
2313
2314 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2315 "MODIFY_PHONE_STATE required for call composer shell cmds");
2316 switch (arg) {
2317 case CALL_COMPOSER_TEST_MODE: {
2318 String enabledStr = getNextArg();
2319 if (ENABLE.equals(enabledStr)) {
2320 CallComposerPictureManager.sTestMode = true;
2321 } else if (DISABLE.equals(enabledStr)) {
2322 CallComposerPictureManager.sTestMode = false;
2323 } else if (QUERY.equals(enabledStr)) {
2324 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2325 } else {
2326 onHelpCallComposer();
2327 return 1;
2328 }
2329 break;
2330 }
2331 case CALL_COMPOSER_SIMULATE_CALL: {
2332 int subscriptionId = Integer.valueOf(getNextArg());
2333 String uuidString = getNextArg();
2334 UUID uuid = UUID.fromString(uuidString);
2335 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2336 Binder.withCleanCallingIdentity(() -> {
2337 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2338 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2339 });
2340 try {
2341 Uri uri = storageUriFuture.get();
2342 getOutPrintWriter().println(String.valueOf(uri));
2343 } catch (Exception e) {
2344 throw new RuntimeException(e);
2345 }
2346 break;
2347 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002348 case CALL_COMPOSER_USER_SETTING: {
2349 try {
2350 int subscriptionId = Integer.valueOf(getNextArg());
2351 String enabledStr = getNextArg();
2352 if (ENABLE.equals(enabledStr)) {
2353 mInterface.setCallComposerStatus(subscriptionId,
2354 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2355 } else if (DISABLE.equals(enabledStr)) {
2356 mInterface.setCallComposerStatus(subscriptionId,
2357 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2358 } else if (QUERY.equals(enabledStr)) {
2359 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2360 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2361 } else {
2362 onHelpCallComposer();
2363 return 1;
2364 }
2365 } catch (RemoteException e) {
2366 e.printStackTrace(getOutPrintWriter());
2367 return 1;
2368 }
2369 break;
2370 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002371 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002372 return 0;
2373 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002374
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002375 private int handleHasCarrierPrivilegesCommand() {
2376 String packageName = getNextArgRequired();
2377
2378 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002379 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002380 try {
2381 hasCarrierPrivileges =
2382 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2383 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2384 } catch (RemoteException e) {
2385 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2386 getErrPrintWriter().println("Exception: " + e.getMessage());
2387 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002388 } finally {
2389 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002390 }
2391
2392 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002393 return 0;
2394 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002395}