blob: 7fbdbad8cdbdcb1011b215aea453994e151ed451 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000031import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070032import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070033import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010034import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070035import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070036import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000037import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070038import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080039import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000040import android.telephony.ims.ImsException;
41import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080042import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080043import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000044import android.util.ArrayMap;
45import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070046import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070047import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048
Brad Ebinger14d467f2021-02-12 06:18:28 +000049import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080051import com.android.internal.telephony.Phone;
52import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080053import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080054import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080055import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080056import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080057import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070058
Allen Xue5522892022-03-14 21:04:49 +000059import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070060import 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";
Allen Xue5522892022-03-14 21:04:49 +0000116 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100117 private static final String CC_CLEAR_VALUES = "clear-values";
118
Hui Wang641e81c2020-10-12 12:14:23 -0700119 private static final String GBA_SUBCOMMAND = "gba";
120 private static final String GBA_SET_SERVICE = "set-service";
121 private static final String GBA_GET_SERVICE = "get-service";
122 private static final String GBA_SET_RELEASE_TIME = "set-release";
123 private static final String GBA_GET_RELEASE_TIME = "get-release";
124
Hui Wang761a6682020-10-31 05:12:53 +0000125 private static final String SINGLE_REGISTATION_CONFIG = "src";
126 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
127 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
128 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
129 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800130 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
131 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800132 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
133 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000134
Tyler Gunn92479152021-01-20 16:30:10 -0800135 private static final String D2D_SUBCOMMAND = "d2d";
136 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800137 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700138 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800139
Nazanin014f41e2021-05-06 17:26:31 -0700140 private static final String BARRING_SUBCOMMAND = "barring";
141 private static final String BARRING_SEND_INFO = "send";
142
James.cf Linbcdf8b32021-01-14 16:44:13 +0800143 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800144 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800145 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800146 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800147 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
148 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000149 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
150 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800151 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
152 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800153 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
154 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800155
jimsun38340bf2021-10-26 15:01:23 +0800156 private static final String RADIO_SUBCOMMAND = "radio";
157 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
158 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
159
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800160 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
161 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
162
Jordan Liu0ccee222021-04-27 11:55:13 -0700163 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
164 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
165
Jack Nudelman644b91a2021-03-12 14:09:48 -0800166 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
167 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
168 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
169
SongFerngWang98dd5992021-05-13 17:50:00 +0800170 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
171 "get-allowed-network-types-for-users";
172 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
173 "set-allowed-network-types-for-users";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700174 // Take advantage of existing methods that already contain permissions checks when possible.
175 private final ITelephony mInterface;
176
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100177 private SubscriptionManager mSubscriptionManager;
178 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700179 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700180 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100181
182 private enum CcType {
183 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xue5522892022-03-14 21:04:49 +0000184 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100185 }
186
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100187 private class CcOptionParseResult {
188 public int mSubId;
189 public boolean mPersistent;
190 }
191
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100192 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
193 // keys by looking at the end of the string which usually tells the type.
194 // For instance: "xxxx_string", "xxxx_string_array", etc.
195 // The carrier config keys in this map does not follow this convention. It is therefore not
196 // possible to infer the type for these keys by looking at the string.
197 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
198 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
199 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
200 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
201 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
206 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
207 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
208 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
209 CcType.STRING);
210 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
211 CcType.STRING_ARRAY);
212 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
213 CcType.STRING_ARRAY);
214 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
215 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
216 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
217 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
219 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
220 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
221 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
222 }
223 };
224
Brad Ebinger14d467f2021-02-12 06:18:28 +0000225 /**
226 * Map from a shorthand string to the feature tags required in registration required in order
227 * for the RCS feature to be considered "capable".
228 */
229 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
230 static {
231 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
232 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
233 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
234 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
235 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
236 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
237 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
238 FeatureTags.FEATURE_TAG_VIDEO)));
239 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
240 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
241 map.put("call_comp",
242 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
243 map.put("call_comp_mmtel",
244 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
245 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
246 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
247 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
248 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
249 // version
250 map.put("chatbot", new ArraySet<>(Arrays.asList(
251 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
252 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
253 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
254 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunhofa4ac962022-01-11 12:44:19 +0000255 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000256 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
257 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
258 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
259 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
260 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunhofa4ac962022-01-11 12:44:19 +0000261 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000262 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
263 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
264 }
265
266
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100267 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700268 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100269 mCarrierConfigManager =
270 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
271 mSubscriptionManager = (SubscriptionManager)
272 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700273 mTelephonyRegistryManager = (TelephonyRegistryManager)
274 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700275 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700276 }
277
278 @Override
279 public int onCommand(String cmd) {
280 if (cmd == null) {
281 return handleDefaultCommands(null);
282 }
283
284 switch (cmd) {
285 case IMS_SUBCOMMAND: {
286 return handleImsCommand();
287 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800288 case RCS_UCE_COMMAND:
289 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800290 case NUMBER_VERIFICATION_SUBCOMMAND:
291 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800292 case EMERGENCY_CALLBACK_MODE:
293 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800294 case EMERGENCY_NUMBER_TEST_MODE:
295 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100296 case CARRIER_CONFIG_SUBCOMMAND: {
297 return handleCcCommand();
298 }
Shuo Qianf5125122019-12-16 17:03:07 -0800299 case DATA_TEST_MODE:
300 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700301 case END_BLOCK_SUPPRESSION:
302 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700303 case GBA_SUBCOMMAND:
304 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800305 case D2D_SUBCOMMAND:
306 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700307 case BARRING_SUBCOMMAND:
308 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000309 case SINGLE_REGISTATION_CONFIG:
310 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000311 case RESTART_MODEM:
312 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800313 case CALL_COMPOSER_SUBCOMMAND:
314 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000315 case UNATTENDED_REBOOT:
316 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800317 case HAS_CARRIER_PRIVILEGES_COMMAND:
318 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800319 case THERMAL_MITIGATION_COMMAND:
320 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700321 case DISABLE_PHYSICAL_SUBSCRIPTION:
322 return handleEnablePhysicalSubscription(false);
323 case ENABLE_PHYSICAL_SUBSCRIPTION:
324 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800325 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
326 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
327 return handleAllowedNetworkTypesCommand(cmd);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700328 default: {
329 return handleDefaultCommands(cmd);
330 }
331 }
332 }
333
334 @Override
335 public void onHelp() {
336 PrintWriter pw = getOutPrintWriter();
337 pw.println("Telephony Commands:");
338 pw.println(" help");
339 pw.println(" Print this help text.");
340 pw.println(" ims");
341 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800342 pw.println(" uce");
343 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800344 pw.println(" emergency-number-test-mode");
345 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700346 pw.println(" end-block-suppression");
347 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800348 pw.println(" data");
349 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100350 pw.println(" cc");
351 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700352 pw.println(" gba");
353 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000354 pw.println(" src");
355 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000356 pw.println(" restart-modem");
357 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000358 pw.println(" unattended-reboot");
359 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800360 pw.println(" has-carrier-privileges [package]");
361 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800362 pw.println(" get-allowed-network-types-for-users");
363 pw.println(" Get the Allowed Network Types.");
364 pw.println(" set-allowed-network-types-for-users");
365 pw.println(" Set the Allowed Network Types.");
jimsun38340bf2021-10-26 15:01:23 +0800366 pw.println(" radio");
367 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700368 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800369 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800370 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700371 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800372 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100373 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700374 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000375 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800376 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700377 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800378 onHelpAllowedNetworkTypes();
jimsun38340bf2021-10-26 15:01:23 +0800379 onHelpRadio();
Tyler Gunn92479152021-01-20 16:30:10 -0800380 }
381
382 private void onHelpD2D() {
383 PrintWriter pw = getOutPrintWriter();
384 pw.println("D2D Comms Commands:");
385 pw.println(" d2d send TYPE VALUE");
386 pw.println(" Sends a D2D message of specified type and value.");
387 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
388 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
389 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
390 MESSAGE_CALL_AUDIO_CODEC));
391 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
392 + Communicator.messageToString(
393 MESSAGE_DEVICE_BATTERY_STATE));
394 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
395 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800396 pw.println(" d2d transport TYPE");
397 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
398 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700399 pw.println(" d2d set-device-support true/default");
400 pw.println(" true - forces device support to be enabled for D2D.");
401 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
402 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700403 }
404
Nazanin014f41e2021-05-06 17:26:31 -0700405 private void onHelpBarring() {
406 PrintWriter pw = getOutPrintWriter();
407 pw.println("Barring Commands:");
408 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
409 + " -t CONDITIONAL_BARRING_TIME_SECS");
410 pw.println(" Notifies of a barring info change for the specified slot id.");
411 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
412 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
413 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
414 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
415 }
416
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700417 private void onHelpIms() {
418 PrintWriter pw = getOutPrintWriter();
419 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800420 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700421 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
422 pw.println(" ImsService. Options are:");
423 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
424 pw.println(" is specified, it will choose the default voice SIM slot.");
425 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
426 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800427 pw.println(" -f: Set the feature that this override if for, if no option is");
428 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700429 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
430 pw.println(" Gets the package name of the currently defined ImsService.");
431 pw.println(" Options are:");
432 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
433 pw.println(" is specified, it will choose the default voice SIM slot.");
434 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000435 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800436 pw.println(" -f: The feature type that the query will be requested for. If none is");
437 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800438 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
439 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
440 pw.println(" configuration overrides. Options are:");
441 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
442 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700443 pw.println(" ims enable [-s SLOT_ID]");
444 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
445 pw.println(" if none is specified.");
446 pw.println(" ims disable [-s SLOT_ID]");
447 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
448 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700449 pw.println(" ims conference-event-package [enable/disable]");
450 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700451 }
452
James.cf Linbcdf8b32021-01-14 16:44:13 +0800453 private void onHelpUce() {
454 PrintWriter pw = getOutPrintWriter();
455 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800456 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
457 pw.println(" Get the EAB contacts from the EAB database.");
458 pw.println(" Options are:");
459 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
460 pw.println(" Expected output format :");
461 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800462 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
463 pw.println(" Remove the EAB contacts from the EAB database.");
464 pw.println(" Options are:");
465 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
466 pw.println(" is specified, it will choose the default voice SIM slot.");
467 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800468 pw.println(" uce get-device-enabled");
469 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
470 pw.println(" uce set-device-enabled true|false");
471 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
472 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000473 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
474 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
475 pw.println(" Options are:");
476 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
477 pw.println(" is specified, it will choose the default voice SIM slot.");
478 pw.println(" add [CAPABILITY]: add a new capability");
479 pw.println(" remove [CAPABILITY]: remove a capability");
480 pw.println(" clear: clear all capability overrides");
481 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
482 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
483 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
484 pw.println(" chatbot_sa, chatbot_role] as well as full length");
485 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
486 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
487 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
488 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800489 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
490 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800491 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
492 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800493 }
494
Hall Liud892bec2018-11-30 14:51:45 -0800495 private void onHelpNumberVerification() {
496 PrintWriter pw = getOutPrintWriter();
497 pw.println("Number verification commands");
498 pw.println(" numverify override-package PACKAGE_NAME;");
499 pw.println(" Set the authorized package for number verification.");
500 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800501 pw.println(" numverify fake-call NUMBER;");
502 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
503 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800504 }
505
Jack Nudelman644b91a2021-03-12 14:09:48 -0800506 private void onHelpThermalMitigation() {
507 PrintWriter pw = getOutPrintWriter();
508 pw.println("Thermal mitigation commands");
509 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
510 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
511 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
512 pw.println(" Remove the package from one of the authorized packages for thermal "
513 + "mitigation.");
514 }
515
Jordan Liu0ccee222021-04-27 11:55:13 -0700516 private void onHelpDisableOrEnablePhysicalSubscription() {
517 PrintWriter pw = getOutPrintWriter();
518 pw.println("Disable or enable a physical subscription");
519 pw.println(" disable-physical-subscription SUB_ID");
520 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
521 pw.println(" enable-physical-subscription SUB_ID");
522 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
523 }
524
Shuo Qianf5125122019-12-16 17:03:07 -0800525 private void onHelpDataTestMode() {
526 PrintWriter pw = getOutPrintWriter();
527 pw.println("Mobile Data Test Mode Commands:");
528 pw.println(" data enable: enable mobile data connectivity");
529 pw.println(" data disable: disable mobile data connectivity");
530 }
531
sqian9d4df8b2019-01-15 18:32:07 -0800532 private void onHelpEmergencyNumber() {
533 PrintWriter pw = getOutPrintWriter();
534 pw.println("Emergency Number Test Mode Commands:");
535 pw.println(" emergency-number-test-mode ");
536 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
537 + " the test mode");
538 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700539 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800540 pw.println(" -c: clear the emergency number list in the test mode.");
541 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700542 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800543 pw.println(" -p: get the full emergency number list in the test mode.");
544 }
545
Shuo Qian489d9282020-07-09 11:30:03 -0700546 private void onHelpEndBlockSupperssion() {
547 PrintWriter pw = getOutPrintWriter();
548 pw.println("End Block Suppression command:");
549 pw.println(" end-block-suppression: disable suppressing blocking by contact");
550 pw.println(" with emergency services.");
551 }
552
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100553 private void onHelpCc() {
554 PrintWriter pw = getOutPrintWriter();
555 pw.println("Carrier Config Commands:");
556 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
557 pw.println(" Print carrier config values.");
558 pw.println(" Options are:");
559 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
560 pw.println(" is specified, it will choose the default voice SIM slot.");
561 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
562 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100563 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100564 pw.println(" Set carrier config KEY to NEW_VALUE.");
565 pw.println(" Options are:");
566 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
567 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100568 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100569 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
570 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
571 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
572 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xue5522892022-03-14 21:04:49 +0000573 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
574 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
575 pw.println(" provided through standard input and follow CarrierConfig XML format.");
576 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
577 pw.println(" Options are:");
578 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
579 pw.println(" is specified, it will choose the default voice SIM slot.");
580 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100581 pw.println(" cc clear-values [-s SLOT_ID]");
582 pw.println(" Clear all carrier override values that has previously been set");
Allen Xue5522892022-03-14 21:04:49 +0000583 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100584 pw.println(" Options are:");
585 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
586 pw.println(" is specified, it will choose the default voice SIM slot.");
587 }
588
Hui Wang641e81c2020-10-12 12:14:23 -0700589 private void onHelpGba() {
590 PrintWriter pw = getOutPrintWriter();
591 pw.println("Gba Commands:");
592 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
593 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
594 pw.println(" Options are:");
595 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
596 pw.println(" is specified, it will choose the default voice SIM slot.");
597 pw.println(" gba get-service [-s SLOT_ID]");
598 pw.println(" Gets the package name of the currently defined GbaService.");
599 pw.println(" Options are:");
600 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
601 pw.println(" is specified, it will choose the default voice SIM slot.");
602 pw.println(" gba set-release [-s SLOT_ID] n");
603 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
604 pw.println(" Do not release/unbind if n is -1.");
605 pw.println(" Options are:");
606 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
607 pw.println(" is specified, it will choose the default voice SIM slot.");
608 pw.println(" gba get-release [-s SLOT_ID]");
609 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
610 pw.println(" Options are:");
611 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
612 pw.println(" is specified, it will choose the default voice SIM slot.");
613 }
614
Hui Wang761a6682020-10-31 05:12:53 +0000615 private void onHelpSrc() {
616 PrintWriter pw = getOutPrintWriter();
617 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800618 pw.println(" src set-test-enabled true|false");
619 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
620 pw.println(" The value could be true, false, or null(undefined).");
621 pw.println(" src get-test-enabled");
622 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000623 pw.println(" src set-device-enabled true|false|null");
624 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
625 pw.println(" The value could be true, false, or null(undefined).");
626 pw.println(" src get-device-enabled");
627 pw.println(" Gets the device config for RCS VoLTE single registration.");
628 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
629 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
630 pw.println(" The value could be true, false, or null(undefined).");
631 pw.println(" Options are:");
632 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
633 pw.println(" is specified, it will choose the default voice SIM slot.");
634 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
635 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
636 pw.println(" Options are:");
637 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
638 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800639 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
640 pw.println(" Sets ims feature validation result.");
641 pw.println(" The value could be true, false, or null(undefined).");
642 pw.println(" Options are:");
643 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
644 pw.println(" is specified, it will choose the default voice SIM slot.");
645 pw.println(" src get-feature-validation [-s SLOT_ID]");
646 pw.println(" Gets ims feature validation override value.");
647 pw.println(" Options are:");
648 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
649 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000650 }
651
SongFerngWang98dd5992021-05-13 17:50:00 +0800652 private void onHelpAllowedNetworkTypes() {
653 PrintWriter pw = getOutPrintWriter();
654 pw.println("Allowed Network Types Commands:");
655 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
656 pw.println(" Print allowed network types value.");
657 pw.println(" Options are:");
658 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
659 pw.println(" option is specified, it will choose the default voice SIM slot.");
660 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
661 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
662 pw.println(" Options are:");
663 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
664 pw.println(" option is specified, it will choose the default voice SIM slot.");
665 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
666 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
667 pw.println(" at TelephonyManager.java");
668 pw.println(" For example:");
669 pw.println(" NR only : 10000000000000000000");
670 pw.println(" NR|LTE : 11000001000000000000");
671 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
672 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
673 pw.println(" LTE only : 01000001000000000000");
674 }
675
jimsun38340bf2021-10-26 15:01:23 +0800676 private void onHelpRadio() {
677 PrintWriter pw = getOutPrintWriter();
678 pw.println("Radio Commands:");
679 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
680 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
681 pw.println(" to be the bound. Options are:");
682 pw.println(" -s: the service name that the modem service should be bound for.");
683 pw.println(" If no option is specified, it will bind to the default.");
684 pw.println(" radio get-modem-service");
685 pw.println(" Gets the service name of the currently defined modem service.");
686 pw.println(" If it is binding to default, 'default' returns.");
687 pw.println(" If it doesn't bind to any modem service for some reasons,");
688 pw.println(" the result would be 'unknown'.");
689 }
690
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700691 private int handleImsCommand() {
692 String arg = getNextArg();
693 if (arg == null) {
694 onHelpIms();
695 return 0;
696 }
697
698 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800699 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700700 return handleImsSetServiceCommand();
701 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800702 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700703 return handleImsGetServiceCommand();
704 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800705 case IMS_CLEAR_SERVICE_OVERRIDE: {
706 return handleImsClearCarrierServiceCommand();
707 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800708 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700709 return handleEnableIms();
710 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800711 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700712 return handleDisableIms();
713 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700714 case IMS_CEP: {
715 return handleCepChange();
716 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700717 }
718
719 return -1;
720 }
721
Shuo Qianf5125122019-12-16 17:03:07 -0800722 private int handleDataTestModeCommand() {
723 PrintWriter errPw = getErrPrintWriter();
724 String arg = getNextArgRequired();
725 if (arg == null) {
726 onHelpDataTestMode();
727 return 0;
728 }
729 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800730 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800731 try {
732 mInterface.enableDataConnectivity();
733 } catch (RemoteException ex) {
734 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
735 errPw.println("Exception: " + ex.getMessage());
736 return -1;
737 }
738 break;
739 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800740 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800741 try {
742 mInterface.disableDataConnectivity();
743 } catch (RemoteException ex) {
744 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
745 errPw.println("Exception: " + ex.getMessage());
746 return -1;
747 }
748 break;
749 }
750 default:
751 onHelpDataTestMode();
752 break;
753 }
754 return 0;
755 }
756
Shuo Qianccbaf742021-02-22 18:32:21 -0800757 private int handleEmergencyCallbackModeCommand() {
758 PrintWriter errPw = getErrPrintWriter();
759 try {
760 mInterface.startEmergencyCallbackMode();
761 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
762 } catch (RemoteException ex) {
763 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
764 errPw.println("Exception: " + ex.getMessage());
765 return -1;
766 }
767 return 0;
768 }
769
sqian9d4df8b2019-01-15 18:32:07 -0800770 private int handleEmergencyNumberTestModeCommand() {
771 PrintWriter errPw = getErrPrintWriter();
772 String opt = getNextOption();
773 if (opt == null) {
774 onHelpEmergencyNumber();
775 return 0;
776 }
777
778 switch (opt) {
779 case "-a": {
780 String emergencyNumberCmd = getNextArgRequired();
781 if (emergencyNumberCmd == null
782 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700783 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800784 + " to be specified after -a in the command ");
785 return -1;
786 }
787 try {
788 mInterface.updateEmergencyNumberListTestMode(
789 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
790 new EmergencyNumber(emergencyNumberCmd, "", "",
791 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
792 new ArrayList<String>(),
793 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
794 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
795 } catch (RemoteException ex) {
796 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
797 + ", error " + ex.getMessage());
798 errPw.println("Exception: " + ex.getMessage());
799 return -1;
800 }
801 break;
802 }
803 case "-c": {
804 try {
805 mInterface.updateEmergencyNumberListTestMode(
806 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
807 } catch (RemoteException ex) {
808 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
809 errPw.println("Exception: " + ex.getMessage());
810 return -1;
811 }
812 break;
813 }
814 case "-r": {
815 String emergencyNumberCmd = getNextArgRequired();
816 if (emergencyNumberCmd == null
817 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700818 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800819 + " to be specified after -r in the command ");
820 return -1;
821 }
822 try {
823 mInterface.updateEmergencyNumberListTestMode(
824 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
825 new EmergencyNumber(emergencyNumberCmd, "", "",
826 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
827 new ArrayList<String>(),
828 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
829 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
830 } catch (RemoteException ex) {
831 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
832 + ", error " + ex.getMessage());
833 errPw.println("Exception: " + ex.getMessage());
834 return -1;
835 }
836 break;
837 }
838 case "-p": {
839 try {
840 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
841 } catch (RemoteException ex) {
842 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
843 errPw.println("Exception: " + ex.getMessage());
844 return -1;
845 }
846 break;
847 }
848 default:
849 onHelpEmergencyNumber();
850 break;
851 }
852 return 0;
853 }
854
Hall Liud892bec2018-11-30 14:51:45 -0800855 private int handleNumberVerificationCommand() {
856 String arg = getNextArg();
857 if (arg == null) {
858 onHelpNumberVerification();
859 return 0;
860 }
861
Hall Liuca5af3a2018-12-04 16:58:23 -0800862 if (!checkShellUid()) {
863 return -1;
864 }
865
Hall Liud892bec2018-11-30 14:51:45 -0800866 switch (arg) {
867 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800868 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
869 return 0;
870 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800871 case NUMBER_VERIFICATION_FAKE_CALL: {
872 boolean val = NumberVerificationManager.getInstance()
873 .checkIncomingCall(getNextArg());
874 getOutPrintWriter().println(val ? "1" : "0");
875 return 0;
876 }
Hall Liud892bec2018-11-30 14:51:45 -0800877 }
878
879 return -1;
880 }
881
Jordan Liu0ccee222021-04-27 11:55:13 -0700882 private boolean subIsEsim(int subId) {
883 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
884 if (info != null) {
885 return info.isEmbedded();
886 }
887 return false;
888 }
889
890 private int handleEnablePhysicalSubscription(boolean enable) {
891 PrintWriter errPw = getErrPrintWriter();
892 int subId = 0;
893 try {
894 subId = Integer.parseInt(getNextArgRequired());
895 } catch (NumberFormatException e) {
896 errPw.println((enable ? "enable" : "disable")
897 + "-physical-subscription requires an integer as a subId.");
898 return -1;
899 }
900 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
901 // non user build.
902 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
903 errPw.println("cc: Permission denied.");
904 return -1;
905 }
906 // Verify that the subId represents a physical sub
907 if (subIsEsim(subId)) {
908 errPw.println("SubId " + subId + " is not for a physical subscription");
909 return -1;
910 }
911 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
912 + " physical subscription with subId=" + subId);
913 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
914 return 0;
915 }
916
Jack Nudelman644b91a2021-03-12 14:09:48 -0800917 private int handleThermalMitigationCommand() {
918 String arg = getNextArg();
919 String packageName = getNextArg();
920 if (arg == null || packageName == null) {
921 onHelpThermalMitigation();
922 return 0;
923 }
924
925 if (!checkShellUid()) {
926 return -1;
927 }
928
929 switch (arg) {
930 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
931 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
932 return 0;
933 }
934 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
935 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
936 mContext);
937 return 0;
938 }
939 default:
940 onHelpThermalMitigation();
941 }
942
943 return -1;
944
945 }
946
Tyler Gunn92479152021-01-20 16:30:10 -0800947 private int handleD2dCommand() {
948 String arg = getNextArg();
949 if (arg == null) {
950 onHelpD2D();
951 return 0;
952 }
953
954 switch (arg) {
955 case D2D_SEND: {
956 return handleD2dSendCommand();
957 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800958 case D2D_TRANSPORT: {
959 return handleD2dTransportCommand();
960 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700961 case D2D_SET_DEVICE_SUPPORT: {
962 return handleD2dDeviceSupportedCommand();
963 }
Tyler Gunn92479152021-01-20 16:30:10 -0800964 }
965
966 return -1;
967 }
968
969 private int handleD2dSendCommand() {
970 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800971 int messageType = -1;
972 int messageValue = -1;
973
Tyler Gunn92479152021-01-20 16:30:10 -0800974 String arg = getNextArg();
975 if (arg == null) {
976 onHelpD2D();
977 return 0;
978 }
979 try {
980 messageType = Integer.parseInt(arg);
981 } catch (NumberFormatException e) {
982 errPw.println("message type must be a valid integer");
983 return -1;
984 }
985
986 arg = getNextArg();
987 if (arg == null) {
988 onHelpD2D();
989 return 0;
990 }
991 try {
992 messageValue = Integer.parseInt(arg);
993 } catch (NumberFormatException e) {
994 errPw.println("message value must be a valid integer");
995 return -1;
996 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800997
Tyler Gunn92479152021-01-20 16:30:10 -0800998 try {
999 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1000 } catch (RemoteException e) {
1001 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1002 errPw.println("Exception: " + e.getMessage());
1003 return -1;
1004 }
1005
1006 return 0;
1007 }
1008
Tyler Gunnbabbda02021-02-10 11:05:02 -08001009 private int handleD2dTransportCommand() {
1010 PrintWriter errPw = getErrPrintWriter();
1011
1012 String arg = getNextArg();
1013 if (arg == null) {
1014 onHelpD2D();
1015 return 0;
1016 }
1017
1018 try {
1019 mInterface.setActiveDeviceToDeviceTransport(arg);
1020 } catch (RemoteException e) {
1021 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1022 errPw.println("Exception: " + e.getMessage());
1023 return -1;
1024 }
1025 return 0;
1026 }
Nazanin014f41e2021-05-06 17:26:31 -07001027 private int handleBarringCommand() {
1028 String arg = getNextArg();
1029 if (arg == null) {
1030 onHelpBarring();
1031 return 0;
1032 }
1033
1034 switch (arg) {
1035 case BARRING_SEND_INFO: {
1036 return handleBarringSendCommand();
1037 }
1038 }
1039 return -1;
1040 }
1041
1042 private int handleBarringSendCommand() {
1043 PrintWriter errPw = getErrPrintWriter();
1044 int slotId = getDefaultSlot();
1045 int subId = SubscriptionManager.getSubId(slotId)[0];
1046 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1047 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1048 boolean isConditionallyBarred = false;
1049 int conditionalBarringTimeSeconds = 0;
1050
1051 String opt;
1052 while ((opt = getNextOption()) != null) {
1053 switch (opt) {
1054 case "-s": {
1055 try {
1056 slotId = Integer.parseInt(getNextArgRequired());
1057 subId = SubscriptionManager.getSubId(slotId)[0];
1058 } catch (NumberFormatException e) {
1059 errPw.println("barring send requires an integer as a SLOT_ID.");
1060 return -1;
1061 }
1062 break;
1063 }
1064 case "-b": {
1065 try {
1066 barringType = Integer.parseInt(getNextArgRequired());
1067 if (barringType < -1 || barringType > 2) {
1068 throw new NumberFormatException();
1069 }
1070
1071 } catch (NumberFormatException e) {
1072 errPw.println("barring send requires an integer in range [-1,2] as "
1073 + "a BARRING_TYPE.");
1074 return -1;
1075 }
1076 break;
1077 }
1078 case "-c": {
1079 try {
1080 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1081 } catch (Exception e) {
1082 errPw.println("barring send requires a boolean after -c indicating"
1083 + " conditional barring");
1084 return -1;
1085 }
1086 break;
1087 }
1088 case "-t": {
1089 try {
1090 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1091 } catch (NumberFormatException e) {
1092 errPw.println("barring send requires an integer for time of barring"
1093 + " in seconds after -t for conditional barring");
1094 return -1;
1095 }
1096 break;
1097 }
1098 }
1099 }
1100 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1101 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1102 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1103 barringServiceInfos.append(0, bsi);
1104 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1105 try {
1106 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1107 } catch (Exception e) {
1108 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1109 errPw.println("Exception: " + e.getMessage());
1110 return -1;
1111 }
1112 return 0;
1113 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001114
Tyler Gunnd4575212021-05-03 14:46:49 -07001115 private int handleD2dDeviceSupportedCommand() {
1116 PrintWriter errPw = getErrPrintWriter();
1117
1118 String arg = getNextArg();
1119 if (arg == null) {
1120 onHelpD2D();
1121 return 0;
1122 }
1123
1124 boolean isEnabled = "true".equals(arg.toLowerCase());
1125 try {
1126 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1127 } catch (RemoteException e) {
1128 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1129 errPw.println("Exception: " + e.getMessage());
1130 return -1;
1131 }
1132 return 0;
1133 }
1134
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001135 // ims set-ims-service
1136 private int handleImsSetServiceCommand() {
1137 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001138 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001139 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001140 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001141
1142 String opt;
1143 while ((opt = getNextOption()) != null) {
1144 switch (opt) {
1145 case "-s": {
1146 try {
1147 slotId = Integer.parseInt(getNextArgRequired());
1148 } catch (NumberFormatException e) {
1149 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1150 return -1;
1151 }
1152 break;
1153 }
1154 case "-c": {
1155 isCarrierService = true;
1156 break;
1157 }
1158 case "-d": {
1159 isCarrierService = false;
1160 break;
1161 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001162 case "-f": {
1163 String featureString = getNextArgRequired();
1164 String[] features = featureString.split(",");
1165 for (int i = 0; i < features.length; i++) {
1166 try {
1167 Integer result = Integer.parseInt(features[i]);
1168 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1169 || result >= ImsFeature.FEATURE_MAX) {
1170 errPw.println("ims set-ims-service -f " + result
1171 + " is an invalid feature.");
1172 return -1;
1173 }
1174 featuresList.add(result);
1175 } catch (NumberFormatException e) {
1176 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1177 + " as an integer.");
1178 return -1;
1179 }
1180 }
1181 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001182 }
1183 }
1184 // Mandatory param, either -c or -d
1185 if (isCarrierService == null) {
1186 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1187 return -1;
1188 }
1189
1190 String packageName = getNextArg();
1191
1192 try {
1193 if (packageName == null) {
1194 packageName = "";
1195 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001196 int[] featureArray = new int[featuresList.size()];
1197 for (int i = 0; i < featuresList.size(); i++) {
1198 featureArray[i] = featuresList.get(i);
1199 }
1200 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1201 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001202 if (VDBG) {
1203 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001204 + (isCarrierService ? "-c " : "-d ")
1205 + "-f " + featuresList + " "
1206 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001207 }
1208 getOutPrintWriter().println(result);
1209 } catch (RemoteException e) {
1210 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001211 + (isCarrierService ? "-c " : "-d ")
1212 + "-f " + featuresList + " "
1213 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001214 errPw.println("Exception: " + e.getMessage());
1215 return -1;
1216 }
1217 return 0;
1218 }
1219
Brad Ebinger999d3302020-11-25 14:31:39 -08001220 // ims clear-ims-service-override
1221 private int handleImsClearCarrierServiceCommand() {
1222 PrintWriter errPw = getErrPrintWriter();
1223 int slotId = getDefaultSlot();
1224
1225 String opt;
1226 while ((opt = getNextOption()) != null) {
1227 switch (opt) {
1228 case "-s": {
1229 try {
1230 slotId = Integer.parseInt(getNextArgRequired());
1231 } catch (NumberFormatException e) {
1232 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1233 return -1;
1234 }
1235 break;
1236 }
1237 }
1238 }
1239
1240 try {
1241 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1242 if (VDBG) {
1243 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1244 + ", result=" + result);
1245 }
1246 getOutPrintWriter().println(result);
1247 } catch (RemoteException e) {
1248 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1249 + ", error" + e.getMessage());
1250 errPw.println("Exception: " + e.getMessage());
1251 return -1;
1252 }
1253 return 0;
1254 }
1255
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001256 // ims get-ims-service
1257 private int handleImsGetServiceCommand() {
1258 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001259 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001260 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001261 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001262
1263 String opt;
1264 while ((opt = getNextOption()) != null) {
1265 switch (opt) {
1266 case "-s": {
1267 try {
1268 slotId = Integer.parseInt(getNextArgRequired());
1269 } catch (NumberFormatException e) {
1270 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1271 return -1;
1272 }
1273 break;
1274 }
1275 case "-c": {
1276 isCarrierService = true;
1277 break;
1278 }
1279 case "-d": {
1280 isCarrierService = false;
1281 break;
1282 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001283 case "-f": {
1284 try {
1285 featureType = Integer.parseInt(getNextArg());
1286 } catch (NumberFormatException e) {
1287 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1288 return -1;
1289 }
1290 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1291 || featureType >= ImsFeature.FEATURE_MAX) {
1292 errPw.println("ims get-ims-service -f invalid feature.");
1293 return -1;
1294 }
1295 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001296 }
1297 }
1298 // Mandatory param, either -c or -d
1299 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001300 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001301 return -1;
1302 }
1303
1304 String result;
1305 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001306 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001307 } catch (RemoteException e) {
1308 return -1;
1309 }
1310 if (VDBG) {
1311 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001312 + (isCarrierService ? "-c " : "-d ")
1313 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1314 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001315 }
1316 getOutPrintWriter().println(result);
1317 return 0;
1318 }
1319
1320 private int handleEnableIms() {
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("ims enable requires an integer as a SLOT_ID.");
1330 return -1;
1331 }
1332 break;
1333 }
1334 }
1335 }
1336 try {
1337 mInterface.enableIms(slotId);
1338 } catch (RemoteException e) {
1339 return -1;
1340 }
1341 if (VDBG) {
1342 Log.v(LOG_TAG, "ims enable -s " + slotId);
1343 }
1344 return 0;
1345 }
1346
1347 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001348 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001349 String opt;
1350 while ((opt = getNextOption()) != null) {
1351 switch (opt) {
1352 case "-s": {
1353 try {
1354 slotId = Integer.parseInt(getNextArgRequired());
1355 } catch (NumberFormatException e) {
1356 getErrPrintWriter().println(
1357 "ims disable requires an integer as a SLOT_ID.");
1358 return -1;
1359 }
1360 break;
1361 }
1362 }
1363 }
1364 try {
1365 mInterface.disableIms(slotId);
1366 } catch (RemoteException e) {
1367 return -1;
1368 }
1369 if (VDBG) {
1370 Log.v(LOG_TAG, "ims disable -s " + slotId);
1371 }
1372 return 0;
1373 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001374
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001375 private int handleCepChange() {
1376 Log.i(LOG_TAG, "handleCepChange");
1377 String opt = getNextArg();
1378 if (opt == null) {
1379 return -1;
1380 }
1381 boolean isCepEnabled = opt.equals("enable");
1382
1383 try {
1384 mInterface.setCepEnabled(isCepEnabled);
1385 } catch (RemoteException e) {
1386 return -1;
1387 }
1388 return 0;
1389 }
1390
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001391 private int getDefaultSlot() {
1392 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1393 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1394 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1395 // If there is no default, default to slot 0.
1396 slotId = DEFAULT_PHONE_ID;
1397 }
1398 return slotId;
1399 }
sqian2fff4a32018-11-05 14:18:37 -08001400
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001401 // Parse options related to Carrier Config Commands.
1402 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001403 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001404 CcOptionParseResult result = new CcOptionParseResult();
1405 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1406 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001407
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001408 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001409 while ((opt = getNextOption()) != null) {
1410 switch (opt) {
1411 case "-s": {
1412 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001413 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1414 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1415 errPw.println(tag + "No valid subscription found.");
1416 return null;
1417 }
1418
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001419 } catch (IllegalArgumentException e) {
1420 // Missing slot id
1421 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001422 return null;
1423 }
1424 break;
1425 }
1426 case "-p": {
1427 if (allowOptionPersistent) {
1428 result.mPersistent = true;
1429 } else {
1430 errPw.println(tag + "Unexpected option " + opt);
1431 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001432 }
1433 break;
1434 }
1435 default: {
1436 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001437 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001438 }
1439 }
1440 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001441 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001442 }
1443
1444 private int slotStringToSubId(String tag, String slotString) {
1445 int slotId = -1;
1446 try {
1447 slotId = Integer.parseInt(slotString);
1448 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001449 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1450 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1451 }
1452
1453 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001454 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1455 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1456 }
1457
Qiong Liuf25799b2020-09-10 10:13:46 +08001458 Phone phone = PhoneFactory.getPhone(slotId);
1459 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001460 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1461 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1462 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001463 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001464 }
1465
Hall Liud892bec2018-11-30 14:51:45 -08001466 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001467 // adb can run as root or as shell, depending on whether the device is rooted.
1468 return Binder.getCallingUid() == Process.SHELL_UID
1469 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001470 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001471
1472 private int handleCcCommand() {
1473 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1474 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001475 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001476 getErrPrintWriter().println("cc: Permission denied.");
1477 return -1;
1478 }
1479
1480 String arg = getNextArg();
1481 if (arg == null) {
1482 onHelpCc();
1483 return 0;
1484 }
1485
1486 switch (arg) {
1487 case CC_GET_VALUE: {
1488 return handleCcGetValue();
1489 }
1490 case CC_SET_VALUE: {
1491 return handleCcSetValue();
1492 }
Allen Xue5522892022-03-14 21:04:49 +00001493 case CC_SET_VALUES_FROM_XML: {
1494 return handleCcSetValuesFromXml();
1495 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001496 case CC_CLEAR_VALUES: {
1497 return handleCcClearValues();
1498 }
1499 default: {
1500 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1501 }
1502 }
1503 return -1;
1504 }
1505
1506 // cc get-value
1507 private int handleCcGetValue() {
1508 PrintWriter errPw = getErrPrintWriter();
1509 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1510 String key = null;
1511
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001512 // Parse all options
Allen Xue5522892022-03-14 21:04:49 +00001513 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001514 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001515 return -1;
1516 }
1517
1518 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001519 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001520 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001521 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001522 return -1;
1523 }
1524
1525 // Get the key.
1526 key = getNextArg();
1527 if (key != null) {
1528 // A key was provided. Verify if it is a valid key
1529 if (!bundle.containsKey(key)) {
1530 errPw.println(tag + key + " is not a valid key.");
1531 return -1;
1532 }
1533
1534 // Print the carrier config value for key.
1535 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1536 } else {
1537 // No key provided. Show all values.
1538 // Iterate over a sorted list of all carrier config keys and print them.
1539 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1540 for (String k : sortedSet) {
1541 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1542 }
1543 }
1544 return 0;
1545 }
1546
1547 // cc set-value
1548 private int handleCcSetValue() {
1549 PrintWriter errPw = getErrPrintWriter();
1550 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1551
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001552 // Parse all options
Allen Xue5522892022-03-14 21:04:49 +00001553 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001554 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001555 return -1;
1556 }
1557
1558 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001559 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001560 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001561 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001562 return -1;
1563 }
1564
1565 // Get the key.
1566 String key = getNextArg();
1567 if (key == null || key.equals("")) {
1568 errPw.println(tag + "KEY is missing");
1569 return -1;
1570 }
1571
1572 // Verify if the key is valid
1573 if (!originalValues.containsKey(key)) {
1574 errPw.println(tag + key + " is not a valid key.");
1575 return -1;
1576 }
1577
1578 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1579 ArrayList<String> valueList = new ArrayList<String>();
1580 while (peekNextArg() != null) {
1581 valueList.add(getNextArg());
1582 }
1583
1584 // Find the type of the carrier config value
1585 CcType type = getType(tag, key, originalValues);
1586 if (type == CcType.UNKNOWN) {
1587 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1588 return -1;
1589 }
Allen Xue5522892022-03-14 21:04:49 +00001590 if (type == CcType.PERSISTABLE_BUNDLE) {
1591 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1592 + "Use set-values-from-xml instead.");
1593 return -1;
1594 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001595
1596 // Create an override bundle containing the key and value that should be overriden.
1597 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1598 if (overrideBundle == null) {
1599 return -1;
1600 }
1601
1602 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001603 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001604
1605 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001606 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001607 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001608 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001609 return -1;
1610 }
1611
1612 // Print the original and new value.
1613 String originalValueString = ccValueToString(key, type, originalValues);
1614 String newValueString = ccValueToString(key, type, newValues);
1615 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1616 getOutPrintWriter().println("New value: \n" + newValueString);
1617
1618 return 0;
1619 }
1620
Allen Xue5522892022-03-14 21:04:49 +00001621 // cc set-values-from-xml
1622 private int handleCcSetValuesFromXml() {
1623 PrintWriter errPw = getErrPrintWriter();
1624 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1625
1626 // Parse all options
1627 CcOptionParseResult options = parseCcOptions(tag, false);
1628 if (options == null) {
1629 return -1;
1630 }
1631
1632 // Get bundle containing all current carrier configuration values.
1633 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1634 if (originalValues == null) {
1635 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1636 return -1;
1637 }
1638
1639 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1640 if (overrideBundle == null) {
1641 return -1;
1642 }
1643
1644 // Verify all values are valid types
1645 for (String key : overrideBundle.keySet()) {
1646 CcType type = getType(tag, key, originalValues);
1647 if (type == CcType.UNKNOWN) {
1648 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1649 return -1;
1650 }
1651 }
1652
1653 // Override the value
1654 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1655
1656 // Find bundle containing all new carrier configuration values after the override.
1657 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1658 if (newValues == null) {
1659 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1660 return -1;
1661 }
1662
1663 // Print the original and new values
1664 overrideBundle.keySet().forEach(key -> {
1665 CcType type = getType(tag, key, originalValues);
1666 String originalValueString = ccValueToString(key, type, originalValues);
1667 String newValueString = ccValueToString(key, type, newValues);
1668 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1669 getOutPrintWriter().println("New value: \n" + newValueString);
1670 });
1671
1672 return 0;
1673 }
1674
1675 private PersistableBundle readPersistableBundleFromXml(String tag) {
1676 PersistableBundle subIdBundles;
1677 try {
1678 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1679 } catch (IOException | RuntimeException e) {
1680 PrintWriter errPw = getErrPrintWriter();
1681 errPw.println(tag + e);
1682 return null;
1683 }
1684
1685 return subIdBundles;
1686 }
1687
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001688 // cc clear-values
1689 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001690 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1691
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001692 // Parse all options
Allen Xue5522892022-03-14 21:04:49 +00001693 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001694 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001695 return -1;
1696 }
1697
1698 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001699 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001700 getOutPrintWriter()
1701 .println("All previously set carrier config override values has been cleared");
1702 return 0;
1703 }
1704
1705 private CcType getType(String tag, String key, PersistableBundle bundle) {
1706 // Find the type by checking the type of the current value stored in the bundle.
1707 Object value = bundle.get(key);
1708
1709 if (CC_TYPE_MAP.containsKey(key)) {
1710 return CC_TYPE_MAP.get(key);
1711 } else if (value != null) {
1712 if (value instanceof Boolean) {
1713 return CcType.BOOLEAN;
Allen Xue5522892022-03-14 21:04:49 +00001714 }
1715 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001716 return CcType.DOUBLE;
Allen Xue5522892022-03-14 21:04:49 +00001717 }
1718 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001719 return CcType.DOUBLE_ARRAY;
Allen Xue5522892022-03-14 21:04:49 +00001720 }
1721 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001722 return CcType.INT;
Allen Xue5522892022-03-14 21:04:49 +00001723 }
1724 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001725 return CcType.INT_ARRAY;
Allen Xue5522892022-03-14 21:04:49 +00001726 }
1727 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001728 return CcType.LONG;
Allen Xue5522892022-03-14 21:04:49 +00001729 }
1730 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001731 return CcType.LONG_ARRAY;
Allen Xue5522892022-03-14 21:04:49 +00001732 }
1733 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001734 return CcType.STRING;
Allen Xue5522892022-03-14 21:04:49 +00001735 }
1736 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001737 return CcType.STRING_ARRAY;
1738 }
Allen Xue5522892022-03-14 21:04:49 +00001739 if (value instanceof PersistableBundle) {
1740 return CcType.PERSISTABLE_BUNDLE;
1741 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001742 } else {
1743 // Current value was null and can therefore not be used in order to find the type.
1744 // Check the name of the key to infer the type. This check is not needed for primitive
1745 // data types (boolean, double, int and long), since they can not be null.
1746 if (key.endsWith("double_array")) {
1747 return CcType.DOUBLE_ARRAY;
1748 }
1749 if (key.endsWith("int_array")) {
1750 return CcType.INT_ARRAY;
1751 }
1752 if (key.endsWith("long_array")) {
1753 return CcType.LONG_ARRAY;
1754 }
1755 if (key.endsWith("string")) {
1756 return CcType.STRING;
1757 }
1758 if (key.endsWith("string_array") || key.endsWith("strings")) {
1759 return CcType.STRING_ARRAY;
1760 }
Allen Xue5522892022-03-14 21:04:49 +00001761 if (key.endsWith("bundle")) {
1762 return CcType.PERSISTABLE_BUNDLE;
1763 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001764 }
1765
1766 // Not possible to infer the type by looking at the current value or the key.
1767 PrintWriter errPw = getErrPrintWriter();
1768 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1769 return CcType.UNKNOWN;
1770 }
1771
1772 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1773 String result;
1774 StringBuilder valueString = new StringBuilder();
1775 String typeString = type.toString();
1776 Object value = bundle.get(key);
1777
1778 if (value == null) {
1779 valueString.append("null");
1780 } else {
1781 switch (type) {
1782 case DOUBLE_ARRAY: {
1783 // Format the string representation of the int array as value1 value2......
1784 double[] valueArray = (double[]) value;
1785 for (int i = 0; i < valueArray.length; i++) {
1786 if (i != 0) {
1787 valueString.append(" ");
1788 }
1789 valueString.append(valueArray[i]);
1790 }
1791 break;
1792 }
1793 case INT_ARRAY: {
1794 // Format the string representation of the int array as value1 value2......
1795 int[] valueArray = (int[]) value;
1796 for (int i = 0; i < valueArray.length; i++) {
1797 if (i != 0) {
1798 valueString.append(" ");
1799 }
1800 valueString.append(valueArray[i]);
1801 }
1802 break;
1803 }
1804 case LONG_ARRAY: {
1805 // Format the string representation of the int array as value1 value2......
1806 long[] valueArray = (long[]) value;
1807 for (int i = 0; i < valueArray.length; i++) {
1808 if (i != 0) {
1809 valueString.append(" ");
1810 }
1811 valueString.append(valueArray[i]);
1812 }
1813 break;
1814 }
1815 case STRING: {
1816 valueString.append("\"" + value.toString() + "\"");
1817 break;
1818 }
1819 case STRING_ARRAY: {
1820 // Format the string representation of the string array as "value1" "value2"....
1821 String[] valueArray = (String[]) value;
1822 for (int i = 0; i < valueArray.length; i++) {
1823 if (i != 0) {
1824 valueString.append(" ");
1825 }
1826 if (valueArray[i] != null) {
1827 valueString.append("\"" + valueArray[i] + "\"");
1828 } else {
1829 valueString.append("null");
1830 }
1831 }
1832 break;
1833 }
1834 default: {
1835 valueString.append(value.toString());
1836 }
1837 }
1838 }
1839 return String.format("%-70s %-15s %s", key, typeString, valueString);
1840 }
1841
1842 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1843 ArrayList<String> valueList) {
1844 PrintWriter errPw = getErrPrintWriter();
1845 PersistableBundle bundle = new PersistableBundle();
1846
1847 // First verify that a valid number of values has been provided for the type.
1848 switch (type) {
1849 case BOOLEAN:
1850 case DOUBLE:
1851 case INT:
1852 case LONG: {
1853 if (valueList.size() != 1) {
1854 errPw.println(tag + "Expected 1 value for type " + type
1855 + ". Found: " + valueList.size());
1856 return null;
1857 }
1858 break;
1859 }
1860 case STRING: {
1861 if (valueList.size() > 1) {
1862 errPw.println(tag + "Expected 0 or 1 values for type " + type
1863 + ". Found: " + valueList.size());
1864 return null;
1865 }
1866 break;
1867 }
1868 }
1869
1870 // Parse the value according to type and add it to the Bundle.
1871 switch (type) {
1872 case BOOLEAN: {
1873 if ("true".equalsIgnoreCase(valueList.get(0))) {
1874 bundle.putBoolean(key, true);
1875 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1876 bundle.putBoolean(key, false);
1877 } else {
1878 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1879 return null;
1880 }
1881 break;
1882 }
1883 case DOUBLE: {
1884 try {
1885 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1886 } catch (NumberFormatException nfe) {
1887 // Not a valid double
1888 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1889 return null;
1890 }
1891 break;
1892 }
1893 case DOUBLE_ARRAY: {
1894 double[] valueDoubleArray = null;
1895 if (valueList.size() > 0) {
1896 valueDoubleArray = new double[valueList.size()];
1897 for (int i = 0; i < valueList.size(); i++) {
1898 try {
1899 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1900 } catch (NumberFormatException nfe) {
1901 // Not a valid double
1902 errPw.println(
1903 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1904 return null;
1905 }
1906 }
1907 }
1908 bundle.putDoubleArray(key, valueDoubleArray);
1909 break;
1910 }
1911 case INT: {
1912 try {
1913 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1914 } catch (NumberFormatException nfe) {
1915 // Not a valid integer
1916 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1917 return null;
1918 }
1919 break;
1920 }
1921 case INT_ARRAY: {
1922 int[] valueIntArray = null;
1923 if (valueList.size() > 0) {
1924 valueIntArray = new int[valueList.size()];
1925 for (int i = 0; i < valueList.size(); i++) {
1926 try {
1927 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1928 } catch (NumberFormatException nfe) {
1929 // Not a valid integer
1930 errPw.println(tag
1931 + "Unable to parse " + valueList.get(i) + " as an integer.");
1932 return null;
1933 }
1934 }
1935 }
1936 bundle.putIntArray(key, valueIntArray);
1937 break;
1938 }
1939 case LONG: {
1940 try {
1941 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1942 } catch (NumberFormatException nfe) {
1943 // Not a valid long
1944 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1945 return null;
1946 }
1947 break;
1948 }
1949 case LONG_ARRAY: {
1950 long[] valueLongArray = null;
1951 if (valueList.size() > 0) {
1952 valueLongArray = new long[valueList.size()];
1953 for (int i = 0; i < valueList.size(); i++) {
1954 try {
1955 valueLongArray[i] = Long.parseLong(valueList.get(i));
1956 } catch (NumberFormatException nfe) {
1957 // Not a valid long
1958 errPw.println(
1959 tag + "Unable to parse " + valueList.get(i) + " as a long");
1960 return null;
1961 }
1962 }
1963 }
1964 bundle.putLongArray(key, valueLongArray);
1965 break;
1966 }
1967 case STRING: {
1968 String value = null;
1969 if (valueList.size() > 0) {
1970 value = valueList.get(0);
1971 }
1972 bundle.putString(key, value);
1973 break;
1974 }
1975 case STRING_ARRAY: {
1976 String[] valueStringArray = null;
1977 if (valueList.size() > 0) {
1978 valueStringArray = new String[valueList.size()];
1979 valueList.toArray(valueStringArray);
1980 }
1981 bundle.putStringArray(key, valueStringArray);
1982 break;
1983 }
1984 }
1985 return bundle;
1986 }
Shuo Qian489d9282020-07-09 11:30:03 -07001987
1988 private int handleEndBlockSuppressionCommand() {
1989 if (!checkShellUid()) {
1990 return -1;
1991 }
1992
1993 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1994 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1995 }
1996 return 0;
1997 }
Hui Wang641e81c2020-10-12 12:14:23 -07001998
Michele Berionne54af4632020-12-28 20:23:16 +00001999 private int handleRestartModemCommand() {
2000 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2001 // non user build.
2002 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2003 getErrPrintWriter().println("RestartModem: Permission denied.");
2004 return -1;
2005 }
2006
2007 boolean result = TelephonyManager.getDefault().rebootRadio();
2008 getOutPrintWriter().println(result);
2009
2010 return result ? 0 : -1;
2011 }
2012
Michele Berionne5e411512020-11-13 02:36:59 +00002013 private int handleUnattendedReboot() {
2014 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2015 // non user build.
2016 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2017 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2018 return -1;
2019 }
2020
2021 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2022 getOutPrintWriter().println("result: " + result);
2023
2024 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2025 }
2026
Hui Wang641e81c2020-10-12 12:14:23 -07002027 private int handleGbaCommand() {
2028 String arg = getNextArg();
2029 if (arg == null) {
2030 onHelpGba();
2031 return 0;
2032 }
2033
2034 switch (arg) {
2035 case GBA_SET_SERVICE: {
2036 return handleGbaSetServiceCommand();
2037 }
2038 case GBA_GET_SERVICE: {
2039 return handleGbaGetServiceCommand();
2040 }
2041 case GBA_SET_RELEASE_TIME: {
2042 return handleGbaSetReleaseCommand();
2043 }
2044 case GBA_GET_RELEASE_TIME: {
2045 return handleGbaGetReleaseCommand();
2046 }
2047 }
2048
2049 return -1;
2050 }
2051
2052 private int getSubId(String cmd) {
2053 int slotId = getDefaultSlot();
2054 String opt = getNextOption();
2055 if (opt != null && opt.equals("-s")) {
2056 try {
2057 slotId = Integer.parseInt(getNextArgRequired());
2058 } catch (NumberFormatException e) {
2059 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2060 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2061 }
2062 }
2063 int[] subIds = SubscriptionManager.getSubId(slotId);
2064 return subIds[0];
2065 }
2066
2067 private int handleGbaSetServiceCommand() {
2068 int subId = getSubId("gba set-service");
2069 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2070 return -1;
2071 }
2072
2073 String packageName = getNextArg();
2074 try {
2075 if (packageName == null) {
2076 packageName = "";
2077 }
2078 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2079 if (VDBG) {
2080 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2081 + packageName + ", result=" + result);
2082 }
2083 getOutPrintWriter().println(result);
2084 } catch (RemoteException e) {
2085 Log.w(LOG_TAG, "gba set-service " + subId + " "
2086 + packageName + ", error" + e.getMessage());
2087 getErrPrintWriter().println("Exception: " + e.getMessage());
2088 return -1;
2089 }
2090 return 0;
2091 }
2092
2093 private int handleGbaGetServiceCommand() {
2094 String result;
2095
2096 int subId = getSubId("gba get-service");
2097 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2098 return -1;
2099 }
2100
2101 try {
2102 result = mInterface.getBoundGbaService(subId);
2103 } catch (RemoteException e) {
2104 return -1;
2105 }
2106 if (VDBG) {
2107 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2108 }
2109 getOutPrintWriter().println(result);
2110 return 0;
2111 }
2112
2113 private int handleGbaSetReleaseCommand() {
2114 //the release time value could be -1
2115 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2116 : SubscriptionManager.getDefaultSubscriptionId();
2117 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2118 return -1;
2119 }
2120
2121 String intervalStr = getNextArg();
2122 if (intervalStr == null) {
2123 return -1;
2124 }
2125
2126 try {
2127 int interval = Integer.parseInt(intervalStr);
2128 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2129 if (VDBG) {
2130 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2131 + intervalStr + ", result=" + result);
2132 }
2133 getOutPrintWriter().println(result);
2134 } catch (NumberFormatException | RemoteException e) {
2135 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2136 + intervalStr + ", error" + e.getMessage());
2137 getErrPrintWriter().println("Exception: " + e.getMessage());
2138 return -1;
2139 }
2140 return 0;
2141 }
2142
2143 private int handleGbaGetReleaseCommand() {
2144 int subId = getSubId("gba get-release");
2145 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2146 return -1;
2147 }
2148
2149 int result = 0;
2150 try {
2151 result = mInterface.getGbaReleaseTime(subId);
2152 } catch (RemoteException e) {
2153 return -1;
2154 }
2155 if (VDBG) {
2156 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2157 }
2158 getOutPrintWriter().println(result);
2159 return 0;
2160 }
Hui Wang761a6682020-10-31 05:12:53 +00002161
2162 private int handleSingleRegistrationConfigCommand() {
2163 String arg = getNextArg();
2164 if (arg == null) {
2165 onHelpSrc();
2166 return 0;
2167 }
2168
2169 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002170 case SRC_SET_TEST_ENABLED: {
2171 return handleSrcSetTestEnabledCommand();
2172 }
2173 case SRC_GET_TEST_ENABLED: {
2174 return handleSrcGetTestEnabledCommand();
2175 }
Hui Wang761a6682020-10-31 05:12:53 +00002176 case SRC_SET_DEVICE_ENABLED: {
2177 return handleSrcSetDeviceEnabledCommand();
2178 }
2179 case SRC_GET_DEVICE_ENABLED: {
2180 return handleSrcGetDeviceEnabledCommand();
2181 }
2182 case SRC_SET_CARRIER_ENABLED: {
2183 return handleSrcSetCarrierEnabledCommand();
2184 }
2185 case SRC_GET_CARRIER_ENABLED: {
2186 return handleSrcGetCarrierEnabledCommand();
2187 }
Hui Wangb647abe2021-02-26 09:33:38 -08002188 case SRC_SET_FEATURE_ENABLED: {
2189 return handleSrcSetFeatureValidationCommand();
2190 }
2191 case SRC_GET_FEATURE_ENABLED: {
2192 return handleSrcGetFeatureValidationCommand();
2193 }
Hui Wang761a6682020-10-31 05:12:53 +00002194 }
2195
2196 return -1;
2197 }
2198
James.cf Linbcdf8b32021-01-14 16:44:13 +08002199 private int handleRcsUceCommand() {
2200 String arg = getNextArg();
2201 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002202 onHelpUce();
2203 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002204 }
2205
2206 switch (arg) {
2207 case UCE_REMOVE_EAB_CONTACT:
2208 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002209 case UCE_GET_EAB_CONTACT:
2210 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002211 case UCE_GET_EAB_CAPABILITY:
2212 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002213 case UCE_GET_DEVICE_ENABLED:
2214 return handleUceGetDeviceEnabledCommand();
2215 case UCE_SET_DEVICE_ENABLED:
2216 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002217 case UCE_OVERRIDE_PUBLISH_CAPS:
2218 return handleUceOverridePublishCaps();
2219 case UCE_GET_LAST_PIDF_XML:
2220 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002221 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2222 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002223 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2224 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002225 }
2226 return -1;
2227 }
2228
2229 private int handleRemovingEabContactCommand() {
2230 int subId = getSubId("uce remove-eab-contact");
2231 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2232 return -1;
2233 }
2234
2235 String phoneNumber = getNextArgRequired();
2236 if (TextUtils.isEmpty(phoneNumber)) {
2237 return -1;
2238 }
2239 int result = 0;
2240 try {
2241 result = mInterface.removeContactFromEab(subId, phoneNumber);
2242 } catch (RemoteException e) {
2243 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2244 getErrPrintWriter().println("Exception: " + e.getMessage());
2245 return -1;
2246 }
2247
2248 if (VDBG) {
2249 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2250 }
calvinpan293ea1b2021-02-04 17:52:13 +08002251 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002252 }
2253
calvinpane4a8a1d2021-01-25 13:51:18 +08002254 private int handleGettingEabContactCommand() {
2255 String phoneNumber = getNextArgRequired();
2256 if (TextUtils.isEmpty(phoneNumber)) {
2257 return -1;
2258 }
2259 String result = "";
2260 try {
2261 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002262 } catch (RemoteException e) {
2263 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2264 getErrPrintWriter().println("Exception: " + e.getMessage());
2265 return -1;
2266 }
2267
2268 if (VDBG) {
2269 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2270 }
calvinpan293ea1b2021-02-04 17:52:13 +08002271 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002272 return 0;
2273 }
2274
Calvin Pana1434322021-07-01 19:27:01 +08002275 private int handleGettingEabCapabilityCommand() {
2276 String phoneNumber = getNextArgRequired();
2277 if (TextUtils.isEmpty(phoneNumber)) {
2278 return -1;
2279 }
2280 String result = "";
2281 try {
2282 result = mInterface.getCapabilityFromEab(phoneNumber);
2283 } catch (RemoteException e) {
2284 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2285 getErrPrintWriter().println("Exception: " + e.getMessage());
2286 return -1;
2287 }
2288
2289 if (VDBG) {
2290 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2291 }
2292 getOutPrintWriter().println(result);
2293 return 0;
2294 }
2295
James.cf Lin4b784aa2021-01-31 03:25:15 +08002296 private int handleUceGetDeviceEnabledCommand() {
2297 boolean result = false;
2298 try {
2299 result = mInterface.getDeviceUceEnabled();
2300 } catch (RemoteException e) {
2301 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2302 return -1;
2303 }
2304 if (VDBG) {
2305 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2306 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002307 getOutPrintWriter().println(result);
2308 return 0;
2309 }
2310
James.cf Lin4b784aa2021-01-31 03:25:15 +08002311 private int handleUceSetDeviceEnabledCommand() {
2312 String enabledStr = getNextArg();
2313 if (TextUtils.isEmpty(enabledStr)) {
2314 return -1;
2315 }
2316
2317 try {
2318 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2319 mInterface.setDeviceUceEnabled(isEnabled);
2320 if (VDBG) {
2321 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2322 }
2323 } catch (NumberFormatException | RemoteException e) {
2324 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2325 getErrPrintWriter().println("Exception: " + e.getMessage());
2326 return -1;
2327 }
2328 return 0;
2329 }
2330
James.cf Line8713a42021-04-29 16:04:26 +08002331 private int handleUceRemoveRequestDisallowedStatus() {
2332 int subId = getSubId("uce remove-request-disallowed-status");
2333 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2334 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2335 return -1;
2336 }
2337 boolean result;
2338 try {
2339 result = mInterface.removeUceRequestDisallowedStatus(subId);
2340 } catch (RemoteException e) {
2341 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2342 return -1;
2343 }
2344 if (VDBG) {
2345 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2346 }
2347 getOutPrintWriter().println(result);
2348 return 0;
2349 }
2350
James.cf Lin0fc71b02021-05-25 01:37:38 +08002351 private int handleUceSetCapRequestTimeout() {
2352 int subId = getSubId("uce set-capabilities-request-timeout");
2353 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2354 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2355 return -1;
2356 }
2357 long timeoutAfterMs = Long.valueOf(getNextArg());
2358 boolean result;
2359 try {
2360 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2361 } catch (RemoteException e) {
2362 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2363 return -1;
2364 }
2365 if (VDBG) {
2366 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2367 }
2368 getOutPrintWriter().println(result);
2369 return 0;
2370 }
2371
Hui Wangbaaee6a2021-02-19 20:45:36 -08002372 private int handleSrcSetTestEnabledCommand() {
2373 String enabledStr = getNextArg();
2374 if (enabledStr == null) {
2375 return -1;
2376 }
2377
2378 try {
2379 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2380 if (VDBG) {
2381 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2382 }
2383 getOutPrintWriter().println("Done");
2384 } catch (NumberFormatException | RemoteException e) {
2385 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2386 getErrPrintWriter().println("Exception: " + e.getMessage());
2387 return -1;
2388 }
2389 return 0;
2390 }
2391
2392 private int handleSrcGetTestEnabledCommand() {
2393 boolean result = false;
2394 try {
2395 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2396 } catch (RemoteException e) {
2397 return -1;
2398 }
2399 if (VDBG) {
2400 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2401 }
2402 getOutPrintWriter().println(result);
2403 return 0;
2404 }
2405
Brad Ebinger14d467f2021-02-12 06:18:28 +00002406 private int handleUceOverridePublishCaps() {
2407 int subId = getSubId("uce override-published-caps");
2408 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2409 return -1;
2410 }
2411 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2412 String operation = getNextArgRequired();
2413 String caps = getNextArg();
2414 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2415 && !"list".equals(operation)) {
2416 getErrPrintWriter().println("Invalid operation: " + operation);
2417 return -1;
2418 }
2419
2420 // add/remove requires capabilities to be specified.
2421 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2422 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2423 + "specified");
2424 return -1;
2425 }
2426
2427 ArraySet<String> capSet = new ArraySet<>();
2428 if (!TextUtils.isEmpty(caps)) {
2429 String[] capArray = caps.split(":");
2430 for (String cap : capArray) {
2431 // Allow unknown tags to be passed in as well.
2432 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2433 }
2434 }
2435
2436 RcsContactUceCapability result = null;
2437 try {
2438 switch (operation) {
2439 case "add":
2440 result = mInterface.addUceRegistrationOverrideShell(subId,
2441 new ArrayList<>(capSet));
2442 break;
2443 case "remove":
2444 result = mInterface.removeUceRegistrationOverrideShell(subId,
2445 new ArrayList<>(capSet));
2446 break;
2447 case "clear":
2448 result = mInterface.clearUceRegistrationOverrideShell(subId);
2449 break;
2450 case "list":
2451 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2452 break;
2453 }
2454 } catch (RemoteException e) {
2455 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2456 getErrPrintWriter().println("Exception: " + e.getMessage());
2457 return -1;
2458 } catch (ServiceSpecificException sse) {
2459 // Reconstruct ImsException
2460 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2461 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2462 getErrPrintWriter().println("Exception: " + imsException);
2463 return -1;
2464 }
2465 if (result == null) {
2466 getErrPrintWriter().println("Service not available");
2467 return -1;
2468 }
2469 getOutPrintWriter().println(result);
2470 return 0;
2471 }
2472
2473 private int handleUceGetPidfXml() {
2474 int subId = getSubId("uce get-last-publish-pidf");
2475 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2476 return -1;
2477 }
2478
2479 String result;
2480 try {
2481 result = mInterface.getLastUcePidfXmlShell(subId);
2482 } catch (RemoteException e) {
2483 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2484 getErrPrintWriter().println("Exception: " + e.getMessage());
2485 return -1;
2486 } catch (ServiceSpecificException sse) {
2487 // Reconstruct ImsException
2488 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2489 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2490 getErrPrintWriter().println("Exception: " + imsException);
2491 return -1;
2492 }
2493 if (result == null) {
2494 getErrPrintWriter().println("Service not available");
2495 return -1;
2496 }
2497 getOutPrintWriter().println(result);
2498 return 0;
2499 }
2500
Hui Wang761a6682020-10-31 05:12:53 +00002501 private int handleSrcSetDeviceEnabledCommand() {
2502 String enabledStr = getNextArg();
2503 if (enabledStr == null) {
2504 return -1;
2505 }
2506
2507 try {
2508 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2509 if (VDBG) {
2510 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2511 }
2512 getOutPrintWriter().println("Done");
2513 } catch (NumberFormatException | RemoteException e) {
2514 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2515 getErrPrintWriter().println("Exception: " + e.getMessage());
2516 return -1;
2517 }
2518 return 0;
2519 }
2520
2521 private int handleSrcGetDeviceEnabledCommand() {
2522 boolean result = false;
2523 try {
2524 result = mInterface.getDeviceSingleRegistrationEnabled();
2525 } catch (RemoteException e) {
2526 return -1;
2527 }
2528 if (VDBG) {
2529 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2530 }
2531 getOutPrintWriter().println(result);
2532 return 0;
2533 }
2534
2535 private int handleSrcSetCarrierEnabledCommand() {
2536 //the release time value could be -1
2537 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2538 : SubscriptionManager.getDefaultSubscriptionId();
2539 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2540 return -1;
2541 }
2542
2543 String enabledStr = getNextArg();
2544 if (enabledStr == null) {
2545 return -1;
2546 }
2547
2548 try {
2549 boolean result =
2550 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2551 if (VDBG) {
2552 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2553 + enabledStr + ", result=" + result);
2554 }
2555 getOutPrintWriter().println(result);
2556 } catch (NumberFormatException | RemoteException e) {
2557 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2558 + enabledStr + ", error" + e.getMessage());
2559 getErrPrintWriter().println("Exception: " + e.getMessage());
2560 return -1;
2561 }
2562 return 0;
2563 }
2564
2565 private int handleSrcGetCarrierEnabledCommand() {
2566 int subId = getSubId("src get-carrier-enabled");
2567 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2568 return -1;
2569 }
2570
2571 boolean result = false;
2572 try {
2573 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2574 } catch (RemoteException e) {
2575 return -1;
2576 }
2577 if (VDBG) {
2578 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2579 }
2580 getOutPrintWriter().println(result);
2581 return 0;
2582 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002583
Hui Wangb647abe2021-02-26 09:33:38 -08002584 private int handleSrcSetFeatureValidationCommand() {
2585 //the release time value could be -1
2586 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2587 : SubscriptionManager.getDefaultSubscriptionId();
2588 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2589 return -1;
2590 }
2591
2592 String enabledStr = getNextArg();
2593 if (enabledStr == null) {
2594 return -1;
2595 }
2596
2597 try {
2598 boolean result =
2599 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2600 if (VDBG) {
2601 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2602 + enabledStr + ", result=" + result);
2603 }
2604 getOutPrintWriter().println(result);
2605 } catch (NumberFormatException | RemoteException e) {
2606 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2607 + enabledStr + ", error" + e.getMessage());
2608 getErrPrintWriter().println("Exception: " + e.getMessage());
2609 return -1;
2610 }
2611 return 0;
2612 }
2613
2614 private int handleSrcGetFeatureValidationCommand() {
2615 int subId = getSubId("src get-feature-validation");
2616 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2617 return -1;
2618 }
2619
2620 Boolean result = false;
2621 try {
2622 result = mInterface.getImsFeatureValidationOverride(subId);
2623 } catch (RemoteException e) {
2624 return -1;
2625 }
2626 if (VDBG) {
2627 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2628 }
2629 getOutPrintWriter().println(result);
2630 return 0;
2631 }
2632
2633
Hall Liuaa4211e2021-01-20 15:43:39 -08002634 private void onHelpCallComposer() {
2635 PrintWriter pw = getOutPrintWriter();
2636 pw.println("Call composer commands");
2637 pw.println(" callcomposer test-mode enable|disable|query");
2638 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2639 pw.println(" upload/download from carrier servers is disabled, and operations are");
2640 pw.println(" performed using emulated local files instead.");
2641 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2642 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2643 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002644 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2645 pw.println(" Enables or disables the user setting for call composer, as set by");
2646 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002647 }
2648
2649 private int handleCallComposerCommand() {
2650 String arg = getNextArg();
2651 if (arg == null) {
2652 onHelpCallComposer();
2653 return 0;
2654 }
2655
2656 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2657 "MODIFY_PHONE_STATE required for call composer shell cmds");
2658 switch (arg) {
2659 case CALL_COMPOSER_TEST_MODE: {
2660 String enabledStr = getNextArg();
2661 if (ENABLE.equals(enabledStr)) {
2662 CallComposerPictureManager.sTestMode = true;
2663 } else if (DISABLE.equals(enabledStr)) {
2664 CallComposerPictureManager.sTestMode = false;
2665 } else if (QUERY.equals(enabledStr)) {
2666 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2667 } else {
2668 onHelpCallComposer();
2669 return 1;
2670 }
2671 break;
2672 }
2673 case CALL_COMPOSER_SIMULATE_CALL: {
2674 int subscriptionId = Integer.valueOf(getNextArg());
2675 String uuidString = getNextArg();
2676 UUID uuid = UUID.fromString(uuidString);
2677 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2678 Binder.withCleanCallingIdentity(() -> {
2679 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2680 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2681 });
2682 try {
2683 Uri uri = storageUriFuture.get();
2684 getOutPrintWriter().println(String.valueOf(uri));
2685 } catch (Exception e) {
2686 throw new RuntimeException(e);
2687 }
2688 break;
2689 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002690 case CALL_COMPOSER_USER_SETTING: {
2691 try {
2692 int subscriptionId = Integer.valueOf(getNextArg());
2693 String enabledStr = getNextArg();
2694 if (ENABLE.equals(enabledStr)) {
2695 mInterface.setCallComposerStatus(subscriptionId,
2696 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2697 } else if (DISABLE.equals(enabledStr)) {
2698 mInterface.setCallComposerStatus(subscriptionId,
2699 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2700 } else if (QUERY.equals(enabledStr)) {
2701 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2702 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2703 } else {
2704 onHelpCallComposer();
2705 return 1;
2706 }
2707 } catch (RemoteException e) {
2708 e.printStackTrace(getOutPrintWriter());
2709 return 1;
2710 }
2711 break;
2712 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002713 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002714 return 0;
2715 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002716
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002717 private int handleHasCarrierPrivilegesCommand() {
2718 String packageName = getNextArgRequired();
2719
2720 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002721 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002722 try {
2723 hasCarrierPrivileges =
2724 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2725 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2726 } catch (RemoteException e) {
2727 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2728 getErrPrintWriter().println("Exception: " + e.getMessage());
2729 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002730 } finally {
2731 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002732 }
2733
2734 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002735 return 0;
2736 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002737
2738 private int handleAllowedNetworkTypesCommand(String command) {
2739 if (!checkShellUid()) {
2740 return -1;
2741 }
2742
2743 PrintWriter errPw = getErrPrintWriter();
2744 String tag = command + ": ";
2745 String opt;
2746 int subId = -1;
2747 Log.v(LOG_TAG, command + " start");
2748
2749 while ((opt = getNextOption()) != null) {
2750 if (opt.equals("-s")) {
2751 try {
2752 subId = slotStringToSubId(tag, getNextArgRequired());
2753 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2754 errPw.println(tag + "No valid subscription found.");
2755 return -1;
2756 }
2757 } catch (IllegalArgumentException e) {
2758 // Missing slot id
2759 errPw.println(tag + "SLOT_ID expected after -s.");
2760 return -1;
2761 }
2762 } else {
2763 errPw.println(tag + "Unknown option " + opt);
2764 return -1;
2765 }
2766 }
2767
2768 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2769 return handleGetAllowedNetworkTypesCommand(subId);
2770 }
2771 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2772 return handleSetAllowedNetworkTypesCommand(subId);
2773 }
2774 return -1;
2775 }
2776
2777 private int handleGetAllowedNetworkTypesCommand(int subId) {
2778 PrintWriter errPw = getErrPrintWriter();
2779
2780 long result = -1;
2781 try {
2782 if (mInterface != null) {
2783 result = mInterface.getAllowedNetworkTypesForReason(subId,
2784 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2785 } else {
2786 throw new IllegalStateException("telephony service is null.");
2787 }
2788 } catch (RemoteException e) {
2789 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2790 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2791 return -1;
2792 }
2793
2794 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2795 return 0;
2796 }
2797
2798 private int handleSetAllowedNetworkTypesCommand(int subId) {
2799 PrintWriter errPw = getErrPrintWriter();
2800
2801 String bitmaskString = getNextArg();
2802 if (TextUtils.isEmpty(bitmaskString)) {
2803 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2804 return -1;
2805 }
2806 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2807 if (allowedNetworkTypes < 0) {
2808 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2809 return -1;
2810 }
2811 boolean result = false;
2812 try {
2813 if (mInterface != null) {
2814 result = mInterface.setAllowedNetworkTypesForReason(subId,
2815 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2816 } else {
2817 throw new IllegalStateException("telephony service is null.");
2818 }
2819 } catch (RemoteException e) {
2820 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2821 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2822 return -1;
2823 }
2824
2825 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2826 if (result) {
2827 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2828 }
2829 getOutPrintWriter().println(resultMessage);
2830 return 0;
2831 }
2832
2833 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2834 if (TextUtils.isEmpty(bitmaskString)) {
2835 return -1;
2836 }
2837 if (VDBG) {
2838 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2839 + ", length: " + bitmaskString.length());
2840 }
2841 try {
2842 return Long.parseLong(bitmaskString, 2);
2843 } catch (NumberFormatException e) {
2844 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2845 return -1;
2846 }
2847 }
jimsun38340bf2021-10-26 15:01:23 +08002848
2849 private int handleRadioSetModemServiceCommand() {
2850 PrintWriter errPw = getErrPrintWriter();
2851 String serviceName = null;
2852
2853 String opt;
2854 while ((opt = getNextOption()) != null) {
2855 switch (opt) {
2856 case "-s": {
2857 serviceName = getNextArgRequired();
2858 break;
2859 }
2860 }
2861 }
2862
2863 try {
2864 boolean result = mInterface.setModemService(serviceName);
2865 if (VDBG) {
2866 Log.v(LOG_TAG,
2867 "RadioSetModemService " + serviceName + ", result = " + result);
2868 }
2869 getOutPrintWriter().println(result);
2870 } catch (RemoteException e) {
2871 Log.w(LOG_TAG,
2872 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2873 errPw.println("Exception: " + e.getMessage());
2874 return -1;
2875 }
2876 return 0;
2877 }
2878
2879 private int handleRadioGetModemServiceCommand() {
2880 PrintWriter errPw = getErrPrintWriter();
2881 String result;
2882
2883 try {
2884 result = mInterface.getModemService();
2885 getOutPrintWriter().println(result);
2886 } catch (RemoteException e) {
2887 errPw.println("Exception: " + e.getMessage());
2888 return -1;
2889 }
2890 if (VDBG) {
2891 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2892 }
2893 return 0;
2894 }
2895
2896 private int handleRadioCommand() {
2897 String arg = getNextArg();
2898 if (arg == null) {
2899 onHelpRadio();
2900 return 0;
2901 }
2902
2903 switch (arg) {
2904 case RADIO_SET_MODEM_SERVICE:
2905 return handleRadioSetModemServiceCommand();
2906
2907 case RADIO_GET_MODEM_SERVICE:
2908 return handleRadioGetModemServiceCommand();
2909 }
2910
2911 return -1;
2912 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002913}