blob: f6d7b9430df18b64b8d2c6c7891c2993b49aec56 [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;
Jack Yu4c0a5502021-12-03 23:58:26 -080033import android.provider.DeviceConfig;
Nazanin014f41e2021-05-06 17:26:31 -070034import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010035import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070036import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070037import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000038import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070039import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080040import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000041import android.telephony.ims.ImsException;
42import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080043import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080044import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000045import android.util.ArrayMap;
46import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070047import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070048import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070049
Brad Ebinger14d467f2021-02-12 06:18:28 +000050import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070051import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080052import com.android.internal.telephony.Phone;
53import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080054import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080055import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080056import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080057import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080058import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070059
60import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080061import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000062import java.util.Arrays;
63import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010064import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080065import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010066import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000067import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010068import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080069import java.util.UUID;
70import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070071
72/**
73 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
74 * permission checks have been done before onCommand was called. Make sure any commands processed
75 * here also contain the appropriate permissions checks.
76 */
77
Hall Liua1548bd2019-12-24 14:14:12 -080078public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070079
80 private static final String LOG_TAG = "TelephonyShellCommand";
81 // Don't commit with this true.
82 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070083 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070084
Hall Liuaa4211e2021-01-20 15:43:39 -080085 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070086 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080087 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080088 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080089 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070090 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000091 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000092 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010093 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080094 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080095 private static final String ENABLE = "enable";
96 private static final String DISABLE = "disable";
97 private static final String QUERY = "query";
98
Hall Liu7135e502021-02-04 16:58:17 -080099 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800100 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800101 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800102
Brad Ebinger999d3302020-11-25 14:31:39 -0800103 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
104 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
105 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700106 // Used to disable or enable processing of conference event package data from the network.
107 // This is handy for testing scenarios where CEP data does not exist on a network which does
108 // support CEP data.
109 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700110
Hall Liud892bec2018-11-30 14:51:45 -0800111 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800112 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800113
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100114 private static final String CC_GET_VALUE = "get-value";
115 private static final String CC_SET_VALUE = "set-value";
116 private static final String CC_CLEAR_VALUES = "clear-values";
117
Hui Wang641e81c2020-10-12 12:14:23 -0700118 private static final String GBA_SUBCOMMAND = "gba";
119 private static final String GBA_SET_SERVICE = "set-service";
120 private static final String GBA_GET_SERVICE = "get-service";
121 private static final String GBA_SET_RELEASE_TIME = "set-release";
122 private static final String GBA_GET_RELEASE_TIME = "get-release";
123
Hui Wang761a6682020-10-31 05:12:53 +0000124 private static final String SINGLE_REGISTATION_CONFIG = "src";
125 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
126 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
127 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
128 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800129 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
130 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800131 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
132 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000133
Tyler Gunn92479152021-01-20 16:30:10 -0800134 private static final String D2D_SUBCOMMAND = "d2d";
135 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800136 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700137 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800138
Nazanin014f41e2021-05-06 17:26:31 -0700139 private static final String BARRING_SUBCOMMAND = "barring";
140 private static final String BARRING_SEND_INFO = "send";
141
James.cf Linbcdf8b32021-01-14 16:44:13 +0800142 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800143 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800144 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800145 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800146 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
147 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000148 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
149 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800150 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
151 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800152 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
153 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800154
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800155 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
156 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
157
Jordan Liu0ccee222021-04-27 11:55:13 -0700158 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
159 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
160
Jack Nudelman644b91a2021-03-12 14:09:48 -0800161 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
162 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
163 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
164
SongFerngWang98dd5992021-05-13 17:50:00 +0800165 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
166 "get-allowed-network-types-for-users";
167 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
168 "set-allowed-network-types-for-users";
Jack Yu4c0a5502021-12-03 23:58:26 -0800169 // Check if telephony new data stack is enabled.
170 private static final String GET_DATA_MODE = "get-data-mode";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700171 // Take advantage of existing methods that already contain permissions checks when possible.
172 private final ITelephony mInterface;
173
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100174 private SubscriptionManager mSubscriptionManager;
175 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700176 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700177 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100178
179 private enum CcType {
180 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
181 STRING_ARRAY, UNKNOWN
182 }
183
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100184 private class CcOptionParseResult {
185 public int mSubId;
186 public boolean mPersistent;
187 }
188
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100189 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
190 // keys by looking at the end of the string which usually tells the type.
191 // For instance: "xxxx_string", "xxxx_string_array", etc.
192 // The carrier config keys in this map does not follow this convention. It is therefore not
193 // possible to infer the type for these keys by looking at the string.
194 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
195 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
196 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
197 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
198 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
199 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
200 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
206 CcType.STRING);
207 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
208 CcType.STRING_ARRAY);
209 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
210 CcType.STRING_ARRAY);
211 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
212 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
213 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
214 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
215 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
216 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
217 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
219 }
220 };
221
Brad Ebinger14d467f2021-02-12 06:18:28 +0000222 /**
223 * Map from a shorthand string to the feature tags required in registration required in order
224 * for the RCS feature to be considered "capable".
225 */
226 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
227 static {
228 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
229 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
230 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
231 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
232 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
233 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
234 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
235 FeatureTags.FEATURE_TAG_VIDEO)));
236 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
237 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
238 map.put("call_comp",
239 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
240 map.put("call_comp_mmtel",
241 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
242 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
243 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
244 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
245 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
246 // version
247 map.put("chatbot", new ArraySet<>(Arrays.asList(
248 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
249 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
250 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
251 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
252 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
253 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
254 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
255 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
256 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
257 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
258 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
259 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
260 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
261 }
262
263
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100264 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700265 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100266 mCarrierConfigManager =
267 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
268 mSubscriptionManager = (SubscriptionManager)
269 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700270 mTelephonyRegistryManager = (TelephonyRegistryManager)
271 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700272 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700273 }
274
275 @Override
276 public int onCommand(String cmd) {
277 if (cmd == null) {
278 return handleDefaultCommands(null);
279 }
280
281 switch (cmd) {
282 case IMS_SUBCOMMAND: {
283 return handleImsCommand();
284 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800285 case RCS_UCE_COMMAND:
286 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800287 case NUMBER_VERIFICATION_SUBCOMMAND:
288 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800289 case EMERGENCY_CALLBACK_MODE:
290 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800291 case EMERGENCY_NUMBER_TEST_MODE:
292 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100293 case CARRIER_CONFIG_SUBCOMMAND: {
294 return handleCcCommand();
295 }
Shuo Qianf5125122019-12-16 17:03:07 -0800296 case DATA_TEST_MODE:
297 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700298 case END_BLOCK_SUPPRESSION:
299 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700300 case GBA_SUBCOMMAND:
301 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800302 case D2D_SUBCOMMAND:
303 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700304 case BARRING_SUBCOMMAND:
305 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000306 case SINGLE_REGISTATION_CONFIG:
307 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000308 case RESTART_MODEM:
309 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800310 case CALL_COMPOSER_SUBCOMMAND:
311 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000312 case UNATTENDED_REBOOT:
313 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800314 case HAS_CARRIER_PRIVILEGES_COMMAND:
315 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800316 case THERMAL_MITIGATION_COMMAND:
317 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700318 case DISABLE_PHYSICAL_SUBSCRIPTION:
319 return handleEnablePhysicalSubscription(false);
320 case ENABLE_PHYSICAL_SUBSCRIPTION:
321 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800322 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
323 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
324 return handleAllowedNetworkTypesCommand(cmd);
Jack Yu4c0a5502021-12-03 23:58:26 -0800325 case GET_DATA_MODE:
326 return handleGetDataMode();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700327 default: {
328 return handleDefaultCommands(cmd);
329 }
330 }
331 }
332
333 @Override
334 public void onHelp() {
335 PrintWriter pw = getOutPrintWriter();
336 pw.println("Telephony Commands:");
337 pw.println(" help");
338 pw.println(" Print this help text.");
339 pw.println(" ims");
340 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800341 pw.println(" uce");
342 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800343 pw.println(" emergency-number-test-mode");
344 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700345 pw.println(" end-block-suppression");
346 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800347 pw.println(" data");
348 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100349 pw.println(" cc");
350 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700351 pw.println(" gba");
352 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000353 pw.println(" src");
354 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000355 pw.println(" restart-modem");
356 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000357 pw.println(" unattended-reboot");
358 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800359 pw.println(" has-carrier-privileges [package]");
360 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800361 pw.println(" get-allowed-network-types-for-users");
362 pw.println(" Get the Allowed Network Types.");
363 pw.println(" set-allowed-network-types-for-users");
364 pw.println(" Set the Allowed Network Types.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700365 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800366 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800367 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700368 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800369 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100370 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700371 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000372 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800373 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700374 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800375 onHelpAllowedNetworkTypes();
Tyler Gunn92479152021-01-20 16:30:10 -0800376 }
377
378 private void onHelpD2D() {
379 PrintWriter pw = getOutPrintWriter();
380 pw.println("D2D Comms Commands:");
381 pw.println(" d2d send TYPE VALUE");
382 pw.println(" Sends a D2D message of specified type and value.");
383 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
384 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
385 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
386 MESSAGE_CALL_AUDIO_CODEC));
387 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
388 + Communicator.messageToString(
389 MESSAGE_DEVICE_BATTERY_STATE));
390 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
391 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800392 pw.println(" d2d transport TYPE");
393 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
394 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700395 pw.println(" d2d set-device-support true/default");
396 pw.println(" true - forces device support to be enabled for D2D.");
397 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
398 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700399 }
400
Nazanin014f41e2021-05-06 17:26:31 -0700401 private void onHelpBarring() {
402 PrintWriter pw = getOutPrintWriter();
403 pw.println("Barring Commands:");
404 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
405 + " -t CONDITIONAL_BARRING_TIME_SECS");
406 pw.println(" Notifies of a barring info change for the specified slot id.");
407 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
408 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
409 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
410 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
411 }
412
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700413 private void onHelpIms() {
414 PrintWriter pw = getOutPrintWriter();
415 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800416 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700417 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
418 pw.println(" ImsService. Options are:");
419 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
420 pw.println(" is specified, it will choose the default voice SIM slot.");
421 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
422 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800423 pw.println(" -f: Set the feature that this override if for, if no option is");
424 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700425 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
426 pw.println(" Gets the package name of the currently defined ImsService.");
427 pw.println(" Options are:");
428 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
429 pw.println(" is specified, it will choose the default voice SIM slot.");
430 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000431 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800432 pw.println(" -f: The feature type that the query will be requested for. If none is");
433 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800434 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
435 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
436 pw.println(" configuration overrides. Options are:");
437 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
438 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700439 pw.println(" ims enable [-s SLOT_ID]");
440 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
441 pw.println(" if none is specified.");
442 pw.println(" ims disable [-s SLOT_ID]");
443 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
444 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700445 pw.println(" ims conference-event-package [enable/disable]");
446 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700447 }
448
James.cf Linbcdf8b32021-01-14 16:44:13 +0800449 private void onHelpUce() {
450 PrintWriter pw = getOutPrintWriter();
451 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800452 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
453 pw.println(" Get the EAB contacts from the EAB database.");
454 pw.println(" Options are:");
455 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
456 pw.println(" Expected output format :");
457 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800458 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
459 pw.println(" Remove the EAB contacts from the EAB database.");
460 pw.println(" Options are:");
461 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
462 pw.println(" is specified, it will choose the default voice SIM slot.");
463 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800464 pw.println(" uce get-device-enabled");
465 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
466 pw.println(" uce set-device-enabled true|false");
467 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
468 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000469 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
470 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
471 pw.println(" Options are:");
472 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
473 pw.println(" is specified, it will choose the default voice SIM slot.");
474 pw.println(" add [CAPABILITY]: add a new capability");
475 pw.println(" remove [CAPABILITY]: remove a capability");
476 pw.println(" clear: clear all capability overrides");
477 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
478 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
479 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
480 pw.println(" chatbot_sa, chatbot_role] as well as full length");
481 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
482 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
483 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
484 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800485 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
486 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800487 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
488 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800489 }
490
Hall Liud892bec2018-11-30 14:51:45 -0800491 private void onHelpNumberVerification() {
492 PrintWriter pw = getOutPrintWriter();
493 pw.println("Number verification commands");
494 pw.println(" numverify override-package PACKAGE_NAME;");
495 pw.println(" Set the authorized package for number verification.");
496 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800497 pw.println(" numverify fake-call NUMBER;");
498 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
499 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800500 }
501
Jack Nudelman644b91a2021-03-12 14:09:48 -0800502 private void onHelpThermalMitigation() {
503 PrintWriter pw = getOutPrintWriter();
504 pw.println("Thermal mitigation commands");
505 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
506 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
507 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
508 pw.println(" Remove the package from one of the authorized packages for thermal "
509 + "mitigation.");
510 }
511
Jordan Liu0ccee222021-04-27 11:55:13 -0700512 private void onHelpDisableOrEnablePhysicalSubscription() {
513 PrintWriter pw = getOutPrintWriter();
514 pw.println("Disable or enable a physical subscription");
515 pw.println(" disable-physical-subscription SUB_ID");
516 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
517 pw.println(" enable-physical-subscription SUB_ID");
518 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
519 }
520
Shuo Qianf5125122019-12-16 17:03:07 -0800521 private void onHelpDataTestMode() {
522 PrintWriter pw = getOutPrintWriter();
523 pw.println("Mobile Data Test Mode Commands:");
524 pw.println(" data enable: enable mobile data connectivity");
525 pw.println(" data disable: disable mobile data connectivity");
526 }
527
sqian9d4df8b2019-01-15 18:32:07 -0800528 private void onHelpEmergencyNumber() {
529 PrintWriter pw = getOutPrintWriter();
530 pw.println("Emergency Number Test Mode Commands:");
531 pw.println(" emergency-number-test-mode ");
532 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
533 + " the test mode");
534 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700535 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800536 pw.println(" -c: clear the emergency number list in the test mode.");
537 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700538 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800539 pw.println(" -p: get the full emergency number list in the test mode.");
540 }
541
Shuo Qian489d9282020-07-09 11:30:03 -0700542 private void onHelpEndBlockSupperssion() {
543 PrintWriter pw = getOutPrintWriter();
544 pw.println("End Block Suppression command:");
545 pw.println(" end-block-suppression: disable suppressing blocking by contact");
546 pw.println(" with emergency services.");
547 }
548
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100549 private void onHelpCc() {
550 PrintWriter pw = getOutPrintWriter();
551 pw.println("Carrier Config Commands:");
552 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
553 pw.println(" Print carrier config values.");
554 pw.println(" Options are:");
555 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
556 pw.println(" is specified, it will choose the default voice SIM slot.");
557 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
558 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100559 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100560 pw.println(" Set carrier config KEY to NEW_VALUE.");
561 pw.println(" Options are:");
562 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
563 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100564 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100565 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
566 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
567 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
568 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
569 pw.println(" cc clear-values [-s SLOT_ID]");
570 pw.println(" Clear all carrier override values that has previously been set");
571 pw.println(" with set-value");
572 pw.println(" Options are:");
573 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
574 pw.println(" is specified, it will choose the default voice SIM slot.");
575 }
576
Hui Wang641e81c2020-10-12 12:14:23 -0700577 private void onHelpGba() {
578 PrintWriter pw = getOutPrintWriter();
579 pw.println("Gba Commands:");
580 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
581 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
582 pw.println(" Options are:");
583 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
584 pw.println(" is specified, it will choose the default voice SIM slot.");
585 pw.println(" gba get-service [-s SLOT_ID]");
586 pw.println(" Gets the package name of the currently defined GbaService.");
587 pw.println(" Options are:");
588 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
589 pw.println(" is specified, it will choose the default voice SIM slot.");
590 pw.println(" gba set-release [-s SLOT_ID] n");
591 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
592 pw.println(" Do not release/unbind if n is -1.");
593 pw.println(" Options are:");
594 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
595 pw.println(" is specified, it will choose the default voice SIM slot.");
596 pw.println(" gba get-release [-s SLOT_ID]");
597 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
598 pw.println(" Options are:");
599 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
600 pw.println(" is specified, it will choose the default voice SIM slot.");
601 }
602
Hui Wang761a6682020-10-31 05:12:53 +0000603 private void onHelpSrc() {
604 PrintWriter pw = getOutPrintWriter();
605 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800606 pw.println(" src set-test-enabled true|false");
607 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
608 pw.println(" The value could be true, false, or null(undefined).");
609 pw.println(" src get-test-enabled");
610 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000611 pw.println(" src set-device-enabled true|false|null");
612 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
613 pw.println(" The value could be true, false, or null(undefined).");
614 pw.println(" src get-device-enabled");
615 pw.println(" Gets the device config for RCS VoLTE single registration.");
616 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
617 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
618 pw.println(" The value could be true, false, or null(undefined).");
619 pw.println(" Options are:");
620 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
621 pw.println(" is specified, it will choose the default voice SIM slot.");
622 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
623 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
624 pw.println(" Options are:");
625 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
626 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800627 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
628 pw.println(" Sets ims feature validation result.");
629 pw.println(" The value could be true, false, or null(undefined).");
630 pw.println(" Options are:");
631 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
632 pw.println(" is specified, it will choose the default voice SIM slot.");
633 pw.println(" src get-feature-validation [-s SLOT_ID]");
634 pw.println(" Gets ims feature validation override value.");
635 pw.println(" Options are:");
636 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
637 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000638 }
639
SongFerngWang98dd5992021-05-13 17:50:00 +0800640 private void onHelpAllowedNetworkTypes() {
641 PrintWriter pw = getOutPrintWriter();
642 pw.println("Allowed Network Types Commands:");
643 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
644 pw.println(" Print allowed network types value.");
645 pw.println(" Options are:");
646 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
647 pw.println(" option is specified, it will choose the default voice SIM slot.");
648 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
649 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
650 pw.println(" Options are:");
651 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
652 pw.println(" option is specified, it will choose the default voice SIM slot.");
653 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
654 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
655 pw.println(" at TelephonyManager.java");
656 pw.println(" For example:");
657 pw.println(" NR only : 10000000000000000000");
658 pw.println(" NR|LTE : 11000001000000000000");
659 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
660 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
661 pw.println(" LTE only : 01000001000000000000");
662 }
663
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700664 private int handleImsCommand() {
665 String arg = getNextArg();
666 if (arg == null) {
667 onHelpIms();
668 return 0;
669 }
670
671 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800672 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700673 return handleImsSetServiceCommand();
674 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800675 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700676 return handleImsGetServiceCommand();
677 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800678 case IMS_CLEAR_SERVICE_OVERRIDE: {
679 return handleImsClearCarrierServiceCommand();
680 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800681 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700682 return handleEnableIms();
683 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800684 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700685 return handleDisableIms();
686 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700687 case IMS_CEP: {
688 return handleCepChange();
689 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700690 }
691
692 return -1;
693 }
694
Shuo Qianf5125122019-12-16 17:03:07 -0800695 private int handleDataTestModeCommand() {
696 PrintWriter errPw = getErrPrintWriter();
697 String arg = getNextArgRequired();
698 if (arg == null) {
699 onHelpDataTestMode();
700 return 0;
701 }
702 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800703 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800704 try {
705 mInterface.enableDataConnectivity();
706 } catch (RemoteException ex) {
707 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
708 errPw.println("Exception: " + ex.getMessage());
709 return -1;
710 }
711 break;
712 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800713 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800714 try {
715 mInterface.disableDataConnectivity();
716 } catch (RemoteException ex) {
717 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
718 errPw.println("Exception: " + ex.getMessage());
719 return -1;
720 }
721 break;
722 }
723 default:
724 onHelpDataTestMode();
725 break;
726 }
727 return 0;
728 }
729
Shuo Qianccbaf742021-02-22 18:32:21 -0800730 private int handleEmergencyCallbackModeCommand() {
731 PrintWriter errPw = getErrPrintWriter();
732 try {
733 mInterface.startEmergencyCallbackMode();
734 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
735 } catch (RemoteException ex) {
736 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
737 errPw.println("Exception: " + ex.getMessage());
738 return -1;
739 }
740 return 0;
741 }
742
sqian9d4df8b2019-01-15 18:32:07 -0800743 private int handleEmergencyNumberTestModeCommand() {
744 PrintWriter errPw = getErrPrintWriter();
745 String opt = getNextOption();
746 if (opt == null) {
747 onHelpEmergencyNumber();
748 return 0;
749 }
750
751 switch (opt) {
752 case "-a": {
753 String emergencyNumberCmd = getNextArgRequired();
754 if (emergencyNumberCmd == null
755 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700756 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800757 + " to be specified after -a in the command ");
758 return -1;
759 }
760 try {
761 mInterface.updateEmergencyNumberListTestMode(
762 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
763 new EmergencyNumber(emergencyNumberCmd, "", "",
764 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
765 new ArrayList<String>(),
766 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
767 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
768 } catch (RemoteException ex) {
769 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
770 + ", error " + ex.getMessage());
771 errPw.println("Exception: " + ex.getMessage());
772 return -1;
773 }
774 break;
775 }
776 case "-c": {
777 try {
778 mInterface.updateEmergencyNumberListTestMode(
779 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
780 } catch (RemoteException ex) {
781 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
782 errPw.println("Exception: " + ex.getMessage());
783 return -1;
784 }
785 break;
786 }
787 case "-r": {
788 String emergencyNumberCmd = getNextArgRequired();
789 if (emergencyNumberCmd == null
790 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700791 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800792 + " to be specified after -r in the command ");
793 return -1;
794 }
795 try {
796 mInterface.updateEmergencyNumberListTestMode(
797 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
798 new EmergencyNumber(emergencyNumberCmd, "", "",
799 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
800 new ArrayList<String>(),
801 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
802 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
803 } catch (RemoteException ex) {
804 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
805 + ", error " + ex.getMessage());
806 errPw.println("Exception: " + ex.getMessage());
807 return -1;
808 }
809 break;
810 }
811 case "-p": {
812 try {
813 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
814 } catch (RemoteException ex) {
815 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
816 errPw.println("Exception: " + ex.getMessage());
817 return -1;
818 }
819 break;
820 }
821 default:
822 onHelpEmergencyNumber();
823 break;
824 }
825 return 0;
826 }
827
Hall Liud892bec2018-11-30 14:51:45 -0800828 private int handleNumberVerificationCommand() {
829 String arg = getNextArg();
830 if (arg == null) {
831 onHelpNumberVerification();
832 return 0;
833 }
834
Hall Liuca5af3a2018-12-04 16:58:23 -0800835 if (!checkShellUid()) {
836 return -1;
837 }
838
Hall Liud892bec2018-11-30 14:51:45 -0800839 switch (arg) {
840 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800841 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
842 return 0;
843 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800844 case NUMBER_VERIFICATION_FAKE_CALL: {
845 boolean val = NumberVerificationManager.getInstance()
846 .checkIncomingCall(getNextArg());
847 getOutPrintWriter().println(val ? "1" : "0");
848 return 0;
849 }
Hall Liud892bec2018-11-30 14:51:45 -0800850 }
851
852 return -1;
853 }
854
Jordan Liu0ccee222021-04-27 11:55:13 -0700855 private boolean subIsEsim(int subId) {
856 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
857 if (info != null) {
858 return info.isEmbedded();
859 }
860 return false;
861 }
862
863 private int handleEnablePhysicalSubscription(boolean enable) {
864 PrintWriter errPw = getErrPrintWriter();
865 int subId = 0;
866 try {
867 subId = Integer.parseInt(getNextArgRequired());
868 } catch (NumberFormatException e) {
869 errPw.println((enable ? "enable" : "disable")
870 + "-physical-subscription requires an integer as a subId.");
871 return -1;
872 }
873 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
874 // non user build.
875 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
876 errPw.println("cc: Permission denied.");
877 return -1;
878 }
879 // Verify that the subId represents a physical sub
880 if (subIsEsim(subId)) {
881 errPw.println("SubId " + subId + " is not for a physical subscription");
882 return -1;
883 }
884 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
885 + " physical subscription with subId=" + subId);
886 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
887 return 0;
888 }
889
Jack Nudelman644b91a2021-03-12 14:09:48 -0800890 private int handleThermalMitigationCommand() {
891 String arg = getNextArg();
892 String packageName = getNextArg();
893 if (arg == null || packageName == null) {
894 onHelpThermalMitigation();
895 return 0;
896 }
897
898 if (!checkShellUid()) {
899 return -1;
900 }
901
902 switch (arg) {
903 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
904 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
905 return 0;
906 }
907 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
908 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
909 mContext);
910 return 0;
911 }
912 default:
913 onHelpThermalMitigation();
914 }
915
916 return -1;
917
918 }
919
Tyler Gunn92479152021-01-20 16:30:10 -0800920 private int handleD2dCommand() {
921 String arg = getNextArg();
922 if (arg == null) {
923 onHelpD2D();
924 return 0;
925 }
926
927 switch (arg) {
928 case D2D_SEND: {
929 return handleD2dSendCommand();
930 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800931 case D2D_TRANSPORT: {
932 return handleD2dTransportCommand();
933 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700934 case D2D_SET_DEVICE_SUPPORT: {
935 return handleD2dDeviceSupportedCommand();
936 }
Tyler Gunn92479152021-01-20 16:30:10 -0800937 }
938
939 return -1;
940 }
941
942 private int handleD2dSendCommand() {
943 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800944 int messageType = -1;
945 int messageValue = -1;
946
Tyler Gunn92479152021-01-20 16:30:10 -0800947 String arg = getNextArg();
948 if (arg == null) {
949 onHelpD2D();
950 return 0;
951 }
952 try {
953 messageType = Integer.parseInt(arg);
954 } catch (NumberFormatException e) {
955 errPw.println("message type must be a valid integer");
956 return -1;
957 }
958
959 arg = getNextArg();
960 if (arg == null) {
961 onHelpD2D();
962 return 0;
963 }
964 try {
965 messageValue = Integer.parseInt(arg);
966 } catch (NumberFormatException e) {
967 errPw.println("message value must be a valid integer");
968 return -1;
969 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800970
Tyler Gunn92479152021-01-20 16:30:10 -0800971 try {
972 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
973 } catch (RemoteException e) {
974 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
975 errPw.println("Exception: " + e.getMessage());
976 return -1;
977 }
978
979 return 0;
980 }
981
Tyler Gunnbabbda02021-02-10 11:05:02 -0800982 private int handleD2dTransportCommand() {
983 PrintWriter errPw = getErrPrintWriter();
984
985 String arg = getNextArg();
986 if (arg == null) {
987 onHelpD2D();
988 return 0;
989 }
990
991 try {
992 mInterface.setActiveDeviceToDeviceTransport(arg);
993 } catch (RemoteException e) {
994 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
995 errPw.println("Exception: " + e.getMessage());
996 return -1;
997 }
998 return 0;
999 }
Nazanin014f41e2021-05-06 17:26:31 -07001000 private int handleBarringCommand() {
1001 String arg = getNextArg();
1002 if (arg == null) {
1003 onHelpBarring();
1004 return 0;
1005 }
1006
1007 switch (arg) {
1008 case BARRING_SEND_INFO: {
1009 return handleBarringSendCommand();
1010 }
1011 }
1012 return -1;
1013 }
1014
1015 private int handleBarringSendCommand() {
1016 PrintWriter errPw = getErrPrintWriter();
1017 int slotId = getDefaultSlot();
1018 int subId = SubscriptionManager.getSubId(slotId)[0];
1019 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1020 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1021 boolean isConditionallyBarred = false;
1022 int conditionalBarringTimeSeconds = 0;
1023
1024 String opt;
1025 while ((opt = getNextOption()) != null) {
1026 switch (opt) {
1027 case "-s": {
1028 try {
1029 slotId = Integer.parseInt(getNextArgRequired());
1030 subId = SubscriptionManager.getSubId(slotId)[0];
1031 } catch (NumberFormatException e) {
1032 errPw.println("barring send requires an integer as a SLOT_ID.");
1033 return -1;
1034 }
1035 break;
1036 }
1037 case "-b": {
1038 try {
1039 barringType = Integer.parseInt(getNextArgRequired());
1040 if (barringType < -1 || barringType > 2) {
1041 throw new NumberFormatException();
1042 }
1043
1044 } catch (NumberFormatException e) {
1045 errPw.println("barring send requires an integer in range [-1,2] as "
1046 + "a BARRING_TYPE.");
1047 return -1;
1048 }
1049 break;
1050 }
1051 case "-c": {
1052 try {
1053 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1054 } catch (Exception e) {
1055 errPw.println("barring send requires a boolean after -c indicating"
1056 + " conditional barring");
1057 return -1;
1058 }
1059 break;
1060 }
1061 case "-t": {
1062 try {
1063 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1064 } catch (NumberFormatException e) {
1065 errPw.println("barring send requires an integer for time of barring"
1066 + " in seconds after -t for conditional barring");
1067 return -1;
1068 }
1069 break;
1070 }
1071 }
1072 }
1073 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1074 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1075 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1076 barringServiceInfos.append(0, bsi);
1077 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1078 try {
1079 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1080 } catch (Exception e) {
1081 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1082 errPw.println("Exception: " + e.getMessage());
1083 return -1;
1084 }
1085 return 0;
1086 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001087
Tyler Gunnd4575212021-05-03 14:46:49 -07001088 private int handleD2dDeviceSupportedCommand() {
1089 PrintWriter errPw = getErrPrintWriter();
1090
1091 String arg = getNextArg();
1092 if (arg == null) {
1093 onHelpD2D();
1094 return 0;
1095 }
1096
1097 boolean isEnabled = "true".equals(arg.toLowerCase());
1098 try {
1099 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1100 } catch (RemoteException e) {
1101 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1102 errPw.println("Exception: " + e.getMessage());
1103 return -1;
1104 }
1105 return 0;
1106 }
1107
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001108 // ims set-ims-service
1109 private int handleImsSetServiceCommand() {
1110 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001111 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001112 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001113 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001114
1115 String opt;
1116 while ((opt = getNextOption()) != null) {
1117 switch (opt) {
1118 case "-s": {
1119 try {
1120 slotId = Integer.parseInt(getNextArgRequired());
1121 } catch (NumberFormatException e) {
1122 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1123 return -1;
1124 }
1125 break;
1126 }
1127 case "-c": {
1128 isCarrierService = true;
1129 break;
1130 }
1131 case "-d": {
1132 isCarrierService = false;
1133 break;
1134 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001135 case "-f": {
1136 String featureString = getNextArgRequired();
1137 String[] features = featureString.split(",");
1138 for (int i = 0; i < features.length; i++) {
1139 try {
1140 Integer result = Integer.parseInt(features[i]);
1141 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1142 || result >= ImsFeature.FEATURE_MAX) {
1143 errPw.println("ims set-ims-service -f " + result
1144 + " is an invalid feature.");
1145 return -1;
1146 }
1147 featuresList.add(result);
1148 } catch (NumberFormatException e) {
1149 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1150 + " as an integer.");
1151 return -1;
1152 }
1153 }
1154 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001155 }
1156 }
1157 // Mandatory param, either -c or -d
1158 if (isCarrierService == null) {
1159 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1160 return -1;
1161 }
1162
1163 String packageName = getNextArg();
1164
1165 try {
1166 if (packageName == null) {
1167 packageName = "";
1168 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001169 int[] featureArray = new int[featuresList.size()];
1170 for (int i = 0; i < featuresList.size(); i++) {
1171 featureArray[i] = featuresList.get(i);
1172 }
1173 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1174 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001175 if (VDBG) {
1176 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001177 + (isCarrierService ? "-c " : "-d ")
1178 + "-f " + featuresList + " "
1179 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001180 }
1181 getOutPrintWriter().println(result);
1182 } catch (RemoteException e) {
1183 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001184 + (isCarrierService ? "-c " : "-d ")
1185 + "-f " + featuresList + " "
1186 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001187 errPw.println("Exception: " + e.getMessage());
1188 return -1;
1189 }
1190 return 0;
1191 }
1192
Brad Ebinger999d3302020-11-25 14:31:39 -08001193 // ims clear-ims-service-override
1194 private int handleImsClearCarrierServiceCommand() {
1195 PrintWriter errPw = getErrPrintWriter();
1196 int slotId = getDefaultSlot();
1197
1198 String opt;
1199 while ((opt = getNextOption()) != null) {
1200 switch (opt) {
1201 case "-s": {
1202 try {
1203 slotId = Integer.parseInt(getNextArgRequired());
1204 } catch (NumberFormatException e) {
1205 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1206 return -1;
1207 }
1208 break;
1209 }
1210 }
1211 }
1212
1213 try {
1214 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1215 if (VDBG) {
1216 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1217 + ", result=" + result);
1218 }
1219 getOutPrintWriter().println(result);
1220 } catch (RemoteException e) {
1221 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1222 + ", error" + e.getMessage());
1223 errPw.println("Exception: " + e.getMessage());
1224 return -1;
1225 }
1226 return 0;
1227 }
1228
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001229 // ims get-ims-service
1230 private int handleImsGetServiceCommand() {
1231 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001232 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001233 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001234 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001235
1236 String opt;
1237 while ((opt = getNextOption()) != null) {
1238 switch (opt) {
1239 case "-s": {
1240 try {
1241 slotId = Integer.parseInt(getNextArgRequired());
1242 } catch (NumberFormatException e) {
1243 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1244 return -1;
1245 }
1246 break;
1247 }
1248 case "-c": {
1249 isCarrierService = true;
1250 break;
1251 }
1252 case "-d": {
1253 isCarrierService = false;
1254 break;
1255 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001256 case "-f": {
1257 try {
1258 featureType = Integer.parseInt(getNextArg());
1259 } catch (NumberFormatException e) {
1260 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1261 return -1;
1262 }
1263 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1264 || featureType >= ImsFeature.FEATURE_MAX) {
1265 errPw.println("ims get-ims-service -f invalid feature.");
1266 return -1;
1267 }
1268 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001269 }
1270 }
1271 // Mandatory param, either -c or -d
1272 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001273 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001274 return -1;
1275 }
1276
1277 String result;
1278 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001279 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001280 } catch (RemoteException e) {
1281 return -1;
1282 }
1283 if (VDBG) {
1284 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001285 + (isCarrierService ? "-c " : "-d ")
1286 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1287 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001288 }
1289 getOutPrintWriter().println(result);
1290 return 0;
1291 }
1292
1293 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001294 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001295 String opt;
1296 while ((opt = getNextOption()) != null) {
1297 switch (opt) {
1298 case "-s": {
1299 try {
1300 slotId = Integer.parseInt(getNextArgRequired());
1301 } catch (NumberFormatException e) {
1302 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1303 return -1;
1304 }
1305 break;
1306 }
1307 }
1308 }
1309 try {
1310 mInterface.enableIms(slotId);
1311 } catch (RemoteException e) {
1312 return -1;
1313 }
1314 if (VDBG) {
1315 Log.v(LOG_TAG, "ims enable -s " + slotId);
1316 }
1317 return 0;
1318 }
1319
1320 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001321 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001322 String opt;
1323 while ((opt = getNextOption()) != null) {
1324 switch (opt) {
1325 case "-s": {
1326 try {
1327 slotId = Integer.parseInt(getNextArgRequired());
1328 } catch (NumberFormatException e) {
1329 getErrPrintWriter().println(
1330 "ims disable requires an integer as a SLOT_ID.");
1331 return -1;
1332 }
1333 break;
1334 }
1335 }
1336 }
1337 try {
1338 mInterface.disableIms(slotId);
1339 } catch (RemoteException e) {
1340 return -1;
1341 }
1342 if (VDBG) {
1343 Log.v(LOG_TAG, "ims disable -s " + slotId);
1344 }
1345 return 0;
1346 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001347
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001348 private int handleCepChange() {
1349 Log.i(LOG_TAG, "handleCepChange");
1350 String opt = getNextArg();
1351 if (opt == null) {
1352 return -1;
1353 }
1354 boolean isCepEnabled = opt.equals("enable");
1355
1356 try {
1357 mInterface.setCepEnabled(isCepEnabled);
1358 } catch (RemoteException e) {
1359 return -1;
1360 }
1361 return 0;
1362 }
1363
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001364 private int getDefaultSlot() {
1365 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1366 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1367 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1368 // If there is no default, default to slot 0.
1369 slotId = DEFAULT_PHONE_ID;
1370 }
1371 return slotId;
1372 }
sqian2fff4a32018-11-05 14:18:37 -08001373
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001374 // Parse options related to Carrier Config Commands.
1375 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001376 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001377 CcOptionParseResult result = new CcOptionParseResult();
1378 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1379 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001380
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001381 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001382 while ((opt = getNextOption()) != null) {
1383 switch (opt) {
1384 case "-s": {
1385 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001386 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1387 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1388 errPw.println(tag + "No valid subscription found.");
1389 return null;
1390 }
1391
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001392 } catch (IllegalArgumentException e) {
1393 // Missing slot id
1394 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001395 return null;
1396 }
1397 break;
1398 }
1399 case "-p": {
1400 if (allowOptionPersistent) {
1401 result.mPersistent = true;
1402 } else {
1403 errPw.println(tag + "Unexpected option " + opt);
1404 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001405 }
1406 break;
1407 }
1408 default: {
1409 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001410 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001411 }
1412 }
1413 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001414 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001415 }
1416
1417 private int slotStringToSubId(String tag, String slotString) {
1418 int slotId = -1;
1419 try {
1420 slotId = Integer.parseInt(slotString);
1421 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001422 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1423 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1424 }
1425
1426 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001427 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1428 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1429 }
1430
Qiong Liuf25799b2020-09-10 10:13:46 +08001431 Phone phone = PhoneFactory.getPhone(slotId);
1432 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001433 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1434 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1435 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001436 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001437 }
1438
Hall Liud892bec2018-11-30 14:51:45 -08001439 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001440 // adb can run as root or as shell, depending on whether the device is rooted.
1441 return Binder.getCallingUid() == Process.SHELL_UID
1442 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001443 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001444
1445 private int handleCcCommand() {
1446 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1447 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001448 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001449 getErrPrintWriter().println("cc: Permission denied.");
1450 return -1;
1451 }
1452
1453 String arg = getNextArg();
1454 if (arg == null) {
1455 onHelpCc();
1456 return 0;
1457 }
1458
1459 switch (arg) {
1460 case CC_GET_VALUE: {
1461 return handleCcGetValue();
1462 }
1463 case CC_SET_VALUE: {
1464 return handleCcSetValue();
1465 }
1466 case CC_CLEAR_VALUES: {
1467 return handleCcClearValues();
1468 }
1469 default: {
1470 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1471 }
1472 }
1473 return -1;
1474 }
1475
1476 // cc get-value
1477 private int handleCcGetValue() {
1478 PrintWriter errPw = getErrPrintWriter();
1479 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1480 String key = null;
1481
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001482 // Parse all options
1483 CcOptionParseResult options = parseCcOptions(tag, false);
1484 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001485 return -1;
1486 }
1487
1488 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001489 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001490 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001491 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001492 return -1;
1493 }
1494
1495 // Get the key.
1496 key = getNextArg();
1497 if (key != null) {
1498 // A key was provided. Verify if it is a valid key
1499 if (!bundle.containsKey(key)) {
1500 errPw.println(tag + key + " is not a valid key.");
1501 return -1;
1502 }
1503
1504 // Print the carrier config value for key.
1505 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1506 } else {
1507 // No key provided. Show all values.
1508 // Iterate over a sorted list of all carrier config keys and print them.
1509 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1510 for (String k : sortedSet) {
1511 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1512 }
1513 }
1514 return 0;
1515 }
1516
1517 // cc set-value
1518 private int handleCcSetValue() {
1519 PrintWriter errPw = getErrPrintWriter();
1520 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1521
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001522 // Parse all options
1523 CcOptionParseResult options = parseCcOptions(tag, true);
1524 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001525 return -1;
1526 }
1527
1528 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001529 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001530 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001531 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001532 return -1;
1533 }
1534
1535 // Get the key.
1536 String key = getNextArg();
1537 if (key == null || key.equals("")) {
1538 errPw.println(tag + "KEY is missing");
1539 return -1;
1540 }
1541
1542 // Verify if the key is valid
1543 if (!originalValues.containsKey(key)) {
1544 errPw.println(tag + key + " is not a valid key.");
1545 return -1;
1546 }
1547
1548 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1549 ArrayList<String> valueList = new ArrayList<String>();
1550 while (peekNextArg() != null) {
1551 valueList.add(getNextArg());
1552 }
1553
1554 // Find the type of the carrier config value
1555 CcType type = getType(tag, key, originalValues);
1556 if (type == CcType.UNKNOWN) {
1557 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1558 return -1;
1559 }
1560
1561 // Create an override bundle containing the key and value that should be overriden.
1562 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1563 if (overrideBundle == null) {
1564 return -1;
1565 }
1566
1567 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001568 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001569
1570 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001571 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001572 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001573 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001574 return -1;
1575 }
1576
1577 // Print the original and new value.
1578 String originalValueString = ccValueToString(key, type, originalValues);
1579 String newValueString = ccValueToString(key, type, newValues);
1580 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1581 getOutPrintWriter().println("New value: \n" + newValueString);
1582
1583 return 0;
1584 }
1585
1586 // cc clear-values
1587 private int handleCcClearValues() {
1588 PrintWriter errPw = getErrPrintWriter();
1589 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1590
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001591 // Parse all options
1592 CcOptionParseResult options = parseCcOptions(tag, false);
1593 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001594 return -1;
1595 }
1596
1597 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001598 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001599 getOutPrintWriter()
1600 .println("All previously set carrier config override values has been cleared");
1601 return 0;
1602 }
1603
1604 private CcType getType(String tag, String key, PersistableBundle bundle) {
1605 // Find the type by checking the type of the current value stored in the bundle.
1606 Object value = bundle.get(key);
1607
1608 if (CC_TYPE_MAP.containsKey(key)) {
1609 return CC_TYPE_MAP.get(key);
1610 } else if (value != null) {
1611 if (value instanceof Boolean) {
1612 return CcType.BOOLEAN;
1613 } else if (value instanceof Double) {
1614 return CcType.DOUBLE;
1615 } else if (value instanceof double[]) {
1616 return CcType.DOUBLE_ARRAY;
1617 } else if (value instanceof Integer) {
1618 return CcType.INT;
1619 } else if (value instanceof int[]) {
1620 return CcType.INT_ARRAY;
1621 } else if (value instanceof Long) {
1622 return CcType.LONG;
1623 } else if (value instanceof long[]) {
1624 return CcType.LONG_ARRAY;
1625 } else if (value instanceof String) {
1626 return CcType.STRING;
1627 } else if (value instanceof String[]) {
1628 return CcType.STRING_ARRAY;
1629 }
1630 } else {
1631 // Current value was null and can therefore not be used in order to find the type.
1632 // Check the name of the key to infer the type. This check is not needed for primitive
1633 // data types (boolean, double, int and long), since they can not be null.
1634 if (key.endsWith("double_array")) {
1635 return CcType.DOUBLE_ARRAY;
1636 }
1637 if (key.endsWith("int_array")) {
1638 return CcType.INT_ARRAY;
1639 }
1640 if (key.endsWith("long_array")) {
1641 return CcType.LONG_ARRAY;
1642 }
1643 if (key.endsWith("string")) {
1644 return CcType.STRING;
1645 }
1646 if (key.endsWith("string_array") || key.endsWith("strings")) {
1647 return CcType.STRING_ARRAY;
1648 }
1649 }
1650
1651 // Not possible to infer the type by looking at the current value or the key.
1652 PrintWriter errPw = getErrPrintWriter();
1653 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1654 return CcType.UNKNOWN;
1655 }
1656
1657 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1658 String result;
1659 StringBuilder valueString = new StringBuilder();
1660 String typeString = type.toString();
1661 Object value = bundle.get(key);
1662
1663 if (value == null) {
1664 valueString.append("null");
1665 } else {
1666 switch (type) {
1667 case DOUBLE_ARRAY: {
1668 // Format the string representation of the int array as value1 value2......
1669 double[] valueArray = (double[]) value;
1670 for (int i = 0; i < valueArray.length; i++) {
1671 if (i != 0) {
1672 valueString.append(" ");
1673 }
1674 valueString.append(valueArray[i]);
1675 }
1676 break;
1677 }
1678 case INT_ARRAY: {
1679 // Format the string representation of the int array as value1 value2......
1680 int[] valueArray = (int[]) value;
1681 for (int i = 0; i < valueArray.length; i++) {
1682 if (i != 0) {
1683 valueString.append(" ");
1684 }
1685 valueString.append(valueArray[i]);
1686 }
1687 break;
1688 }
1689 case LONG_ARRAY: {
1690 // Format the string representation of the int array as value1 value2......
1691 long[] valueArray = (long[]) value;
1692 for (int i = 0; i < valueArray.length; i++) {
1693 if (i != 0) {
1694 valueString.append(" ");
1695 }
1696 valueString.append(valueArray[i]);
1697 }
1698 break;
1699 }
1700 case STRING: {
1701 valueString.append("\"" + value.toString() + "\"");
1702 break;
1703 }
1704 case STRING_ARRAY: {
1705 // Format the string representation of the string array as "value1" "value2"....
1706 String[] valueArray = (String[]) value;
1707 for (int i = 0; i < valueArray.length; i++) {
1708 if (i != 0) {
1709 valueString.append(" ");
1710 }
1711 if (valueArray[i] != null) {
1712 valueString.append("\"" + valueArray[i] + "\"");
1713 } else {
1714 valueString.append("null");
1715 }
1716 }
1717 break;
1718 }
1719 default: {
1720 valueString.append(value.toString());
1721 }
1722 }
1723 }
1724 return String.format("%-70s %-15s %s", key, typeString, valueString);
1725 }
1726
1727 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1728 ArrayList<String> valueList) {
1729 PrintWriter errPw = getErrPrintWriter();
1730 PersistableBundle bundle = new PersistableBundle();
1731
1732 // First verify that a valid number of values has been provided for the type.
1733 switch (type) {
1734 case BOOLEAN:
1735 case DOUBLE:
1736 case INT:
1737 case LONG: {
1738 if (valueList.size() != 1) {
1739 errPw.println(tag + "Expected 1 value for type " + type
1740 + ". Found: " + valueList.size());
1741 return null;
1742 }
1743 break;
1744 }
1745 case STRING: {
1746 if (valueList.size() > 1) {
1747 errPw.println(tag + "Expected 0 or 1 values for type " + type
1748 + ". Found: " + valueList.size());
1749 return null;
1750 }
1751 break;
1752 }
1753 }
1754
1755 // Parse the value according to type and add it to the Bundle.
1756 switch (type) {
1757 case BOOLEAN: {
1758 if ("true".equalsIgnoreCase(valueList.get(0))) {
1759 bundle.putBoolean(key, true);
1760 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1761 bundle.putBoolean(key, false);
1762 } else {
1763 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1764 return null;
1765 }
1766 break;
1767 }
1768 case DOUBLE: {
1769 try {
1770 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1771 } catch (NumberFormatException nfe) {
1772 // Not a valid double
1773 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1774 return null;
1775 }
1776 break;
1777 }
1778 case DOUBLE_ARRAY: {
1779 double[] valueDoubleArray = null;
1780 if (valueList.size() > 0) {
1781 valueDoubleArray = new double[valueList.size()];
1782 for (int i = 0; i < valueList.size(); i++) {
1783 try {
1784 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1785 } catch (NumberFormatException nfe) {
1786 // Not a valid double
1787 errPw.println(
1788 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1789 return null;
1790 }
1791 }
1792 }
1793 bundle.putDoubleArray(key, valueDoubleArray);
1794 break;
1795 }
1796 case INT: {
1797 try {
1798 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1799 } catch (NumberFormatException nfe) {
1800 // Not a valid integer
1801 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1802 return null;
1803 }
1804 break;
1805 }
1806 case INT_ARRAY: {
1807 int[] valueIntArray = null;
1808 if (valueList.size() > 0) {
1809 valueIntArray = new int[valueList.size()];
1810 for (int i = 0; i < valueList.size(); i++) {
1811 try {
1812 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1813 } catch (NumberFormatException nfe) {
1814 // Not a valid integer
1815 errPw.println(tag
1816 + "Unable to parse " + valueList.get(i) + " as an integer.");
1817 return null;
1818 }
1819 }
1820 }
1821 bundle.putIntArray(key, valueIntArray);
1822 break;
1823 }
1824 case LONG: {
1825 try {
1826 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1827 } catch (NumberFormatException nfe) {
1828 // Not a valid long
1829 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1830 return null;
1831 }
1832 break;
1833 }
1834 case LONG_ARRAY: {
1835 long[] valueLongArray = null;
1836 if (valueList.size() > 0) {
1837 valueLongArray = new long[valueList.size()];
1838 for (int i = 0; i < valueList.size(); i++) {
1839 try {
1840 valueLongArray[i] = Long.parseLong(valueList.get(i));
1841 } catch (NumberFormatException nfe) {
1842 // Not a valid long
1843 errPw.println(
1844 tag + "Unable to parse " + valueList.get(i) + " as a long");
1845 return null;
1846 }
1847 }
1848 }
1849 bundle.putLongArray(key, valueLongArray);
1850 break;
1851 }
1852 case STRING: {
1853 String value = null;
1854 if (valueList.size() > 0) {
1855 value = valueList.get(0);
1856 }
1857 bundle.putString(key, value);
1858 break;
1859 }
1860 case STRING_ARRAY: {
1861 String[] valueStringArray = null;
1862 if (valueList.size() > 0) {
1863 valueStringArray = new String[valueList.size()];
1864 valueList.toArray(valueStringArray);
1865 }
1866 bundle.putStringArray(key, valueStringArray);
1867 break;
1868 }
1869 }
1870 return bundle;
1871 }
Shuo Qian489d9282020-07-09 11:30:03 -07001872
1873 private int handleEndBlockSuppressionCommand() {
1874 if (!checkShellUid()) {
1875 return -1;
1876 }
1877
1878 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1879 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1880 }
1881 return 0;
1882 }
Hui Wang641e81c2020-10-12 12:14:23 -07001883
Michele Berionne54af4632020-12-28 20:23:16 +00001884 private int handleRestartModemCommand() {
1885 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1886 // non user build.
1887 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1888 getErrPrintWriter().println("RestartModem: Permission denied.");
1889 return -1;
1890 }
1891
1892 boolean result = TelephonyManager.getDefault().rebootRadio();
1893 getOutPrintWriter().println(result);
1894
1895 return result ? 0 : -1;
1896 }
1897
Michele Berionne5e411512020-11-13 02:36:59 +00001898 private int handleUnattendedReboot() {
1899 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1900 // non user build.
1901 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1902 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1903 return -1;
1904 }
1905
1906 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1907 getOutPrintWriter().println("result: " + result);
1908
1909 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1910 }
1911
Hui Wang641e81c2020-10-12 12:14:23 -07001912 private int handleGbaCommand() {
1913 String arg = getNextArg();
1914 if (arg == null) {
1915 onHelpGba();
1916 return 0;
1917 }
1918
1919 switch (arg) {
1920 case GBA_SET_SERVICE: {
1921 return handleGbaSetServiceCommand();
1922 }
1923 case GBA_GET_SERVICE: {
1924 return handleGbaGetServiceCommand();
1925 }
1926 case GBA_SET_RELEASE_TIME: {
1927 return handleGbaSetReleaseCommand();
1928 }
1929 case GBA_GET_RELEASE_TIME: {
1930 return handleGbaGetReleaseCommand();
1931 }
1932 }
1933
1934 return -1;
1935 }
1936
1937 private int getSubId(String cmd) {
1938 int slotId = getDefaultSlot();
1939 String opt = getNextOption();
1940 if (opt != null && opt.equals("-s")) {
1941 try {
1942 slotId = Integer.parseInt(getNextArgRequired());
1943 } catch (NumberFormatException e) {
1944 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1945 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1946 }
1947 }
1948 int[] subIds = SubscriptionManager.getSubId(slotId);
1949 return subIds[0];
1950 }
1951
1952 private int handleGbaSetServiceCommand() {
1953 int subId = getSubId("gba set-service");
1954 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1955 return -1;
1956 }
1957
1958 String packageName = getNextArg();
1959 try {
1960 if (packageName == null) {
1961 packageName = "";
1962 }
1963 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1964 if (VDBG) {
1965 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1966 + packageName + ", result=" + result);
1967 }
1968 getOutPrintWriter().println(result);
1969 } catch (RemoteException e) {
1970 Log.w(LOG_TAG, "gba set-service " + subId + " "
1971 + packageName + ", error" + e.getMessage());
1972 getErrPrintWriter().println("Exception: " + e.getMessage());
1973 return -1;
1974 }
1975 return 0;
1976 }
1977
1978 private int handleGbaGetServiceCommand() {
1979 String result;
1980
1981 int subId = getSubId("gba get-service");
1982 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1983 return -1;
1984 }
1985
1986 try {
1987 result = mInterface.getBoundGbaService(subId);
1988 } catch (RemoteException e) {
1989 return -1;
1990 }
1991 if (VDBG) {
1992 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1993 }
1994 getOutPrintWriter().println(result);
1995 return 0;
1996 }
1997
1998 private int handleGbaSetReleaseCommand() {
1999 //the release time value could be -1
2000 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2001 : SubscriptionManager.getDefaultSubscriptionId();
2002 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2003 return -1;
2004 }
2005
2006 String intervalStr = getNextArg();
2007 if (intervalStr == null) {
2008 return -1;
2009 }
2010
2011 try {
2012 int interval = Integer.parseInt(intervalStr);
2013 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2014 if (VDBG) {
2015 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2016 + intervalStr + ", result=" + result);
2017 }
2018 getOutPrintWriter().println(result);
2019 } catch (NumberFormatException | RemoteException e) {
2020 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2021 + intervalStr + ", error" + e.getMessage());
2022 getErrPrintWriter().println("Exception: " + e.getMessage());
2023 return -1;
2024 }
2025 return 0;
2026 }
2027
2028 private int handleGbaGetReleaseCommand() {
2029 int subId = getSubId("gba get-release");
2030 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2031 return -1;
2032 }
2033
2034 int result = 0;
2035 try {
2036 result = mInterface.getGbaReleaseTime(subId);
2037 } catch (RemoteException e) {
2038 return -1;
2039 }
2040 if (VDBG) {
2041 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2042 }
2043 getOutPrintWriter().println(result);
2044 return 0;
2045 }
Hui Wang761a6682020-10-31 05:12:53 +00002046
2047 private int handleSingleRegistrationConfigCommand() {
2048 String arg = getNextArg();
2049 if (arg == null) {
2050 onHelpSrc();
2051 return 0;
2052 }
2053
2054 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002055 case SRC_SET_TEST_ENABLED: {
2056 return handleSrcSetTestEnabledCommand();
2057 }
2058 case SRC_GET_TEST_ENABLED: {
2059 return handleSrcGetTestEnabledCommand();
2060 }
Hui Wang761a6682020-10-31 05:12:53 +00002061 case SRC_SET_DEVICE_ENABLED: {
2062 return handleSrcSetDeviceEnabledCommand();
2063 }
2064 case SRC_GET_DEVICE_ENABLED: {
2065 return handleSrcGetDeviceEnabledCommand();
2066 }
2067 case SRC_SET_CARRIER_ENABLED: {
2068 return handleSrcSetCarrierEnabledCommand();
2069 }
2070 case SRC_GET_CARRIER_ENABLED: {
2071 return handleSrcGetCarrierEnabledCommand();
2072 }
Hui Wangb647abe2021-02-26 09:33:38 -08002073 case SRC_SET_FEATURE_ENABLED: {
2074 return handleSrcSetFeatureValidationCommand();
2075 }
2076 case SRC_GET_FEATURE_ENABLED: {
2077 return handleSrcGetFeatureValidationCommand();
2078 }
Hui Wang761a6682020-10-31 05:12:53 +00002079 }
2080
2081 return -1;
2082 }
2083
James.cf Linbcdf8b32021-01-14 16:44:13 +08002084 private int handleRcsUceCommand() {
2085 String arg = getNextArg();
2086 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002087 onHelpUce();
2088 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002089 }
2090
2091 switch (arg) {
2092 case UCE_REMOVE_EAB_CONTACT:
2093 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002094 case UCE_GET_EAB_CONTACT:
2095 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002096 case UCE_GET_EAB_CAPABILITY:
2097 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002098 case UCE_GET_DEVICE_ENABLED:
2099 return handleUceGetDeviceEnabledCommand();
2100 case UCE_SET_DEVICE_ENABLED:
2101 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002102 case UCE_OVERRIDE_PUBLISH_CAPS:
2103 return handleUceOverridePublishCaps();
2104 case UCE_GET_LAST_PIDF_XML:
2105 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002106 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2107 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002108 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2109 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002110 }
2111 return -1;
2112 }
2113
2114 private int handleRemovingEabContactCommand() {
2115 int subId = getSubId("uce remove-eab-contact");
2116 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2117 return -1;
2118 }
2119
2120 String phoneNumber = getNextArgRequired();
2121 if (TextUtils.isEmpty(phoneNumber)) {
2122 return -1;
2123 }
2124 int result = 0;
2125 try {
2126 result = mInterface.removeContactFromEab(subId, phoneNumber);
2127 } catch (RemoteException e) {
2128 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2129 getErrPrintWriter().println("Exception: " + e.getMessage());
2130 return -1;
2131 }
2132
2133 if (VDBG) {
2134 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2135 }
calvinpan293ea1b2021-02-04 17:52:13 +08002136 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002137 }
2138
calvinpane4a8a1d2021-01-25 13:51:18 +08002139 private int handleGettingEabContactCommand() {
2140 String phoneNumber = getNextArgRequired();
2141 if (TextUtils.isEmpty(phoneNumber)) {
2142 return -1;
2143 }
2144 String result = "";
2145 try {
2146 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002147 } catch (RemoteException e) {
2148 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2149 getErrPrintWriter().println("Exception: " + e.getMessage());
2150 return -1;
2151 }
2152
2153 if (VDBG) {
2154 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2155 }
calvinpan293ea1b2021-02-04 17:52:13 +08002156 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002157 return 0;
2158 }
2159
Calvin Pana1434322021-07-01 19:27:01 +08002160 private int handleGettingEabCapabilityCommand() {
2161 String phoneNumber = getNextArgRequired();
2162 if (TextUtils.isEmpty(phoneNumber)) {
2163 return -1;
2164 }
2165 String result = "";
2166 try {
2167 result = mInterface.getCapabilityFromEab(phoneNumber);
2168 } catch (RemoteException e) {
2169 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2170 getErrPrintWriter().println("Exception: " + e.getMessage());
2171 return -1;
2172 }
2173
2174 if (VDBG) {
2175 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2176 }
2177 getOutPrintWriter().println(result);
2178 return 0;
2179 }
2180
James.cf Lin4b784aa2021-01-31 03:25:15 +08002181 private int handleUceGetDeviceEnabledCommand() {
2182 boolean result = false;
2183 try {
2184 result = mInterface.getDeviceUceEnabled();
2185 } catch (RemoteException e) {
2186 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2187 return -1;
2188 }
2189 if (VDBG) {
2190 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2191 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002192 getOutPrintWriter().println(result);
2193 return 0;
2194 }
2195
James.cf Lin4b784aa2021-01-31 03:25:15 +08002196 private int handleUceSetDeviceEnabledCommand() {
2197 String enabledStr = getNextArg();
2198 if (TextUtils.isEmpty(enabledStr)) {
2199 return -1;
2200 }
2201
2202 try {
2203 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2204 mInterface.setDeviceUceEnabled(isEnabled);
2205 if (VDBG) {
2206 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2207 }
2208 } catch (NumberFormatException | RemoteException e) {
2209 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2210 getErrPrintWriter().println("Exception: " + e.getMessage());
2211 return -1;
2212 }
2213 return 0;
2214 }
2215
James.cf Line8713a42021-04-29 16:04:26 +08002216 private int handleUceRemoveRequestDisallowedStatus() {
2217 int subId = getSubId("uce remove-request-disallowed-status");
2218 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2219 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2220 return -1;
2221 }
2222 boolean result;
2223 try {
2224 result = mInterface.removeUceRequestDisallowedStatus(subId);
2225 } catch (RemoteException e) {
2226 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2227 return -1;
2228 }
2229 if (VDBG) {
2230 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2231 }
2232 getOutPrintWriter().println(result);
2233 return 0;
2234 }
2235
James.cf Lin0fc71b02021-05-25 01:37:38 +08002236 private int handleUceSetCapRequestTimeout() {
2237 int subId = getSubId("uce set-capabilities-request-timeout");
2238 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2239 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2240 return -1;
2241 }
2242 long timeoutAfterMs = Long.valueOf(getNextArg());
2243 boolean result;
2244 try {
2245 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2246 } catch (RemoteException e) {
2247 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2248 return -1;
2249 }
2250 if (VDBG) {
2251 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2252 }
2253 getOutPrintWriter().println(result);
2254 return 0;
2255 }
2256
Hui Wangbaaee6a2021-02-19 20:45:36 -08002257 private int handleSrcSetTestEnabledCommand() {
2258 String enabledStr = getNextArg();
2259 if (enabledStr == null) {
2260 return -1;
2261 }
2262
2263 try {
2264 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2265 if (VDBG) {
2266 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2267 }
2268 getOutPrintWriter().println("Done");
2269 } catch (NumberFormatException | RemoteException e) {
2270 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2271 getErrPrintWriter().println("Exception: " + e.getMessage());
2272 return -1;
2273 }
2274 return 0;
2275 }
2276
2277 private int handleSrcGetTestEnabledCommand() {
2278 boolean result = false;
2279 try {
2280 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2281 } catch (RemoteException e) {
2282 return -1;
2283 }
2284 if (VDBG) {
2285 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2286 }
2287 getOutPrintWriter().println(result);
2288 return 0;
2289 }
2290
Brad Ebinger14d467f2021-02-12 06:18:28 +00002291 private int handleUceOverridePublishCaps() {
2292 int subId = getSubId("uce override-published-caps");
2293 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2294 return -1;
2295 }
2296 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2297 String operation = getNextArgRequired();
2298 String caps = getNextArg();
2299 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2300 && !"list".equals(operation)) {
2301 getErrPrintWriter().println("Invalid operation: " + operation);
2302 return -1;
2303 }
2304
2305 // add/remove requires capabilities to be specified.
2306 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2307 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2308 + "specified");
2309 return -1;
2310 }
2311
2312 ArraySet<String> capSet = new ArraySet<>();
2313 if (!TextUtils.isEmpty(caps)) {
2314 String[] capArray = caps.split(":");
2315 for (String cap : capArray) {
2316 // Allow unknown tags to be passed in as well.
2317 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2318 }
2319 }
2320
2321 RcsContactUceCapability result = null;
2322 try {
2323 switch (operation) {
2324 case "add":
2325 result = mInterface.addUceRegistrationOverrideShell(subId,
2326 new ArrayList<>(capSet));
2327 break;
2328 case "remove":
2329 result = mInterface.removeUceRegistrationOverrideShell(subId,
2330 new ArrayList<>(capSet));
2331 break;
2332 case "clear":
2333 result = mInterface.clearUceRegistrationOverrideShell(subId);
2334 break;
2335 case "list":
2336 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2337 break;
2338 }
2339 } catch (RemoteException e) {
2340 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2341 getErrPrintWriter().println("Exception: " + e.getMessage());
2342 return -1;
2343 } catch (ServiceSpecificException sse) {
2344 // Reconstruct ImsException
2345 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2346 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2347 getErrPrintWriter().println("Exception: " + imsException);
2348 return -1;
2349 }
2350 if (result == null) {
2351 getErrPrintWriter().println("Service not available");
2352 return -1;
2353 }
2354 getOutPrintWriter().println(result);
2355 return 0;
2356 }
2357
2358 private int handleUceGetPidfXml() {
2359 int subId = getSubId("uce get-last-publish-pidf");
2360 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2361 return -1;
2362 }
2363
2364 String result;
2365 try {
2366 result = mInterface.getLastUcePidfXmlShell(subId);
2367 } catch (RemoteException e) {
2368 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2369 getErrPrintWriter().println("Exception: " + e.getMessage());
2370 return -1;
2371 } catch (ServiceSpecificException sse) {
2372 // Reconstruct ImsException
2373 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2374 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2375 getErrPrintWriter().println("Exception: " + imsException);
2376 return -1;
2377 }
2378 if (result == null) {
2379 getErrPrintWriter().println("Service not available");
2380 return -1;
2381 }
2382 getOutPrintWriter().println(result);
2383 return 0;
2384 }
2385
Hui Wang761a6682020-10-31 05:12:53 +00002386 private int handleSrcSetDeviceEnabledCommand() {
2387 String enabledStr = getNextArg();
2388 if (enabledStr == null) {
2389 return -1;
2390 }
2391
2392 try {
2393 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2394 if (VDBG) {
2395 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2396 }
2397 getOutPrintWriter().println("Done");
2398 } catch (NumberFormatException | RemoteException e) {
2399 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2400 getErrPrintWriter().println("Exception: " + e.getMessage());
2401 return -1;
2402 }
2403 return 0;
2404 }
2405
2406 private int handleSrcGetDeviceEnabledCommand() {
2407 boolean result = false;
2408 try {
2409 result = mInterface.getDeviceSingleRegistrationEnabled();
2410 } catch (RemoteException e) {
2411 return -1;
2412 }
2413 if (VDBG) {
2414 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2415 }
2416 getOutPrintWriter().println(result);
2417 return 0;
2418 }
2419
2420 private int handleSrcSetCarrierEnabledCommand() {
2421 //the release time value could be -1
2422 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2423 : SubscriptionManager.getDefaultSubscriptionId();
2424 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2425 return -1;
2426 }
2427
2428 String enabledStr = getNextArg();
2429 if (enabledStr == null) {
2430 return -1;
2431 }
2432
2433 try {
2434 boolean result =
2435 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2436 if (VDBG) {
2437 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2438 + enabledStr + ", result=" + result);
2439 }
2440 getOutPrintWriter().println(result);
2441 } catch (NumberFormatException | RemoteException e) {
2442 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2443 + enabledStr + ", error" + e.getMessage());
2444 getErrPrintWriter().println("Exception: " + e.getMessage());
2445 return -1;
2446 }
2447 return 0;
2448 }
2449
2450 private int handleSrcGetCarrierEnabledCommand() {
2451 int subId = getSubId("src get-carrier-enabled");
2452 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2453 return -1;
2454 }
2455
2456 boolean result = false;
2457 try {
2458 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2459 } catch (RemoteException e) {
2460 return -1;
2461 }
2462 if (VDBG) {
2463 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2464 }
2465 getOutPrintWriter().println(result);
2466 return 0;
2467 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002468
Hui Wangb647abe2021-02-26 09:33:38 -08002469 private int handleSrcSetFeatureValidationCommand() {
2470 //the release time value could be -1
2471 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2472 : SubscriptionManager.getDefaultSubscriptionId();
2473 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2474 return -1;
2475 }
2476
2477 String enabledStr = getNextArg();
2478 if (enabledStr == null) {
2479 return -1;
2480 }
2481
2482 try {
2483 boolean result =
2484 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2485 if (VDBG) {
2486 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2487 + enabledStr + ", result=" + result);
2488 }
2489 getOutPrintWriter().println(result);
2490 } catch (NumberFormatException | RemoteException e) {
2491 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2492 + enabledStr + ", error" + e.getMessage());
2493 getErrPrintWriter().println("Exception: " + e.getMessage());
2494 return -1;
2495 }
2496 return 0;
2497 }
2498
2499 private int handleSrcGetFeatureValidationCommand() {
2500 int subId = getSubId("src get-feature-validation");
2501 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2502 return -1;
2503 }
2504
2505 Boolean result = false;
2506 try {
2507 result = mInterface.getImsFeatureValidationOverride(subId);
2508 } catch (RemoteException e) {
2509 return -1;
2510 }
2511 if (VDBG) {
2512 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2513 }
2514 getOutPrintWriter().println(result);
2515 return 0;
2516 }
2517
2518
Hall Liuaa4211e2021-01-20 15:43:39 -08002519 private void onHelpCallComposer() {
2520 PrintWriter pw = getOutPrintWriter();
2521 pw.println("Call composer commands");
2522 pw.println(" callcomposer test-mode enable|disable|query");
2523 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2524 pw.println(" upload/download from carrier servers is disabled, and operations are");
2525 pw.println(" performed using emulated local files instead.");
2526 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2527 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2528 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002529 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2530 pw.println(" Enables or disables the user setting for call composer, as set by");
2531 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002532 }
2533
2534 private int handleCallComposerCommand() {
2535 String arg = getNextArg();
2536 if (arg == null) {
2537 onHelpCallComposer();
2538 return 0;
2539 }
2540
2541 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2542 "MODIFY_PHONE_STATE required for call composer shell cmds");
2543 switch (arg) {
2544 case CALL_COMPOSER_TEST_MODE: {
2545 String enabledStr = getNextArg();
2546 if (ENABLE.equals(enabledStr)) {
2547 CallComposerPictureManager.sTestMode = true;
2548 } else if (DISABLE.equals(enabledStr)) {
2549 CallComposerPictureManager.sTestMode = false;
2550 } else if (QUERY.equals(enabledStr)) {
2551 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2552 } else {
2553 onHelpCallComposer();
2554 return 1;
2555 }
2556 break;
2557 }
2558 case CALL_COMPOSER_SIMULATE_CALL: {
2559 int subscriptionId = Integer.valueOf(getNextArg());
2560 String uuidString = getNextArg();
2561 UUID uuid = UUID.fromString(uuidString);
2562 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2563 Binder.withCleanCallingIdentity(() -> {
2564 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2565 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2566 });
2567 try {
2568 Uri uri = storageUriFuture.get();
2569 getOutPrintWriter().println(String.valueOf(uri));
2570 } catch (Exception e) {
2571 throw new RuntimeException(e);
2572 }
2573 break;
2574 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002575 case CALL_COMPOSER_USER_SETTING: {
2576 try {
2577 int subscriptionId = Integer.valueOf(getNextArg());
2578 String enabledStr = getNextArg();
2579 if (ENABLE.equals(enabledStr)) {
2580 mInterface.setCallComposerStatus(subscriptionId,
2581 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2582 } else if (DISABLE.equals(enabledStr)) {
2583 mInterface.setCallComposerStatus(subscriptionId,
2584 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2585 } else if (QUERY.equals(enabledStr)) {
2586 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2587 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2588 } else {
2589 onHelpCallComposer();
2590 return 1;
2591 }
2592 } catch (RemoteException e) {
2593 e.printStackTrace(getOutPrintWriter());
2594 return 1;
2595 }
2596 break;
2597 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002598 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002599 return 0;
2600 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002601
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002602 private int handleHasCarrierPrivilegesCommand() {
2603 String packageName = getNextArgRequired();
2604
2605 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002606 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002607 try {
2608 hasCarrierPrivileges =
2609 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2610 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2611 } catch (RemoteException e) {
2612 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2613 getErrPrintWriter().println("Exception: " + e.getMessage());
2614 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002615 } finally {
2616 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002617 }
2618
2619 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002620 return 0;
2621 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002622
2623 private int handleAllowedNetworkTypesCommand(String command) {
2624 if (!checkShellUid()) {
2625 return -1;
2626 }
2627
2628 PrintWriter errPw = getErrPrintWriter();
2629 String tag = command + ": ";
2630 String opt;
2631 int subId = -1;
2632 Log.v(LOG_TAG, command + " start");
2633
2634 while ((opt = getNextOption()) != null) {
2635 if (opt.equals("-s")) {
2636 try {
2637 subId = slotStringToSubId(tag, getNextArgRequired());
2638 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2639 errPw.println(tag + "No valid subscription found.");
2640 return -1;
2641 }
2642 } catch (IllegalArgumentException e) {
2643 // Missing slot id
2644 errPw.println(tag + "SLOT_ID expected after -s.");
2645 return -1;
2646 }
2647 } else {
2648 errPw.println(tag + "Unknown option " + opt);
2649 return -1;
2650 }
2651 }
2652
2653 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2654 return handleGetAllowedNetworkTypesCommand(subId);
2655 }
2656 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2657 return handleSetAllowedNetworkTypesCommand(subId);
2658 }
2659 return -1;
2660 }
2661
2662 private int handleGetAllowedNetworkTypesCommand(int subId) {
2663 PrintWriter errPw = getErrPrintWriter();
2664
2665 long result = -1;
2666 try {
2667 if (mInterface != null) {
2668 result = mInterface.getAllowedNetworkTypesForReason(subId,
2669 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2670 } else {
2671 throw new IllegalStateException("telephony service is null.");
2672 }
2673 } catch (RemoteException e) {
2674 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2675 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2676 return -1;
2677 }
2678
2679 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2680 return 0;
2681 }
2682
2683 private int handleSetAllowedNetworkTypesCommand(int subId) {
2684 PrintWriter errPw = getErrPrintWriter();
2685
2686 String bitmaskString = getNextArg();
2687 if (TextUtils.isEmpty(bitmaskString)) {
2688 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2689 return -1;
2690 }
2691 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2692 if (allowedNetworkTypes < 0) {
2693 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2694 return -1;
2695 }
2696 boolean result = false;
2697 try {
2698 if (mInterface != null) {
2699 result = mInterface.setAllowedNetworkTypesForReason(subId,
2700 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2701 } else {
2702 throw new IllegalStateException("telephony service is null.");
2703 }
2704 } catch (RemoteException e) {
2705 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2706 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2707 return -1;
2708 }
2709
2710 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2711 if (result) {
2712 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2713 }
2714 getOutPrintWriter().println(resultMessage);
2715 return 0;
2716 }
2717
2718 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2719 if (TextUtils.isEmpty(bitmaskString)) {
2720 return -1;
2721 }
2722 if (VDBG) {
2723 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2724 + ", length: " + bitmaskString.length());
2725 }
2726 try {
2727 return Long.parseLong(bitmaskString, 2);
2728 } catch (NumberFormatException e) {
2729 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2730 return -1;
2731 }
2732 }
Jack Yu4c0a5502021-12-03 23:58:26 -08002733
2734 private int handleGetDataMode() {
2735 if (!checkShellUid()) {
2736 return -1;
2737 }
2738
2739 boolean newDataStackEnabled = false;
2740 try {
2741 newDataStackEnabled = mInterface.isUsingNewDataStack();
2742 } catch (RemoteException e) {
2743 getOutPrintWriter().println("Something went wrong. " + e);
2744 return -1;
2745 }
2746
2747 getOutPrintWriter().println("Telephony new data stack is "
2748 + (newDataStackEnabled ? "enabled." : "disabled."));
2749
2750 boolean configEnabled = Boolean.parseBoolean(DeviceConfig.getProperty(
2751 DeviceConfig.NAMESPACE_TELEPHONY, "new_telephony_data_enabled"));
2752 if (configEnabled != newDataStackEnabled) {
2753 getOutPrintWriter().println("The config has been "
2754 + (configEnabled ? "enabled" : "disabled") + ". Need to reboot the device.");
2755 } else {
2756 getOutPrintWriter().println("Run the following command to "
2757 + (configEnabled ? "disable" : "enable") + " the new telephony data stack.");
2758 getOutPrintWriter().println("adb root && adb shell device_config put telephony "
2759 + "new_telephony_data_enabled " + (configEnabled ? "false" : "true")
2760 + " && adb reboot");
2761 }
2762 return 0;
2763 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002764}