blob: d23d4e4b0d1b4713eb1fd7324fea9cd64d50ae6d [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
Cole Faustc16d5292022-10-15 21:33:27 -070024import static java.util.Map.entry;
25
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010027import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080028import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080031import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000033import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070034import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070035import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010036import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070037import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000039import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070040import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080041import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000042import android.telephony.ims.ImsException;
43import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080044import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080045import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000046import android.util.ArrayMap;
47import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070049import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050
Brad Ebinger14d467f2021-02-12 06:18:28 +000051import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080053import com.android.internal.telephony.Phone;
54import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080055import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080056import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080057import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080058import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080059import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000060import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000061import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070062
Allen Xuee00f0e2022-03-14 21:04:49 +000063import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080065import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Arrays;
67import java.util.Collections;
Brad Ebinger24c29992019-12-05 13:03:21 -080068import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000069import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010070import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000071import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080073import java.util.UUID;
74import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070075
76/**
77 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
78 * permission checks have been done before onCommand was called. Make sure any commands processed
79 * here also contain the appropriate permissions checks.
80 */
81
Hall Liua1548bd2019-12-24 14:14:12 -080082public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
84 private static final String LOG_TAG = "TelephonyShellCommand";
85 // Don't commit with this true.
86 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070087 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070088
Hall Liuaa4211e2021-01-20 15:43:39 -080089 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070090 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080091 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080092 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080093 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070094 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000095 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000096 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010097 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080098 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String ENABLE = "enable";
100 private static final String DISABLE = "disable";
101 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000102 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000103 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
104 "set-carrier-service-package-override";
105 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
106 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000107 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800108
Hall Liu7135e502021-02-04 16:58:17 -0800109 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800110 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800111 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Brad Ebinger999d3302020-11-25 14:31:39 -0800113 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
114 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
115 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700116 // Used to disable or enable processing of conference event package data from the network.
117 // This is handy for testing scenarios where CEP data does not exist on a network which does
118 // support CEP data.
119 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700120
Hall Liud892bec2018-11-30 14:51:45 -0800121 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800122 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800123
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100124 private static final String CC_GET_VALUE = "get-value";
125 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000126 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private static final String CC_CLEAR_VALUES = "clear-values";
128
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000129 private static final String EUICC_SUBCOMMAND = "euicc";
130 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
131
Hui Wang641e81c2020-10-12 12:14:23 -0700132 private static final String GBA_SUBCOMMAND = "gba";
133 private static final String GBA_SET_SERVICE = "set-service";
134 private static final String GBA_GET_SERVICE = "get-service";
135 private static final String GBA_SET_RELEASE_TIME = "set-release";
136 private static final String GBA_GET_RELEASE_TIME = "get-release";
137
Hui Wang761a6682020-10-31 05:12:53 +0000138 private static final String SINGLE_REGISTATION_CONFIG = "src";
139 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
140 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
141 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
142 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800143 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
144 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800145 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
146 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000147
Tyler Gunn92479152021-01-20 16:30:10 -0800148 private static final String D2D_SUBCOMMAND = "d2d";
149 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800150 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700151 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800152
Nazanin014f41e2021-05-06 17:26:31 -0700153 private static final String BARRING_SUBCOMMAND = "barring";
154 private static final String BARRING_SEND_INFO = "send";
155
James.cf Linbcdf8b32021-01-14 16:44:13 +0800156 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800157 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800158 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800159 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800160 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
161 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000162 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
163 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800164 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
165 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800166 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
167 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800168
jimsun3b9ccac2021-10-26 15:01:23 +0800169 private static final String RADIO_SUBCOMMAND = "radio";
170 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
171 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
172
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800173 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
174 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
175
Jordan Liu0ccee222021-04-27 11:55:13 -0700176 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
177 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
178
Jack Nudelman644b91a2021-03-12 14:09:48 -0800179 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
180 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
181 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700182 private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
183 "set-satellite-service-package-name";
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700184 private static final String SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME =
185 "set-satellite-gateway-service-package-name";
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700186 private static final String SET_SATELLITE_LISTENING_TIMEOUT_DURATION =
187 "set-satellite-listening-timeout-duration";
Thomas Nguyen87dce732023-04-20 18:27:16 -0700188 private static final String SET_SATELLITE_POINTING_UI_CLASS_NAME =
189 "set-satellite-pointing-ui-class-name";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800190
Grant Menke567d48f2022-08-18 20:19:10 +0000191 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
192 + "'*', '#' or '+') needs to be specified after -a in the command ";
193
194 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
195 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
196 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
197
SongFerngWang98dd5992021-05-13 17:50:00 +0800198 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
199 "get-allowed-network-types-for-users";
200 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
201 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000202 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000203 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700204 // Take advantage of existing methods that already contain permissions checks when possible.
205 private final ITelephony mInterface;
206
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100207 private SubscriptionManager mSubscriptionManager;
208 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700209 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700210 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100211
212 private enum CcType {
213 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000214 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100215 }
216
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100217 private class CcOptionParseResult {
218 public int mSubId;
219 public boolean mPersistent;
220 }
221
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100222 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
223 // keys by looking at the end of the string which usually tells the type.
224 // For instance: "xxxx_string", "xxxx_string_array", etc.
225 // The carrier config keys in this map does not follow this convention. It is therefore not
226 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700227 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
228 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
229 CcType.STRING),
230 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
231 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
232 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
233 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
234 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
235 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
236 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
237 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
238 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
239 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
240 CcType.STRING),
241 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
242 CcType.STRING_ARRAY),
243 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
244 CcType.STRING_ARRAY),
245 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
246 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
247 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
248 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
249 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
250 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
251 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
252 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100253
Brad Ebinger14d467f2021-02-12 06:18:28 +0000254 /**
255 * Map from a shorthand string to the feature tags required in registration required in order
256 * for the RCS feature to be considered "capable".
257 */
258 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
259 static {
260 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
261 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
262 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
263 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
264 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
265 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
266 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
267 FeatureTags.FEATURE_TAG_VIDEO)));
268 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
269 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
270 map.put("call_comp",
271 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
272 map.put("call_comp_mmtel",
273 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
274 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
275 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
276 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
277 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
278 // version
279 map.put("chatbot", new ArraySet<>(Arrays.asList(
280 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
281 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
282 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
283 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000284 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000285 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
286 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
287 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
288 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
289 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000290 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000291 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
292 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
293 }
294
295
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100296 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700297 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100298 mCarrierConfigManager =
299 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
300 mSubscriptionManager = (SubscriptionManager)
301 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700302 mTelephonyRegistryManager = (TelephonyRegistryManager)
303 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700304 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700305 }
306
307 @Override
308 public int onCommand(String cmd) {
309 if (cmd == null) {
310 return handleDefaultCommands(null);
311 }
312
313 switch (cmd) {
314 case IMS_SUBCOMMAND: {
315 return handleImsCommand();
316 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800317 case RCS_UCE_COMMAND:
318 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800319 case NUMBER_VERIFICATION_SUBCOMMAND:
320 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800321 case EMERGENCY_CALLBACK_MODE:
322 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800323 case EMERGENCY_NUMBER_TEST_MODE:
324 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100325 case CARRIER_CONFIG_SUBCOMMAND: {
326 return handleCcCommand();
327 }
Shuo Qianf5125122019-12-16 17:03:07 -0800328 case DATA_TEST_MODE:
329 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700330 case END_BLOCK_SUPPRESSION:
331 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000332 case EUICC_SUBCOMMAND:
333 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700334 case GBA_SUBCOMMAND:
335 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800336 case D2D_SUBCOMMAND:
337 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700338 case BARRING_SUBCOMMAND:
339 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000340 case SINGLE_REGISTATION_CONFIG:
341 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000342 case RESTART_MODEM:
343 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800344 case CALL_COMPOSER_SUBCOMMAND:
345 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000346 case UNATTENDED_REBOOT:
347 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800348 case HAS_CARRIER_PRIVILEGES_COMMAND:
349 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800350 case THERMAL_MITIGATION_COMMAND:
351 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700352 case DISABLE_PHYSICAL_SUBSCRIPTION:
353 return handleEnablePhysicalSubscription(false);
354 case ENABLE_PHYSICAL_SUBSCRIPTION:
355 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800356 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
357 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
358 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000359 case GET_IMEI:
360 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000361 case GET_SIM_SLOTS_MAPPING:
362 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800363 case RADIO_SUBCOMMAND:
364 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000365 case CARRIER_RESTRICTION_STATUS_TEST:
366 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000367 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
368 return setCarrierServicePackageOverride();
369 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
370 return clearCarrierServicePackageOverride();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700371 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
372 return handleSetSatelliteServicePackageNameCommand();
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700373 case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
374 return handleSetSatelliteGatewayServicePackageNameCommand();
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700375 case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
376 return handleSetSatelliteListeningTimeoutDuration();
Thomas Nguyen87dce732023-04-20 18:27:16 -0700377 case SET_SATELLITE_POINTING_UI_CLASS_NAME:
378 return handleSetSatellitePointingUiClassNameCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700379 default: {
380 return handleDefaultCommands(cmd);
381 }
382 }
383 }
384
385 @Override
386 public void onHelp() {
387 PrintWriter pw = getOutPrintWriter();
388 pw.println("Telephony Commands:");
389 pw.println(" help");
390 pw.println(" Print this help text.");
391 pw.println(" ims");
392 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800393 pw.println(" uce");
394 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800395 pw.println(" emergency-number-test-mode");
396 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700397 pw.println(" end-block-suppression");
398 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800399 pw.println(" data");
400 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100401 pw.println(" cc");
402 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700403 pw.println(" gba");
404 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000405 pw.println(" src");
406 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000407 pw.println(" restart-modem");
408 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000409 pw.println(" unattended-reboot");
410 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800411 pw.println(" has-carrier-privileges [package]");
412 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800413 pw.println(" get-allowed-network-types-for-users");
414 pw.println(" Get the Allowed Network Types.");
415 pw.println(" set-allowed-network-types-for-users");
416 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800417 pw.println(" radio");
418 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700419 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800420 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800421 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700422 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800423 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100424 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700425 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000426 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800427 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700428 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800429 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800430 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000431 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700432 onHelpSatellite();
Tyler Gunn92479152021-01-20 16:30:10 -0800433 }
434
435 private void onHelpD2D() {
436 PrintWriter pw = getOutPrintWriter();
437 pw.println("D2D Comms Commands:");
438 pw.println(" d2d send TYPE VALUE");
439 pw.println(" Sends a D2D message of specified type and value.");
440 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
441 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
442 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
443 MESSAGE_CALL_AUDIO_CODEC));
444 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
445 + Communicator.messageToString(
446 MESSAGE_DEVICE_BATTERY_STATE));
447 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
448 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800449 pw.println(" d2d transport TYPE");
450 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
451 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700452 pw.println(" d2d set-device-support true/default");
453 pw.println(" true - forces device support to be enabled for D2D.");
454 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
455 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700456 }
457
Nazanin014f41e2021-05-06 17:26:31 -0700458 private void onHelpBarring() {
459 PrintWriter pw = getOutPrintWriter();
460 pw.println("Barring Commands:");
461 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
462 + " -t CONDITIONAL_BARRING_TIME_SECS");
463 pw.println(" Notifies of a barring info change for the specified slot id.");
464 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
465 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
466 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
467 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
468 }
469
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700470 private void onHelpIms() {
471 PrintWriter pw = getOutPrintWriter();
472 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800473 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700474 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
475 pw.println(" ImsService. Options are:");
476 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
477 pw.println(" is specified, it will choose the default voice SIM slot.");
478 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
479 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800480 pw.println(" -f: Set the feature that this override if for, if no option is");
481 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700482 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
483 pw.println(" Gets the package name of the currently defined ImsService.");
484 pw.println(" Options are:");
485 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
486 pw.println(" is specified, it will choose the default voice SIM slot.");
487 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000488 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800489 pw.println(" -f: The feature type that the query will be requested for. If none is");
490 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800491 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
492 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
493 pw.println(" configuration overrides. Options are:");
494 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
495 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700496 pw.println(" ims enable [-s SLOT_ID]");
497 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
498 pw.println(" if none is specified.");
499 pw.println(" ims disable [-s SLOT_ID]");
500 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
501 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700502 pw.println(" ims conference-event-package [enable/disable]");
503 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700504 }
505
James.cf Linbcdf8b32021-01-14 16:44:13 +0800506 private void onHelpUce() {
507 PrintWriter pw = getOutPrintWriter();
508 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800509 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
510 pw.println(" Get the EAB contacts from the EAB database.");
511 pw.println(" Options are:");
512 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
513 pw.println(" Expected output format :");
514 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800515 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
516 pw.println(" Remove the EAB contacts from the EAB database.");
517 pw.println(" Options are:");
518 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
519 pw.println(" is specified, it will choose the default voice SIM slot.");
520 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800521 pw.println(" uce get-device-enabled");
522 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
523 pw.println(" uce set-device-enabled true|false");
524 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
525 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000526 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
527 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
528 pw.println(" Options are:");
529 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
530 pw.println(" is specified, it will choose the default voice SIM slot.");
531 pw.println(" add [CAPABILITY]: add a new capability");
532 pw.println(" remove [CAPABILITY]: remove a capability");
533 pw.println(" clear: clear all capability overrides");
534 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
535 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
536 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
537 pw.println(" chatbot_sa, chatbot_role] as well as full length");
538 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
539 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
540 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
541 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800542 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
543 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800544 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
545 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800546 }
547
Hall Liud892bec2018-11-30 14:51:45 -0800548 private void onHelpNumberVerification() {
549 PrintWriter pw = getOutPrintWriter();
550 pw.println("Number verification commands");
551 pw.println(" numverify override-package PACKAGE_NAME;");
552 pw.println(" Set the authorized package for number verification.");
553 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800554 pw.println(" numverify fake-call NUMBER;");
555 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
556 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800557 }
558
Jack Nudelman644b91a2021-03-12 14:09:48 -0800559 private void onHelpThermalMitigation() {
560 PrintWriter pw = getOutPrintWriter();
561 pw.println("Thermal mitigation commands");
562 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
563 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
564 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
565 pw.println(" Remove the package from one of the authorized packages for thermal "
566 + "mitigation.");
567 }
568
Jordan Liu0ccee222021-04-27 11:55:13 -0700569 private void onHelpDisableOrEnablePhysicalSubscription() {
570 PrintWriter pw = getOutPrintWriter();
571 pw.println("Disable or enable a physical subscription");
572 pw.println(" disable-physical-subscription SUB_ID");
573 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
574 pw.println(" enable-physical-subscription SUB_ID");
575 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
576 }
577
Shuo Qianf5125122019-12-16 17:03:07 -0800578 private void onHelpDataTestMode() {
579 PrintWriter pw = getOutPrintWriter();
580 pw.println("Mobile Data Test Mode Commands:");
581 pw.println(" data enable: enable mobile data connectivity");
582 pw.println(" data disable: disable mobile data connectivity");
583 }
584
sqian9d4df8b2019-01-15 18:32:07 -0800585 private void onHelpEmergencyNumber() {
586 PrintWriter pw = getOutPrintWriter();
587 pw.println("Emergency Number Test Mode Commands:");
588 pw.println(" emergency-number-test-mode ");
589 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
590 + " the test mode");
591 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700592 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800593 pw.println(" -c: clear the emergency number list in the test mode.");
594 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700595 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800596 pw.println(" -p: get the full emergency number list in the test mode.");
597 }
598
Shuo Qian489d9282020-07-09 11:30:03 -0700599 private void onHelpEndBlockSupperssion() {
600 PrintWriter pw = getOutPrintWriter();
601 pw.println("End Block Suppression command:");
602 pw.println(" end-block-suppression: disable suppressing blocking by contact");
603 pw.println(" with emergency services.");
604 }
605
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100606 private void onHelpCc() {
607 PrintWriter pw = getOutPrintWriter();
608 pw.println("Carrier Config Commands:");
609 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
610 pw.println(" Print carrier config values.");
611 pw.println(" Options are:");
612 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
613 pw.println(" is specified, it will choose the default voice SIM slot.");
614 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
615 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100616 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100617 pw.println(" Set carrier config KEY to NEW_VALUE.");
618 pw.println(" Options are:");
619 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
620 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100621 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100622 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
623 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
624 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
625 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000626 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
627 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
628 pw.println(" provided through standard input and follow CarrierConfig XML format.");
629 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
630 pw.println(" Options are:");
631 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
632 pw.println(" is specified, it will choose the default voice SIM slot.");
633 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100634 pw.println(" cc clear-values [-s SLOT_ID]");
635 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000636 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100637 pw.println(" Options are:");
638 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
639 pw.println(" is specified, it will choose the default voice SIM slot.");
640 }
641
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000642 private void onHelpEuicc() {
643 PrintWriter pw = getOutPrintWriter();
644 pw.println("Euicc Commands:");
645 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
646 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
647 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
648 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
649 }
650
Hui Wang641e81c2020-10-12 12:14:23 -0700651 private void onHelpGba() {
652 PrintWriter pw = getOutPrintWriter();
653 pw.println("Gba Commands:");
654 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
655 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
656 pw.println(" Options are:");
657 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
658 pw.println(" is specified, it will choose the default voice SIM slot.");
659 pw.println(" gba get-service [-s SLOT_ID]");
660 pw.println(" Gets the package name of the currently defined GbaService.");
661 pw.println(" Options are:");
662 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
663 pw.println(" is specified, it will choose the default voice SIM slot.");
664 pw.println(" gba set-release [-s SLOT_ID] n");
665 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
666 pw.println(" Do not release/unbind if n is -1.");
667 pw.println(" Options are:");
668 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
669 pw.println(" is specified, it will choose the default voice SIM slot.");
670 pw.println(" gba get-release [-s SLOT_ID]");
671 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
672 pw.println(" Options are:");
673 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
674 pw.println(" is specified, it will choose the default voice SIM slot.");
675 }
676
Hui Wang761a6682020-10-31 05:12:53 +0000677 private void onHelpSrc() {
678 PrintWriter pw = getOutPrintWriter();
679 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800680 pw.println(" src set-test-enabled true|false");
681 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
682 pw.println(" The value could be true, false, or null(undefined).");
683 pw.println(" src get-test-enabled");
684 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000685 pw.println(" src set-device-enabled true|false|null");
686 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
687 pw.println(" The value could be true, false, or null(undefined).");
688 pw.println(" src get-device-enabled");
689 pw.println(" Gets the device config for RCS VoLTE single registration.");
690 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
691 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
692 pw.println(" The value could be true, false, or null(undefined).");
693 pw.println(" Options are:");
694 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
695 pw.println(" is specified, it will choose the default voice SIM slot.");
696 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
697 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
698 pw.println(" Options are:");
699 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
700 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800701 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
702 pw.println(" Sets ims feature validation result.");
703 pw.println(" The value could be true, false, or null(undefined).");
704 pw.println(" Options are:");
705 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
706 pw.println(" is specified, it will choose the default voice SIM slot.");
707 pw.println(" src get-feature-validation [-s SLOT_ID]");
708 pw.println(" Gets ims feature validation override value.");
709 pw.println(" Options are:");
710 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
711 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000712 }
713
SongFerngWang98dd5992021-05-13 17:50:00 +0800714 private void onHelpAllowedNetworkTypes() {
715 PrintWriter pw = getOutPrintWriter();
716 pw.println("Allowed Network Types Commands:");
717 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
718 pw.println(" Print allowed network types value.");
719 pw.println(" Options are:");
720 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
721 pw.println(" option is specified, it will choose the default voice SIM slot.");
722 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
723 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
724 pw.println(" Options are:");
725 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
726 pw.println(" option is specified, it will choose the default voice SIM slot.");
727 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
728 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
729 pw.println(" at TelephonyManager.java");
730 pw.println(" For example:");
731 pw.println(" NR only : 10000000000000000000");
732 pw.println(" NR|LTE : 11000001000000000000");
733 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
734 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
735 pw.println(" LTE only : 01000001000000000000");
736 }
737
jimsun3b9ccac2021-10-26 15:01:23 +0800738 private void onHelpRadio() {
739 PrintWriter pw = getOutPrintWriter();
740 pw.println("Radio Commands:");
741 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
742 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
743 pw.println(" to be the bound. Options are:");
744 pw.println(" -s: the service name that the modem service should be bound for.");
745 pw.println(" If no option is specified, it will bind to the default.");
746 pw.println(" radio get-modem-service");
747 pw.println(" Gets the service name of the currently defined modem service.");
748 pw.println(" If it is binding to default, 'default' returns.");
749 pw.println(" If it doesn't bind to any modem service for some reasons,");
750 pw.println(" the result would be 'unknown'.");
751 }
752
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700753 private void onHelpSatellite() {
754 PrintWriter pw = getOutPrintWriter();
755 pw.println("Satellite Commands:");
756 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
757 pw.println(" Sets the package name of satellite service defined in");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700758 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700759 pw.println(" -s: the satellite service package name that Telephony will bind to.");
760 pw.println(" If no option is specified, it will bind to the default.");
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700761 pw.println(" set-satellite-gateway-service-package-name [-s SERVICE_PACKAGE_NAME]");
762 pw.println(" Sets the package name of satellite gateway service defined in");
763 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
764 pw.println(" -s: the satellite gateway service package name that Telephony will bind");
765 pw.println(" to. If no option is specified, it will bind to the default.");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700766 pw.println(" set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
767 pw.println(" Sets the timeout duration in millis that satellite will stay at listening");
768 pw.println(" mode. Options are:");
769 pw.println(" -t: the timeout duration in milliseconds.");
770 pw.println(" If no option is specified, it will use the default values.");
Thomas Nguyen87dce732023-04-20 18:27:16 -0700771 pw.println(" set-satellite-pointing-ui-class-name [-p PACKAGE_NAME -c CLASS_NAME]");
772 pw.println(" Sets the package and class name of satellite pointing UI app defined in");
773 pw.println(" PACKAGE_NAME and CLASS_NAME to be launched. Options are:");
774 pw.println(" -p: the satellite pointing UI app package name that Telephony will");
775 pw.println(" launch. If no option is specified, it will launch the default.");
776 pw.println(" -c: the satellite pointing UI app class name that Telephony will");
777 pw.println(" launch.");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700778 }
779
Ling Ma4fbab492022-01-25 22:36:16 +0000780 private void onHelpImei() {
781 PrintWriter pw = getOutPrintWriter();
782 pw.println("IMEI Commands:");
783 pw.println(" get-imei [-s SLOT_ID]");
784 pw.println(" Gets the device IMEI. Options are:");
785 pw.println(" -s: the slot ID to get the IMEI. If no option");
786 pw.println(" is specified, it will choose the default voice SIM slot.");
787 }
788
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700789 private int handleImsCommand() {
790 String arg = getNextArg();
791 if (arg == null) {
792 onHelpIms();
793 return 0;
794 }
795
796 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800797 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700798 return handleImsSetServiceCommand();
799 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800800 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700801 return handleImsGetServiceCommand();
802 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800803 case IMS_CLEAR_SERVICE_OVERRIDE: {
804 return handleImsClearCarrierServiceCommand();
805 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800806 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700807 return handleEnableIms();
808 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800809 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700810 return handleDisableIms();
811 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700812 case IMS_CEP: {
813 return handleCepChange();
814 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700815 }
816
817 return -1;
818 }
819
Shuo Qianf5125122019-12-16 17:03:07 -0800820 private int handleDataTestModeCommand() {
821 PrintWriter errPw = getErrPrintWriter();
822 String arg = getNextArgRequired();
823 if (arg == null) {
824 onHelpDataTestMode();
825 return 0;
826 }
827 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800828 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800829 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700830 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800831 } catch (RemoteException ex) {
832 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
833 errPw.println("Exception: " + ex.getMessage());
834 return -1;
835 }
836 break;
837 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800838 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800839 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700840 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800841 } catch (RemoteException ex) {
842 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
843 errPw.println("Exception: " + ex.getMessage());
844 return -1;
845 }
846 break;
847 }
848 default:
849 onHelpDataTestMode();
850 break;
851 }
852 return 0;
853 }
854
Shuo Qianccbaf742021-02-22 18:32:21 -0800855 private int handleEmergencyCallbackModeCommand() {
856 PrintWriter errPw = getErrPrintWriter();
857 try {
858 mInterface.startEmergencyCallbackMode();
859 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
860 } catch (RemoteException ex) {
861 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
862 errPw.println("Exception: " + ex.getMessage());
863 return -1;
864 }
865 return 0;
866 }
867
Grant Menke567d48f2022-08-18 20:19:10 +0000868 private void removeEmergencyNumberTestMode(String emergencyNumber) {
869 PrintWriter errPw = getErrPrintWriter();
870 for (int routingType : ROUTING_TYPES) {
871 try {
872 mInterface.updateEmergencyNumberListTestMode(
873 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
874 new EmergencyNumber(emergencyNumber, "", "",
875 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
876 new ArrayList<String>(),
877 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
878 routingType));
879 } catch (RemoteException ex) {
880 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
881 errPw.println("Exception: " + ex.getMessage());
882 }
883 }
884 }
885
sqian9d4df8b2019-01-15 18:32:07 -0800886 private int handleEmergencyNumberTestModeCommand() {
887 PrintWriter errPw = getErrPrintWriter();
888 String opt = getNextOption();
889 if (opt == null) {
890 onHelpEmergencyNumber();
891 return 0;
892 }
sqian9d4df8b2019-01-15 18:32:07 -0800893 switch (opt) {
894 case "-a": {
895 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000896 if (emergencyNumberCmd == null){
897 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800898 return -1;
899 }
Grant Menke567d48f2022-08-18 20:19:10 +0000900 String[] params = emergencyNumberCmd.split(":");
901 String emergencyNumber;
902 if (params[0] == null ||
903 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
904 errPw.println(INVALID_ENTRY_ERROR);
905 return -1;
906 } else {
907 emergencyNumber = params[0];
908 }
909 removeEmergencyNumberTestMode(emergencyNumber);
910 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
911 if (params.length > 1) {
912 switch (params[1].toLowerCase(Locale.ROOT)) {
913 case "emergency":
914 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
915 break;
916 case "normal":
917 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
918 break;
919 case "unknown":
920 break;
921 default:
922 errPw.println("\"" + params[1] + "\" is not a valid specification for "
923 + "emergency call routing. Please enter either \"normal\", "
924 + "\"unknown\", or \"emergency\" for call routing. "
925 + "(-a 1234:normal)");
926 return -1;
927 }
928 }
sqian9d4df8b2019-01-15 18:32:07 -0800929 try {
930 mInterface.updateEmergencyNumberListTestMode(
931 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000932 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800933 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
934 new ArrayList<String>(),
935 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000936 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800937 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000938 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800939 + ", error " + ex.getMessage());
940 errPw.println("Exception: " + ex.getMessage());
941 return -1;
942 }
943 break;
944 }
945 case "-c": {
946 try {
947 mInterface.updateEmergencyNumberListTestMode(
948 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
949 } catch (RemoteException ex) {
950 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
951 errPw.println("Exception: " + ex.getMessage());
952 return -1;
953 }
954 break;
955 }
956 case "-r": {
957 String emergencyNumberCmd = getNextArgRequired();
958 if (emergencyNumberCmd == null
959 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700960 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800961 + " to be specified after -r in the command ");
962 return -1;
963 }
Grant Menke567d48f2022-08-18 20:19:10 +0000964 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800965 break;
966 }
967 case "-p": {
968 try {
969 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
970 } catch (RemoteException ex) {
971 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
972 errPw.println("Exception: " + ex.getMessage());
973 return -1;
974 }
975 break;
976 }
977 default:
978 onHelpEmergencyNumber();
979 break;
980 }
981 return 0;
982 }
983
Hall Liud892bec2018-11-30 14:51:45 -0800984 private int handleNumberVerificationCommand() {
985 String arg = getNextArg();
986 if (arg == null) {
987 onHelpNumberVerification();
988 return 0;
989 }
990
Hall Liuca5af3a2018-12-04 16:58:23 -0800991 if (!checkShellUid()) {
992 return -1;
993 }
994
Hall Liud892bec2018-11-30 14:51:45 -0800995 switch (arg) {
996 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800997 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
998 return 0;
999 }
Hall Liuca5af3a2018-12-04 16:58:23 -08001000 case NUMBER_VERIFICATION_FAKE_CALL: {
1001 boolean val = NumberVerificationManager.getInstance()
1002 .checkIncomingCall(getNextArg());
1003 getOutPrintWriter().println(val ? "1" : "0");
1004 return 0;
1005 }
Hall Liud892bec2018-11-30 14:51:45 -08001006 }
1007
1008 return -1;
1009 }
1010
Jordan Liu0ccee222021-04-27 11:55:13 -07001011 private boolean subIsEsim(int subId) {
1012 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
1013 if (info != null) {
1014 return info.isEmbedded();
1015 }
1016 return false;
1017 }
1018
1019 private int handleEnablePhysicalSubscription(boolean enable) {
1020 PrintWriter errPw = getErrPrintWriter();
1021 int subId = 0;
1022 try {
1023 subId = Integer.parseInt(getNextArgRequired());
1024 } catch (NumberFormatException e) {
1025 errPw.println((enable ? "enable" : "disable")
1026 + "-physical-subscription requires an integer as a subId.");
1027 return -1;
1028 }
1029 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1030 // non user build.
1031 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1032 errPw.println("cc: Permission denied.");
1033 return -1;
1034 }
1035 // Verify that the subId represents a physical sub
1036 if (subIsEsim(subId)) {
1037 errPw.println("SubId " + subId + " is not for a physical subscription");
1038 return -1;
1039 }
1040 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1041 + " physical subscription with subId=" + subId);
1042 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1043 return 0;
1044 }
1045
Jack Nudelman644b91a2021-03-12 14:09:48 -08001046 private int handleThermalMitigationCommand() {
1047 String arg = getNextArg();
1048 String packageName = getNextArg();
1049 if (arg == null || packageName == null) {
1050 onHelpThermalMitigation();
1051 return 0;
1052 }
1053
1054 if (!checkShellUid()) {
1055 return -1;
1056 }
1057
1058 switch (arg) {
1059 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1060 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1061 return 0;
1062 }
1063 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1064 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1065 mContext);
1066 return 0;
1067 }
1068 default:
1069 onHelpThermalMitigation();
1070 }
1071
1072 return -1;
1073
1074 }
1075
Tyler Gunn92479152021-01-20 16:30:10 -08001076 private int handleD2dCommand() {
1077 String arg = getNextArg();
1078 if (arg == null) {
1079 onHelpD2D();
1080 return 0;
1081 }
1082
1083 switch (arg) {
1084 case D2D_SEND: {
1085 return handleD2dSendCommand();
1086 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001087 case D2D_TRANSPORT: {
1088 return handleD2dTransportCommand();
1089 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001090 case D2D_SET_DEVICE_SUPPORT: {
1091 return handleD2dDeviceSupportedCommand();
1092 }
Tyler Gunn92479152021-01-20 16:30:10 -08001093 }
1094
1095 return -1;
1096 }
1097
1098 private int handleD2dSendCommand() {
1099 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001100 int messageType = -1;
1101 int messageValue = -1;
1102
Tyler Gunn92479152021-01-20 16:30:10 -08001103 String arg = getNextArg();
1104 if (arg == null) {
1105 onHelpD2D();
1106 return 0;
1107 }
1108 try {
1109 messageType = Integer.parseInt(arg);
1110 } catch (NumberFormatException e) {
1111 errPw.println("message type must be a valid integer");
1112 return -1;
1113 }
1114
1115 arg = getNextArg();
1116 if (arg == null) {
1117 onHelpD2D();
1118 return 0;
1119 }
1120 try {
1121 messageValue = Integer.parseInt(arg);
1122 } catch (NumberFormatException e) {
1123 errPw.println("message value must be a valid integer");
1124 return -1;
1125 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001126
Tyler Gunn92479152021-01-20 16:30:10 -08001127 try {
1128 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1129 } catch (RemoteException e) {
1130 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1131 errPw.println("Exception: " + e.getMessage());
1132 return -1;
1133 }
1134
1135 return 0;
1136 }
1137
Tyler Gunnbabbda02021-02-10 11:05:02 -08001138 private int handleD2dTransportCommand() {
1139 PrintWriter errPw = getErrPrintWriter();
1140
1141 String arg = getNextArg();
1142 if (arg == null) {
1143 onHelpD2D();
1144 return 0;
1145 }
1146
1147 try {
1148 mInterface.setActiveDeviceToDeviceTransport(arg);
1149 } catch (RemoteException e) {
1150 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1151 errPw.println("Exception: " + e.getMessage());
1152 return -1;
1153 }
1154 return 0;
1155 }
Nazanin014f41e2021-05-06 17:26:31 -07001156 private int handleBarringCommand() {
1157 String arg = getNextArg();
1158 if (arg == null) {
1159 onHelpBarring();
1160 return 0;
1161 }
1162
1163 switch (arg) {
1164 case BARRING_SEND_INFO: {
1165 return handleBarringSendCommand();
1166 }
1167 }
1168 return -1;
1169 }
1170
1171 private int handleBarringSendCommand() {
1172 PrintWriter errPw = getErrPrintWriter();
1173 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001174 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001175 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1176 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1177 boolean isConditionallyBarred = false;
1178 int conditionalBarringTimeSeconds = 0;
1179
1180 String opt;
1181 while ((opt = getNextOption()) != null) {
1182 switch (opt) {
1183 case "-s": {
1184 try {
1185 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001186 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001187 } catch (NumberFormatException e) {
1188 errPw.println("barring send requires an integer as a SLOT_ID.");
1189 return -1;
1190 }
1191 break;
1192 }
1193 case "-b": {
1194 try {
1195 barringType = Integer.parseInt(getNextArgRequired());
1196 if (barringType < -1 || barringType > 2) {
1197 throw new NumberFormatException();
1198 }
1199
1200 } catch (NumberFormatException e) {
1201 errPw.println("barring send requires an integer in range [-1,2] as "
1202 + "a BARRING_TYPE.");
1203 return -1;
1204 }
1205 break;
1206 }
1207 case "-c": {
1208 try {
1209 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1210 } catch (Exception e) {
1211 errPw.println("barring send requires a boolean after -c indicating"
1212 + " conditional barring");
1213 return -1;
1214 }
1215 break;
1216 }
1217 case "-t": {
1218 try {
1219 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1220 } catch (NumberFormatException e) {
1221 errPw.println("barring send requires an integer for time of barring"
1222 + " in seconds after -t for conditional barring");
1223 return -1;
1224 }
1225 break;
1226 }
1227 }
1228 }
1229 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1230 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1231 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1232 barringServiceInfos.append(0, bsi);
1233 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1234 try {
1235 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1236 } catch (Exception e) {
1237 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1238 errPw.println("Exception: " + e.getMessage());
1239 return -1;
1240 }
1241 return 0;
1242 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001243
Tyler Gunnd4575212021-05-03 14:46:49 -07001244 private int handleD2dDeviceSupportedCommand() {
1245 PrintWriter errPw = getErrPrintWriter();
1246
1247 String arg = getNextArg();
1248 if (arg == null) {
1249 onHelpD2D();
1250 return 0;
1251 }
1252
Jack Yua533d632022-09-30 13:53:46 -07001253 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001254 try {
1255 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1256 } catch (RemoteException e) {
1257 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1258 errPw.println("Exception: " + e.getMessage());
1259 return -1;
1260 }
1261 return 0;
1262 }
1263
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001264 // ims set-ims-service
1265 private int handleImsSetServiceCommand() {
1266 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001267 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001268 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001269 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001270
1271 String opt;
1272 while ((opt = getNextOption()) != null) {
1273 switch (opt) {
1274 case "-s": {
1275 try {
1276 slotId = Integer.parseInt(getNextArgRequired());
1277 } catch (NumberFormatException e) {
1278 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1279 return -1;
1280 }
1281 break;
1282 }
1283 case "-c": {
1284 isCarrierService = true;
1285 break;
1286 }
1287 case "-d": {
1288 isCarrierService = false;
1289 break;
1290 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001291 case "-f": {
1292 String featureString = getNextArgRequired();
1293 String[] features = featureString.split(",");
1294 for (int i = 0; i < features.length; i++) {
1295 try {
1296 Integer result = Integer.parseInt(features[i]);
1297 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1298 || result >= ImsFeature.FEATURE_MAX) {
1299 errPw.println("ims set-ims-service -f " + result
1300 + " is an invalid feature.");
1301 return -1;
1302 }
1303 featuresList.add(result);
1304 } catch (NumberFormatException e) {
1305 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1306 + " as an integer.");
1307 return -1;
1308 }
1309 }
1310 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001311 }
1312 }
1313 // Mandatory param, either -c or -d
1314 if (isCarrierService == null) {
1315 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1316 return -1;
1317 }
1318
1319 String packageName = getNextArg();
1320
1321 try {
1322 if (packageName == null) {
1323 packageName = "";
1324 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001325 int[] featureArray = new int[featuresList.size()];
1326 for (int i = 0; i < featuresList.size(); i++) {
1327 featureArray[i] = featuresList.get(i);
1328 }
1329 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1330 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001331 if (VDBG) {
1332 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001333 + (isCarrierService ? "-c " : "-d ")
1334 + "-f " + featuresList + " "
1335 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001336 }
1337 getOutPrintWriter().println(result);
1338 } catch (RemoteException e) {
1339 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001340 + (isCarrierService ? "-c " : "-d ")
1341 + "-f " + featuresList + " "
1342 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001343 errPw.println("Exception: " + e.getMessage());
1344 return -1;
1345 }
1346 return 0;
1347 }
1348
Brad Ebinger999d3302020-11-25 14:31:39 -08001349 // ims clear-ims-service-override
1350 private int handleImsClearCarrierServiceCommand() {
1351 PrintWriter errPw = getErrPrintWriter();
1352 int slotId = getDefaultSlot();
1353
1354 String opt;
1355 while ((opt = getNextOption()) != null) {
1356 switch (opt) {
1357 case "-s": {
1358 try {
1359 slotId = Integer.parseInt(getNextArgRequired());
1360 } catch (NumberFormatException e) {
1361 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1362 return -1;
1363 }
1364 break;
1365 }
1366 }
1367 }
1368
1369 try {
1370 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1371 if (VDBG) {
1372 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1373 + ", result=" + result);
1374 }
1375 getOutPrintWriter().println(result);
1376 } catch (RemoteException e) {
1377 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1378 + ", error" + e.getMessage());
1379 errPw.println("Exception: " + e.getMessage());
1380 return -1;
1381 }
1382 return 0;
1383 }
1384
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001385 // ims get-ims-service
1386 private int handleImsGetServiceCommand() {
1387 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001388 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001389 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001390 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001391
1392 String opt;
1393 while ((opt = getNextOption()) != null) {
1394 switch (opt) {
1395 case "-s": {
1396 try {
1397 slotId = Integer.parseInt(getNextArgRequired());
1398 } catch (NumberFormatException e) {
1399 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1400 return -1;
1401 }
1402 break;
1403 }
1404 case "-c": {
1405 isCarrierService = true;
1406 break;
1407 }
1408 case "-d": {
1409 isCarrierService = false;
1410 break;
1411 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001412 case "-f": {
1413 try {
1414 featureType = Integer.parseInt(getNextArg());
1415 } catch (NumberFormatException e) {
1416 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1417 return -1;
1418 }
1419 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1420 || featureType >= ImsFeature.FEATURE_MAX) {
1421 errPw.println("ims get-ims-service -f invalid feature.");
1422 return -1;
1423 }
1424 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001425 }
1426 }
1427 // Mandatory param, either -c or -d
1428 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001429 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001430 return -1;
1431 }
1432
1433 String result;
1434 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001435 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001436 } catch (RemoteException e) {
1437 return -1;
1438 }
1439 if (VDBG) {
1440 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001441 + (isCarrierService ? "-c " : "-d ")
1442 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1443 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001444 }
1445 getOutPrintWriter().println(result);
1446 return 0;
1447 }
1448
1449 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001450 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001451 String opt;
1452 while ((opt = getNextOption()) != null) {
1453 switch (opt) {
1454 case "-s": {
1455 try {
1456 slotId = Integer.parseInt(getNextArgRequired());
1457 } catch (NumberFormatException e) {
1458 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1459 return -1;
1460 }
1461 break;
1462 }
1463 }
1464 }
1465 try {
1466 mInterface.enableIms(slotId);
1467 } catch (RemoteException e) {
1468 return -1;
1469 }
1470 if (VDBG) {
1471 Log.v(LOG_TAG, "ims enable -s " + slotId);
1472 }
1473 return 0;
1474 }
1475
1476 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001477 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001478 String opt;
1479 while ((opt = getNextOption()) != null) {
1480 switch (opt) {
1481 case "-s": {
1482 try {
1483 slotId = Integer.parseInt(getNextArgRequired());
1484 } catch (NumberFormatException e) {
1485 getErrPrintWriter().println(
1486 "ims disable requires an integer as a SLOT_ID.");
1487 return -1;
1488 }
1489 break;
1490 }
1491 }
1492 }
1493 try {
1494 mInterface.disableIms(slotId);
1495 } catch (RemoteException e) {
1496 return -1;
1497 }
1498 if (VDBG) {
1499 Log.v(LOG_TAG, "ims disable -s " + slotId);
1500 }
1501 return 0;
1502 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001503
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001504 private int handleCepChange() {
1505 Log.i(LOG_TAG, "handleCepChange");
1506 String opt = getNextArg();
1507 if (opt == null) {
1508 return -1;
1509 }
1510 boolean isCepEnabled = opt.equals("enable");
1511
1512 try {
1513 mInterface.setCepEnabled(isCepEnabled);
1514 } catch (RemoteException e) {
1515 return -1;
1516 }
1517 return 0;
1518 }
1519
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001520 private int getDefaultSlot() {
1521 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1522 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1523 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1524 // If there is no default, default to slot 0.
1525 slotId = DEFAULT_PHONE_ID;
1526 }
1527 return slotId;
1528 }
sqian2fff4a32018-11-05 14:18:37 -08001529
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001530 // Parse options related to Carrier Config Commands.
1531 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001532 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001533 CcOptionParseResult result = new CcOptionParseResult();
1534 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1535 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001536
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001537 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001538 while ((opt = getNextOption()) != null) {
1539 switch (opt) {
1540 case "-s": {
1541 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001542 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1543 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1544 errPw.println(tag + "No valid subscription found.");
1545 return null;
1546 }
1547
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001548 } catch (IllegalArgumentException e) {
1549 // Missing slot id
1550 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001551 return null;
1552 }
1553 break;
1554 }
1555 case "-p": {
1556 if (allowOptionPersistent) {
1557 result.mPersistent = true;
1558 } else {
1559 errPw.println(tag + "Unexpected option " + opt);
1560 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001561 }
1562 break;
1563 }
1564 default: {
1565 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001566 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001567 }
1568 }
1569 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001570 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001571 }
1572
1573 private int slotStringToSubId(String tag, String slotString) {
1574 int slotId = -1;
1575 try {
1576 slotId = Integer.parseInt(slotString);
1577 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001578 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1579 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1580 }
1581
1582 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001583 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1584 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1585 }
1586
Qiong Liuf25799b2020-09-10 10:13:46 +08001587 Phone phone = PhoneFactory.getPhone(slotId);
1588 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001589 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1590 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1591 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001592 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001593 }
1594
Hall Liud892bec2018-11-30 14:51:45 -08001595 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001596 // adb can run as root or as shell, depending on whether the device is rooted.
1597 return Binder.getCallingUid() == Process.SHELL_UID
1598 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001599 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001600
1601 private int handleCcCommand() {
1602 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1603 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001604 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001605 getErrPrintWriter().println("cc: Permission denied.");
1606 return -1;
1607 }
1608
1609 String arg = getNextArg();
1610 if (arg == null) {
1611 onHelpCc();
1612 return 0;
1613 }
1614
1615 switch (arg) {
1616 case CC_GET_VALUE: {
1617 return handleCcGetValue();
1618 }
1619 case CC_SET_VALUE: {
1620 return handleCcSetValue();
1621 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001622 case CC_SET_VALUES_FROM_XML: {
1623 return handleCcSetValuesFromXml();
1624 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001625 case CC_CLEAR_VALUES: {
1626 return handleCcClearValues();
1627 }
1628 default: {
1629 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1630 }
1631 }
1632 return -1;
1633 }
1634
1635 // cc get-value
1636 private int handleCcGetValue() {
1637 PrintWriter errPw = getErrPrintWriter();
1638 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1639 String key = null;
1640
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001641 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001642 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001643 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001644 return -1;
1645 }
1646
1647 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001648 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001649 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001650 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001651 return -1;
1652 }
1653
1654 // Get the key.
1655 key = getNextArg();
1656 if (key != null) {
1657 // A key was provided. Verify if it is a valid key
1658 if (!bundle.containsKey(key)) {
1659 errPw.println(tag + key + " is not a valid key.");
1660 return -1;
1661 }
1662
1663 // Print the carrier config value for key.
1664 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1665 } else {
1666 // No key provided. Show all values.
1667 // Iterate over a sorted list of all carrier config keys and print them.
1668 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1669 for (String k : sortedSet) {
1670 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1671 }
1672 }
1673 return 0;
1674 }
1675
1676 // cc set-value
1677 private int handleCcSetValue() {
1678 PrintWriter errPw = getErrPrintWriter();
1679 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1680
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001681 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001682 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001683 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001684 return -1;
1685 }
1686
1687 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001688 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001689 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001690 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001691 return -1;
1692 }
1693
1694 // Get the key.
1695 String key = getNextArg();
1696 if (key == null || key.equals("")) {
1697 errPw.println(tag + "KEY is missing");
1698 return -1;
1699 }
1700
1701 // Verify if the key is valid
1702 if (!originalValues.containsKey(key)) {
1703 errPw.println(tag + key + " is not a valid key.");
1704 return -1;
1705 }
1706
1707 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1708 ArrayList<String> valueList = new ArrayList<String>();
1709 while (peekNextArg() != null) {
1710 valueList.add(getNextArg());
1711 }
1712
1713 // Find the type of the carrier config value
1714 CcType type = getType(tag, key, originalValues);
1715 if (type == CcType.UNKNOWN) {
1716 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1717 return -1;
1718 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001719 if (type == CcType.PERSISTABLE_BUNDLE) {
1720 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1721 + "Use set-values-from-xml instead.");
1722 return -1;
1723 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001724
1725 // Create an override bundle containing the key and value that should be overriden.
1726 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1727 if (overrideBundle == null) {
1728 return -1;
1729 }
1730
1731 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001732 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001733
1734 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001735 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001736 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001737 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001738 return -1;
1739 }
1740
1741 // Print the original and new value.
1742 String originalValueString = ccValueToString(key, type, originalValues);
1743 String newValueString = ccValueToString(key, type, newValues);
1744 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1745 getOutPrintWriter().println("New value: \n" + newValueString);
1746
1747 return 0;
1748 }
1749
Allen Xuee00f0e2022-03-14 21:04:49 +00001750 // cc set-values-from-xml
1751 private int handleCcSetValuesFromXml() {
1752 PrintWriter errPw = getErrPrintWriter();
1753 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1754
1755 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001756 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001757 if (options == null) {
1758 return -1;
1759 }
1760
1761 // Get bundle containing all current carrier configuration values.
1762 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1763 if (originalValues == null) {
1764 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1765 return -1;
1766 }
1767
1768 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1769 if (overrideBundle == null) {
1770 return -1;
1771 }
1772
1773 // Verify all values are valid types
1774 for (String key : overrideBundle.keySet()) {
1775 CcType type = getType(tag, key, originalValues);
1776 if (type == CcType.UNKNOWN) {
1777 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1778 return -1;
1779 }
1780 }
1781
1782 // Override the value
1783 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1784
1785 // Find bundle containing all new carrier configuration values after the override.
1786 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1787 if (newValues == null) {
1788 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1789 return -1;
1790 }
1791
1792 // Print the original and new values
1793 overrideBundle.keySet().forEach(key -> {
1794 CcType type = getType(tag, key, originalValues);
1795 String originalValueString = ccValueToString(key, type, originalValues);
1796 String newValueString = ccValueToString(key, type, newValues);
1797 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1798 getOutPrintWriter().println("New value: \n" + newValueString);
1799 });
1800
1801 return 0;
1802 }
1803
1804 private PersistableBundle readPersistableBundleFromXml(String tag) {
1805 PersistableBundle subIdBundles;
1806 try {
1807 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1808 } catch (IOException | RuntimeException e) {
1809 PrintWriter errPw = getErrPrintWriter();
1810 errPw.println(tag + e);
1811 return null;
1812 }
1813
1814 return subIdBundles;
1815 }
1816
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001817 // cc clear-values
1818 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001819 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1820
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001821 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001822 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001823 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001824 return -1;
1825 }
1826
1827 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001828 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001829 getOutPrintWriter()
1830 .println("All previously set carrier config override values has been cleared");
1831 return 0;
1832 }
1833
1834 private CcType getType(String tag, String key, PersistableBundle bundle) {
1835 // Find the type by checking the type of the current value stored in the bundle.
1836 Object value = bundle.get(key);
1837
1838 if (CC_TYPE_MAP.containsKey(key)) {
1839 return CC_TYPE_MAP.get(key);
1840 } else if (value != null) {
1841 if (value instanceof Boolean) {
1842 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001843 }
1844 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001845 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001846 }
1847 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001848 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001849 }
1850 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001851 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001852 }
1853 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001854 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001855 }
1856 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001857 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001858 }
1859 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001860 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001861 }
1862 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001863 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001864 }
1865 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001866 return CcType.STRING_ARRAY;
1867 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001868 if (value instanceof PersistableBundle) {
1869 return CcType.PERSISTABLE_BUNDLE;
1870 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001871 } else {
1872 // Current value was null and can therefore not be used in order to find the type.
1873 // Check the name of the key to infer the type. This check is not needed for primitive
1874 // data types (boolean, double, int and long), since they can not be null.
1875 if (key.endsWith("double_array")) {
1876 return CcType.DOUBLE_ARRAY;
1877 }
1878 if (key.endsWith("int_array")) {
1879 return CcType.INT_ARRAY;
1880 }
1881 if (key.endsWith("long_array")) {
1882 return CcType.LONG_ARRAY;
1883 }
1884 if (key.endsWith("string")) {
1885 return CcType.STRING;
1886 }
1887 if (key.endsWith("string_array") || key.endsWith("strings")) {
1888 return CcType.STRING_ARRAY;
1889 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001890 if (key.endsWith("bundle")) {
1891 return CcType.PERSISTABLE_BUNDLE;
1892 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001893 }
1894
1895 // Not possible to infer the type by looking at the current value or the key.
1896 PrintWriter errPw = getErrPrintWriter();
1897 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1898 return CcType.UNKNOWN;
1899 }
1900
1901 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1902 String result;
1903 StringBuilder valueString = new StringBuilder();
1904 String typeString = type.toString();
1905 Object value = bundle.get(key);
1906
1907 if (value == null) {
1908 valueString.append("null");
1909 } else {
1910 switch (type) {
1911 case DOUBLE_ARRAY: {
1912 // Format the string representation of the int array as value1 value2......
1913 double[] valueArray = (double[]) value;
1914 for (int i = 0; i < valueArray.length; i++) {
1915 if (i != 0) {
1916 valueString.append(" ");
1917 }
1918 valueString.append(valueArray[i]);
1919 }
1920 break;
1921 }
1922 case INT_ARRAY: {
1923 // Format the string representation of the int array as value1 value2......
1924 int[] valueArray = (int[]) value;
1925 for (int i = 0; i < valueArray.length; i++) {
1926 if (i != 0) {
1927 valueString.append(" ");
1928 }
1929 valueString.append(valueArray[i]);
1930 }
1931 break;
1932 }
1933 case LONG_ARRAY: {
1934 // Format the string representation of the int array as value1 value2......
1935 long[] valueArray = (long[]) value;
1936 for (int i = 0; i < valueArray.length; i++) {
1937 if (i != 0) {
1938 valueString.append(" ");
1939 }
1940 valueString.append(valueArray[i]);
1941 }
1942 break;
1943 }
1944 case STRING: {
1945 valueString.append("\"" + value.toString() + "\"");
1946 break;
1947 }
1948 case STRING_ARRAY: {
1949 // Format the string representation of the string array as "value1" "value2"....
1950 String[] valueArray = (String[]) value;
1951 for (int i = 0; i < valueArray.length; i++) {
1952 if (i != 0) {
1953 valueString.append(" ");
1954 }
1955 if (valueArray[i] != null) {
1956 valueString.append("\"" + valueArray[i] + "\"");
1957 } else {
1958 valueString.append("null");
1959 }
1960 }
1961 break;
1962 }
1963 default: {
1964 valueString.append(value.toString());
1965 }
1966 }
1967 }
1968 return String.format("%-70s %-15s %s", key, typeString, valueString);
1969 }
1970
1971 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1972 ArrayList<String> valueList) {
1973 PrintWriter errPw = getErrPrintWriter();
1974 PersistableBundle bundle = new PersistableBundle();
1975
1976 // First verify that a valid number of values has been provided for the type.
1977 switch (type) {
1978 case BOOLEAN:
1979 case DOUBLE:
1980 case INT:
1981 case LONG: {
1982 if (valueList.size() != 1) {
1983 errPw.println(tag + "Expected 1 value for type " + type
1984 + ". Found: " + valueList.size());
1985 return null;
1986 }
1987 break;
1988 }
1989 case STRING: {
1990 if (valueList.size() > 1) {
1991 errPw.println(tag + "Expected 0 or 1 values for type " + type
1992 + ". Found: " + valueList.size());
1993 return null;
1994 }
1995 break;
1996 }
1997 }
1998
1999 // Parse the value according to type and add it to the Bundle.
2000 switch (type) {
2001 case BOOLEAN: {
2002 if ("true".equalsIgnoreCase(valueList.get(0))) {
2003 bundle.putBoolean(key, true);
2004 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
2005 bundle.putBoolean(key, false);
2006 } else {
2007 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2008 return null;
2009 }
2010 break;
2011 }
2012 case DOUBLE: {
2013 try {
2014 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
2015 } catch (NumberFormatException nfe) {
2016 // Not a valid double
2017 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2018 return null;
2019 }
2020 break;
2021 }
2022 case DOUBLE_ARRAY: {
2023 double[] valueDoubleArray = null;
2024 if (valueList.size() > 0) {
2025 valueDoubleArray = new double[valueList.size()];
2026 for (int i = 0; i < valueList.size(); i++) {
2027 try {
2028 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2029 } catch (NumberFormatException nfe) {
2030 // Not a valid double
2031 errPw.println(
2032 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2033 return null;
2034 }
2035 }
2036 }
2037 bundle.putDoubleArray(key, valueDoubleArray);
2038 break;
2039 }
2040 case INT: {
2041 try {
2042 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2043 } catch (NumberFormatException nfe) {
2044 // Not a valid integer
2045 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2046 return null;
2047 }
2048 break;
2049 }
2050 case INT_ARRAY: {
2051 int[] valueIntArray = null;
2052 if (valueList.size() > 0) {
2053 valueIntArray = new int[valueList.size()];
2054 for (int i = 0; i < valueList.size(); i++) {
2055 try {
2056 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2057 } catch (NumberFormatException nfe) {
2058 // Not a valid integer
2059 errPw.println(tag
2060 + "Unable to parse " + valueList.get(i) + " as an integer.");
2061 return null;
2062 }
2063 }
2064 }
2065 bundle.putIntArray(key, valueIntArray);
2066 break;
2067 }
2068 case LONG: {
2069 try {
2070 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2071 } catch (NumberFormatException nfe) {
2072 // Not a valid long
2073 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2074 return null;
2075 }
2076 break;
2077 }
2078 case LONG_ARRAY: {
2079 long[] valueLongArray = null;
2080 if (valueList.size() > 0) {
2081 valueLongArray = new long[valueList.size()];
2082 for (int i = 0; i < valueList.size(); i++) {
2083 try {
2084 valueLongArray[i] = Long.parseLong(valueList.get(i));
2085 } catch (NumberFormatException nfe) {
2086 // Not a valid long
2087 errPw.println(
2088 tag + "Unable to parse " + valueList.get(i) + " as a long");
2089 return null;
2090 }
2091 }
2092 }
2093 bundle.putLongArray(key, valueLongArray);
2094 break;
2095 }
2096 case STRING: {
2097 String value = null;
2098 if (valueList.size() > 0) {
2099 value = valueList.get(0);
2100 }
2101 bundle.putString(key, value);
2102 break;
2103 }
2104 case STRING_ARRAY: {
2105 String[] valueStringArray = null;
2106 if (valueList.size() > 0) {
2107 valueStringArray = new String[valueList.size()];
2108 valueList.toArray(valueStringArray);
2109 }
2110 bundle.putStringArray(key, valueStringArray);
2111 break;
2112 }
2113 }
2114 return bundle;
2115 }
Shuo Qian489d9282020-07-09 11:30:03 -07002116
2117 private int handleEndBlockSuppressionCommand() {
2118 if (!checkShellUid()) {
2119 return -1;
2120 }
2121
2122 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2123 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2124 }
2125 return 0;
2126 }
Hui Wang641e81c2020-10-12 12:14:23 -07002127
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002128 private int handleEuiccCommand() {
2129 String arg = getNextArg();
2130 if (arg == null) {
2131 onHelpEuicc();
2132 return 0;
2133 }
2134
2135 switch (arg) {
2136 case EUICC_SET_UI_COMPONENT: {
2137 return handleEuiccServiceCommand();
2138 }
2139 }
2140 return -1;
2141 }
2142
2143 private int handleEuiccServiceCommand() {
2144 String uiComponent = getNextArg();
2145 String packageName = getNextArg();
2146 if (packageName == null || uiComponent == null) {
2147 return -1;
2148 }
2149 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2150 if (VDBG) {
2151 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2152 + packageName);
2153 }
2154 return 0;
2155 }
2156
Michele Berionne54af4632020-12-28 20:23:16 +00002157 private int handleRestartModemCommand() {
2158 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2159 // non user build.
2160 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2161 getErrPrintWriter().println("RestartModem: Permission denied.");
2162 return -1;
2163 }
2164
2165 boolean result = TelephonyManager.getDefault().rebootRadio();
2166 getOutPrintWriter().println(result);
2167
2168 return result ? 0 : -1;
2169 }
2170
Ling Ma4fbab492022-01-25 22:36:16 +00002171 private int handleGetImei() {
2172 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2173 // non user build.
2174 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2175 getErrPrintWriter().println("Device IMEI: Permission denied.");
2176 return -1;
2177 }
2178
2179 final long identity = Binder.clearCallingIdentity();
2180
2181 String imei = null;
2182 String arg = getNextArg();
2183 if (arg != null) {
2184 try {
2185 int specifiedSlotIndex = Integer.parseInt(arg);
2186 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2187 } catch (NumberFormatException exception) {
2188 PrintWriter errPw = getErrPrintWriter();
2189 errPw.println("-s requires an integer as slot index.");
2190 return -1;
2191 }
2192
2193 } else {
2194 imei = TelephonyManager.from(mContext).getImei();
2195 }
2196 getOutPrintWriter().println("Device IMEI: " + imei);
2197
2198 Binder.restoreCallingIdentity(identity);
2199 return 0;
2200 }
2201
Michele Berionne5e411512020-11-13 02:36:59 +00002202 private int handleUnattendedReboot() {
2203 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2204 // non user build.
2205 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2206 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2207 return -1;
2208 }
2209
2210 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2211 getOutPrintWriter().println("result: " + result);
2212
2213 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2214 }
2215
Aman Gupta07124872022-02-09 08:02:14 +00002216 private int handleGetSimSlotsMapping() {
2217 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2218 // non user build.
2219 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2220 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2221 return -1;
2222 }
2223 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2224 String result = telephonyManager.getSimSlotMapping().toString();
2225 getOutPrintWriter().println("simSlotsMapping: " + result);
2226
2227 return 0;
2228 }
2229
Hui Wang641e81c2020-10-12 12:14:23 -07002230 private int handleGbaCommand() {
2231 String arg = getNextArg();
2232 if (arg == null) {
2233 onHelpGba();
2234 return 0;
2235 }
2236
2237 switch (arg) {
2238 case GBA_SET_SERVICE: {
2239 return handleGbaSetServiceCommand();
2240 }
2241 case GBA_GET_SERVICE: {
2242 return handleGbaGetServiceCommand();
2243 }
2244 case GBA_SET_RELEASE_TIME: {
2245 return handleGbaSetReleaseCommand();
2246 }
2247 case GBA_GET_RELEASE_TIME: {
2248 return handleGbaGetReleaseCommand();
2249 }
2250 }
2251
2252 return -1;
2253 }
2254
2255 private int getSubId(String cmd) {
2256 int slotId = getDefaultSlot();
2257 String opt = getNextOption();
2258 if (opt != null && opt.equals("-s")) {
2259 try {
2260 slotId = Integer.parseInt(getNextArgRequired());
2261 } catch (NumberFormatException e) {
2262 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2263 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2264 }
2265 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002266 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002267 }
2268
2269 private int handleGbaSetServiceCommand() {
2270 int subId = getSubId("gba set-service");
2271 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2272 return -1;
2273 }
2274
2275 String packageName = getNextArg();
2276 try {
2277 if (packageName == null) {
2278 packageName = "";
2279 }
2280 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2281 if (VDBG) {
2282 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2283 + packageName + ", result=" + result);
2284 }
2285 getOutPrintWriter().println(result);
2286 } catch (RemoteException e) {
2287 Log.w(LOG_TAG, "gba set-service " + subId + " "
2288 + packageName + ", error" + e.getMessage());
2289 getErrPrintWriter().println("Exception: " + e.getMessage());
2290 return -1;
2291 }
2292 return 0;
2293 }
2294
2295 private int handleGbaGetServiceCommand() {
2296 String result;
2297
2298 int subId = getSubId("gba get-service");
2299 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2300 return -1;
2301 }
2302
2303 try {
2304 result = mInterface.getBoundGbaService(subId);
2305 } catch (RemoteException e) {
2306 return -1;
2307 }
2308 if (VDBG) {
2309 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2310 }
2311 getOutPrintWriter().println(result);
2312 return 0;
2313 }
2314
2315 private int handleGbaSetReleaseCommand() {
2316 //the release time value could be -1
2317 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2318 : SubscriptionManager.getDefaultSubscriptionId();
2319 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2320 return -1;
2321 }
2322
2323 String intervalStr = getNextArg();
2324 if (intervalStr == null) {
2325 return -1;
2326 }
2327
2328 try {
2329 int interval = Integer.parseInt(intervalStr);
2330 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2331 if (VDBG) {
2332 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2333 + intervalStr + ", result=" + result);
2334 }
2335 getOutPrintWriter().println(result);
2336 } catch (NumberFormatException | RemoteException e) {
2337 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2338 + intervalStr + ", error" + e.getMessage());
2339 getErrPrintWriter().println("Exception: " + e.getMessage());
2340 return -1;
2341 }
2342 return 0;
2343 }
2344
2345 private int handleGbaGetReleaseCommand() {
2346 int subId = getSubId("gba get-release");
2347 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2348 return -1;
2349 }
2350
2351 int result = 0;
2352 try {
2353 result = mInterface.getGbaReleaseTime(subId);
2354 } catch (RemoteException e) {
2355 return -1;
2356 }
2357 if (VDBG) {
2358 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2359 }
2360 getOutPrintWriter().println(result);
2361 return 0;
2362 }
Hui Wang761a6682020-10-31 05:12:53 +00002363
2364 private int handleSingleRegistrationConfigCommand() {
2365 String arg = getNextArg();
2366 if (arg == null) {
2367 onHelpSrc();
2368 return 0;
2369 }
2370
2371 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002372 case SRC_SET_TEST_ENABLED: {
2373 return handleSrcSetTestEnabledCommand();
2374 }
2375 case SRC_GET_TEST_ENABLED: {
2376 return handleSrcGetTestEnabledCommand();
2377 }
Hui Wang761a6682020-10-31 05:12:53 +00002378 case SRC_SET_DEVICE_ENABLED: {
2379 return handleSrcSetDeviceEnabledCommand();
2380 }
2381 case SRC_GET_DEVICE_ENABLED: {
2382 return handleSrcGetDeviceEnabledCommand();
2383 }
2384 case SRC_SET_CARRIER_ENABLED: {
2385 return handleSrcSetCarrierEnabledCommand();
2386 }
2387 case SRC_GET_CARRIER_ENABLED: {
2388 return handleSrcGetCarrierEnabledCommand();
2389 }
Hui Wangb647abe2021-02-26 09:33:38 -08002390 case SRC_SET_FEATURE_ENABLED: {
2391 return handleSrcSetFeatureValidationCommand();
2392 }
2393 case SRC_GET_FEATURE_ENABLED: {
2394 return handleSrcGetFeatureValidationCommand();
2395 }
Hui Wang761a6682020-10-31 05:12:53 +00002396 }
2397
2398 return -1;
2399 }
2400
James.cf Linbcdf8b32021-01-14 16:44:13 +08002401 private int handleRcsUceCommand() {
2402 String arg = getNextArg();
2403 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002404 onHelpUce();
2405 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002406 }
2407
2408 switch (arg) {
2409 case UCE_REMOVE_EAB_CONTACT:
2410 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002411 case UCE_GET_EAB_CONTACT:
2412 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002413 case UCE_GET_EAB_CAPABILITY:
2414 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002415 case UCE_GET_DEVICE_ENABLED:
2416 return handleUceGetDeviceEnabledCommand();
2417 case UCE_SET_DEVICE_ENABLED:
2418 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002419 case UCE_OVERRIDE_PUBLISH_CAPS:
2420 return handleUceOverridePublishCaps();
2421 case UCE_GET_LAST_PIDF_XML:
2422 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002423 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2424 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002425 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2426 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002427 }
2428 return -1;
2429 }
2430
2431 private int handleRemovingEabContactCommand() {
2432 int subId = getSubId("uce remove-eab-contact");
2433 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2434 return -1;
2435 }
2436
2437 String phoneNumber = getNextArgRequired();
2438 if (TextUtils.isEmpty(phoneNumber)) {
2439 return -1;
2440 }
2441 int result = 0;
2442 try {
2443 result = mInterface.removeContactFromEab(subId, phoneNumber);
2444 } catch (RemoteException e) {
2445 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2446 getErrPrintWriter().println("Exception: " + e.getMessage());
2447 return -1;
2448 }
2449
2450 if (VDBG) {
2451 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2452 }
calvinpan293ea1b2021-02-04 17:52:13 +08002453 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002454 }
2455
calvinpane4a8a1d2021-01-25 13:51:18 +08002456 private int handleGettingEabContactCommand() {
2457 String phoneNumber = getNextArgRequired();
2458 if (TextUtils.isEmpty(phoneNumber)) {
2459 return -1;
2460 }
2461 String result = "";
2462 try {
2463 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002464 } catch (RemoteException e) {
2465 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2466 getErrPrintWriter().println("Exception: " + e.getMessage());
2467 return -1;
2468 }
2469
2470 if (VDBG) {
2471 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2472 }
calvinpan293ea1b2021-02-04 17:52:13 +08002473 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002474 return 0;
2475 }
2476
Calvin Pana1434322021-07-01 19:27:01 +08002477 private int handleGettingEabCapabilityCommand() {
2478 String phoneNumber = getNextArgRequired();
2479 if (TextUtils.isEmpty(phoneNumber)) {
2480 return -1;
2481 }
2482 String result = "";
2483 try {
2484 result = mInterface.getCapabilityFromEab(phoneNumber);
2485 } catch (RemoteException e) {
2486 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2487 getErrPrintWriter().println("Exception: " + e.getMessage());
2488 return -1;
2489 }
2490
2491 if (VDBG) {
2492 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2493 }
2494 getOutPrintWriter().println(result);
2495 return 0;
2496 }
2497
James.cf Lin4b784aa2021-01-31 03:25:15 +08002498 private int handleUceGetDeviceEnabledCommand() {
2499 boolean result = false;
2500 try {
2501 result = mInterface.getDeviceUceEnabled();
2502 } catch (RemoteException e) {
2503 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2504 return -1;
2505 }
2506 if (VDBG) {
2507 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2508 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002509 getOutPrintWriter().println(result);
2510 return 0;
2511 }
2512
James.cf Lin4b784aa2021-01-31 03:25:15 +08002513 private int handleUceSetDeviceEnabledCommand() {
2514 String enabledStr = getNextArg();
2515 if (TextUtils.isEmpty(enabledStr)) {
2516 return -1;
2517 }
2518
2519 try {
2520 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2521 mInterface.setDeviceUceEnabled(isEnabled);
2522 if (VDBG) {
2523 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2524 }
2525 } catch (NumberFormatException | RemoteException e) {
2526 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2527 getErrPrintWriter().println("Exception: " + e.getMessage());
2528 return -1;
2529 }
2530 return 0;
2531 }
2532
James.cf Line8713a42021-04-29 16:04:26 +08002533 private int handleUceRemoveRequestDisallowedStatus() {
2534 int subId = getSubId("uce remove-request-disallowed-status");
2535 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2536 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2537 return -1;
2538 }
2539 boolean result;
2540 try {
2541 result = mInterface.removeUceRequestDisallowedStatus(subId);
2542 } catch (RemoteException e) {
2543 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2544 return -1;
2545 }
2546 if (VDBG) {
2547 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2548 }
2549 getOutPrintWriter().println(result);
2550 return 0;
2551 }
2552
James.cf Lin0fc71b02021-05-25 01:37:38 +08002553 private int handleUceSetCapRequestTimeout() {
2554 int subId = getSubId("uce set-capabilities-request-timeout");
2555 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2556 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2557 return -1;
2558 }
2559 long timeoutAfterMs = Long.valueOf(getNextArg());
2560 boolean result;
2561 try {
2562 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2563 } catch (RemoteException e) {
2564 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2565 return -1;
2566 }
2567 if (VDBG) {
2568 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2569 }
2570 getOutPrintWriter().println(result);
2571 return 0;
2572 }
2573
Hui Wangbaaee6a2021-02-19 20:45:36 -08002574 private int handleSrcSetTestEnabledCommand() {
2575 String enabledStr = getNextArg();
2576 if (enabledStr == null) {
2577 return -1;
2578 }
2579
2580 try {
2581 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2582 if (VDBG) {
2583 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2584 }
2585 getOutPrintWriter().println("Done");
2586 } catch (NumberFormatException | RemoteException e) {
2587 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2588 getErrPrintWriter().println("Exception: " + e.getMessage());
2589 return -1;
2590 }
2591 return 0;
2592 }
2593
2594 private int handleSrcGetTestEnabledCommand() {
2595 boolean result = false;
2596 try {
2597 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2598 } catch (RemoteException e) {
2599 return -1;
2600 }
2601 if (VDBG) {
2602 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2603 }
2604 getOutPrintWriter().println(result);
2605 return 0;
2606 }
2607
Brad Ebinger14d467f2021-02-12 06:18:28 +00002608 private int handleUceOverridePublishCaps() {
2609 int subId = getSubId("uce override-published-caps");
2610 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2611 return -1;
2612 }
2613 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2614 String operation = getNextArgRequired();
2615 String caps = getNextArg();
2616 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2617 && !"list".equals(operation)) {
2618 getErrPrintWriter().println("Invalid operation: " + operation);
2619 return -1;
2620 }
2621
2622 // add/remove requires capabilities to be specified.
2623 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2624 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2625 + "specified");
2626 return -1;
2627 }
2628
2629 ArraySet<String> capSet = new ArraySet<>();
2630 if (!TextUtils.isEmpty(caps)) {
2631 String[] capArray = caps.split(":");
2632 for (String cap : capArray) {
2633 // Allow unknown tags to be passed in as well.
2634 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2635 }
2636 }
2637
2638 RcsContactUceCapability result = null;
2639 try {
2640 switch (operation) {
2641 case "add":
2642 result = mInterface.addUceRegistrationOverrideShell(subId,
2643 new ArrayList<>(capSet));
2644 break;
2645 case "remove":
2646 result = mInterface.removeUceRegistrationOverrideShell(subId,
2647 new ArrayList<>(capSet));
2648 break;
2649 case "clear":
2650 result = mInterface.clearUceRegistrationOverrideShell(subId);
2651 break;
2652 case "list":
2653 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2654 break;
2655 }
2656 } catch (RemoteException e) {
2657 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2658 getErrPrintWriter().println("Exception: " + e.getMessage());
2659 return -1;
2660 } catch (ServiceSpecificException sse) {
2661 // Reconstruct ImsException
2662 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2663 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2664 getErrPrintWriter().println("Exception: " + imsException);
2665 return -1;
2666 }
2667 if (result == null) {
2668 getErrPrintWriter().println("Service not available");
2669 return -1;
2670 }
2671 getOutPrintWriter().println(result);
2672 return 0;
2673 }
2674
2675 private int handleUceGetPidfXml() {
2676 int subId = getSubId("uce get-last-publish-pidf");
2677 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2678 return -1;
2679 }
2680
2681 String result;
2682 try {
2683 result = mInterface.getLastUcePidfXmlShell(subId);
2684 } catch (RemoteException e) {
2685 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2686 getErrPrintWriter().println("Exception: " + e.getMessage());
2687 return -1;
2688 } catch (ServiceSpecificException sse) {
2689 // Reconstruct ImsException
2690 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2691 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2692 getErrPrintWriter().println("Exception: " + imsException);
2693 return -1;
2694 }
2695 if (result == null) {
2696 getErrPrintWriter().println("Service not available");
2697 return -1;
2698 }
2699 getOutPrintWriter().println(result);
2700 return 0;
2701 }
2702
Hui Wang761a6682020-10-31 05:12:53 +00002703 private int handleSrcSetDeviceEnabledCommand() {
2704 String enabledStr = getNextArg();
2705 if (enabledStr == null) {
2706 return -1;
2707 }
2708
2709 try {
2710 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2711 if (VDBG) {
2712 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2713 }
2714 getOutPrintWriter().println("Done");
2715 } catch (NumberFormatException | RemoteException e) {
2716 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2717 getErrPrintWriter().println("Exception: " + e.getMessage());
2718 return -1;
2719 }
2720 return 0;
2721 }
2722
2723 private int handleSrcGetDeviceEnabledCommand() {
2724 boolean result = false;
2725 try {
2726 result = mInterface.getDeviceSingleRegistrationEnabled();
2727 } catch (RemoteException e) {
2728 return -1;
2729 }
2730 if (VDBG) {
2731 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2732 }
2733 getOutPrintWriter().println(result);
2734 return 0;
2735 }
2736
2737 private int handleSrcSetCarrierEnabledCommand() {
2738 //the release time value could be -1
2739 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2740 : SubscriptionManager.getDefaultSubscriptionId();
2741 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2742 return -1;
2743 }
2744
2745 String enabledStr = getNextArg();
2746 if (enabledStr == null) {
2747 return -1;
2748 }
2749
2750 try {
2751 boolean result =
2752 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2753 if (VDBG) {
2754 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2755 + enabledStr + ", result=" + result);
2756 }
2757 getOutPrintWriter().println(result);
2758 } catch (NumberFormatException | RemoteException e) {
2759 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2760 + enabledStr + ", error" + e.getMessage());
2761 getErrPrintWriter().println("Exception: " + e.getMessage());
2762 return -1;
2763 }
2764 return 0;
2765 }
2766
2767 private int handleSrcGetCarrierEnabledCommand() {
2768 int subId = getSubId("src get-carrier-enabled");
2769 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2770 return -1;
2771 }
2772
2773 boolean result = false;
2774 try {
2775 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2776 } catch (RemoteException e) {
2777 return -1;
2778 }
2779 if (VDBG) {
2780 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2781 }
2782 getOutPrintWriter().println(result);
2783 return 0;
2784 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002785
Hui Wangb647abe2021-02-26 09:33:38 -08002786 private int handleSrcSetFeatureValidationCommand() {
2787 //the release time value could be -1
2788 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2789 : SubscriptionManager.getDefaultSubscriptionId();
2790 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2791 return -1;
2792 }
2793
2794 String enabledStr = getNextArg();
2795 if (enabledStr == null) {
2796 return -1;
2797 }
2798
2799 try {
2800 boolean result =
2801 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2802 if (VDBG) {
2803 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2804 + enabledStr + ", result=" + result);
2805 }
2806 getOutPrintWriter().println(result);
2807 } catch (NumberFormatException | RemoteException e) {
2808 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2809 + enabledStr + ", error" + e.getMessage());
2810 getErrPrintWriter().println("Exception: " + e.getMessage());
2811 return -1;
2812 }
2813 return 0;
2814 }
2815
2816 private int handleSrcGetFeatureValidationCommand() {
2817 int subId = getSubId("src get-feature-validation");
2818 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2819 return -1;
2820 }
2821
2822 Boolean result = false;
2823 try {
2824 result = mInterface.getImsFeatureValidationOverride(subId);
2825 } catch (RemoteException e) {
2826 return -1;
2827 }
2828 if (VDBG) {
2829 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2830 }
2831 getOutPrintWriter().println(result);
2832 return 0;
2833 }
2834
2835
Hall Liuaa4211e2021-01-20 15:43:39 -08002836 private void onHelpCallComposer() {
2837 PrintWriter pw = getOutPrintWriter();
2838 pw.println("Call composer commands");
2839 pw.println(" callcomposer test-mode enable|disable|query");
2840 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2841 pw.println(" upload/download from carrier servers is disabled, and operations are");
2842 pw.println(" performed using emulated local files instead.");
2843 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2844 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2845 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002846 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2847 pw.println(" Enables or disables the user setting for call composer, as set by");
2848 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002849 }
2850
2851 private int handleCallComposerCommand() {
2852 String arg = getNextArg();
2853 if (arg == null) {
2854 onHelpCallComposer();
2855 return 0;
2856 }
2857
2858 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2859 "MODIFY_PHONE_STATE required for call composer shell cmds");
2860 switch (arg) {
2861 case CALL_COMPOSER_TEST_MODE: {
2862 String enabledStr = getNextArg();
2863 if (ENABLE.equals(enabledStr)) {
2864 CallComposerPictureManager.sTestMode = true;
2865 } else if (DISABLE.equals(enabledStr)) {
2866 CallComposerPictureManager.sTestMode = false;
2867 } else if (QUERY.equals(enabledStr)) {
2868 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2869 } else {
2870 onHelpCallComposer();
2871 return 1;
2872 }
2873 break;
2874 }
2875 case CALL_COMPOSER_SIMULATE_CALL: {
2876 int subscriptionId = Integer.valueOf(getNextArg());
2877 String uuidString = getNextArg();
2878 UUID uuid = UUID.fromString(uuidString);
2879 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2880 Binder.withCleanCallingIdentity(() -> {
2881 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2882 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2883 });
2884 try {
2885 Uri uri = storageUriFuture.get();
2886 getOutPrintWriter().println(String.valueOf(uri));
2887 } catch (Exception e) {
2888 throw new RuntimeException(e);
2889 }
2890 break;
2891 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002892 case CALL_COMPOSER_USER_SETTING: {
2893 try {
2894 int subscriptionId = Integer.valueOf(getNextArg());
2895 String enabledStr = getNextArg();
2896 if (ENABLE.equals(enabledStr)) {
2897 mInterface.setCallComposerStatus(subscriptionId,
2898 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2899 } else if (DISABLE.equals(enabledStr)) {
2900 mInterface.setCallComposerStatus(subscriptionId,
2901 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2902 } else if (QUERY.equals(enabledStr)) {
2903 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2904 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2905 } else {
2906 onHelpCallComposer();
2907 return 1;
2908 }
2909 } catch (RemoteException e) {
2910 e.printStackTrace(getOutPrintWriter());
2911 return 1;
2912 }
2913 break;
2914 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002915 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002916 return 0;
2917 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002918
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002919 private int handleHasCarrierPrivilegesCommand() {
2920 String packageName = getNextArgRequired();
2921
2922 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002923 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002924 try {
2925 hasCarrierPrivileges =
2926 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2927 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2928 } catch (RemoteException e) {
2929 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2930 getErrPrintWriter().println("Exception: " + e.getMessage());
2931 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002932 } finally {
2933 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002934 }
2935
2936 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002937 return 0;
2938 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002939
2940 private int handleAllowedNetworkTypesCommand(String command) {
2941 if (!checkShellUid()) {
2942 return -1;
2943 }
2944
2945 PrintWriter errPw = getErrPrintWriter();
2946 String tag = command + ": ";
2947 String opt;
2948 int subId = -1;
2949 Log.v(LOG_TAG, command + " start");
2950
2951 while ((opt = getNextOption()) != null) {
2952 if (opt.equals("-s")) {
2953 try {
2954 subId = slotStringToSubId(tag, getNextArgRequired());
2955 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2956 errPw.println(tag + "No valid subscription found.");
2957 return -1;
2958 }
2959 } catch (IllegalArgumentException e) {
2960 // Missing slot id
2961 errPw.println(tag + "SLOT_ID expected after -s.");
2962 return -1;
2963 }
2964 } else {
2965 errPw.println(tag + "Unknown option " + opt);
2966 return -1;
2967 }
2968 }
2969
2970 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2971 return handleGetAllowedNetworkTypesCommand(subId);
2972 }
2973 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2974 return handleSetAllowedNetworkTypesCommand(subId);
2975 }
2976 return -1;
2977 }
2978
2979 private int handleGetAllowedNetworkTypesCommand(int subId) {
2980 PrintWriter errPw = getErrPrintWriter();
2981
2982 long result = -1;
2983 try {
2984 if (mInterface != null) {
2985 result = mInterface.getAllowedNetworkTypesForReason(subId,
2986 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2987 } else {
2988 throw new IllegalStateException("telephony service is null.");
2989 }
2990 } catch (RemoteException e) {
2991 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2992 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2993 return -1;
2994 }
2995
2996 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2997 return 0;
2998 }
2999
3000 private int handleSetAllowedNetworkTypesCommand(int subId) {
3001 PrintWriter errPw = getErrPrintWriter();
3002
3003 String bitmaskString = getNextArg();
3004 if (TextUtils.isEmpty(bitmaskString)) {
3005 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
3006 return -1;
3007 }
3008 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
3009 if (allowedNetworkTypes < 0) {
3010 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
3011 return -1;
3012 }
3013 boolean result = false;
3014 try {
3015 if (mInterface != null) {
3016 result = mInterface.setAllowedNetworkTypesForReason(subId,
3017 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
3018 } else {
3019 throw new IllegalStateException("telephony service is null.");
3020 }
3021 } catch (RemoteException e) {
3022 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
3023 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
3024 return -1;
3025 }
3026
3027 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
3028 if (result) {
3029 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3030 }
3031 getOutPrintWriter().println(resultMessage);
3032 return 0;
3033 }
3034
3035 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3036 if (TextUtils.isEmpty(bitmaskString)) {
3037 return -1;
3038 }
3039 if (VDBG) {
3040 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3041 + ", length: " + bitmaskString.length());
3042 }
3043 try {
3044 return Long.parseLong(bitmaskString, 2);
3045 } catch (NumberFormatException e) {
3046 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3047 return -1;
3048 }
3049 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003050
jimsun3b9ccac2021-10-26 15:01:23 +08003051 private int handleRadioSetModemServiceCommand() {
3052 PrintWriter errPw = getErrPrintWriter();
3053 String serviceName = null;
3054
3055 String opt;
3056 while ((opt = getNextOption()) != null) {
3057 switch (opt) {
3058 case "-s": {
3059 serviceName = getNextArgRequired();
3060 break;
3061 }
3062 }
3063 }
3064
3065 try {
3066 boolean result = mInterface.setModemService(serviceName);
3067 if (VDBG) {
3068 Log.v(LOG_TAG,
3069 "RadioSetModemService " + serviceName + ", result = " + result);
3070 }
3071 getOutPrintWriter().println(result);
3072 } catch (RemoteException e) {
3073 Log.w(LOG_TAG,
3074 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3075 errPw.println("Exception: " + e.getMessage());
3076 return -1;
3077 }
3078 return 0;
3079 }
3080
3081 private int handleRadioGetModemServiceCommand() {
3082 PrintWriter errPw = getErrPrintWriter();
3083 String result;
3084
3085 try {
3086 result = mInterface.getModemService();
3087 getOutPrintWriter().println(result);
3088 } catch (RemoteException e) {
3089 errPw.println("Exception: " + e.getMessage());
3090 return -1;
3091 }
3092 if (VDBG) {
3093 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3094 }
3095 return 0;
3096 }
3097
3098 private int handleRadioCommand() {
3099 String arg = getNextArg();
3100 if (arg == null) {
3101 onHelpRadio();
3102 return 0;
3103 }
3104
3105 switch (arg) {
3106 case RADIO_SET_MODEM_SERVICE:
3107 return handleRadioSetModemServiceCommand();
3108
3109 case RADIO_GET_MODEM_SERVICE:
3110 return handleRadioGetModemServiceCommand();
3111 }
3112
3113 return -1;
3114 }
arunvoddud7401012022-12-15 16:08:12 +00003115
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003116 private int handleSetSatelliteServicePackageNameCommand() {
3117 PrintWriter errPw = getErrPrintWriter();
3118 String serviceName = null;
3119
3120 String opt;
3121 while ((opt = getNextOption()) != null) {
3122 switch (opt) {
3123 case "-s": {
3124 serviceName = getNextArgRequired();
3125 break;
3126 }
3127 }
3128 }
3129 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3130 + serviceName);
3131
3132 try {
3133 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3134 if (VDBG) {
3135 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3136 + ", result = " + result);
3137 }
3138 getOutPrintWriter().println(result);
3139 } catch (RemoteException e) {
3140 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3141 + ", error = " + e.getMessage());
3142 errPw.println("Exception: " + e.getMessage());
3143 return -1;
3144 }
3145 return 0;
3146 }
3147
Thomas Nguyen1854a5a2023-04-04 09:31:47 -07003148 private int handleSetSatelliteGatewayServicePackageNameCommand() {
3149 PrintWriter errPw = getErrPrintWriter();
3150 String serviceName = null;
3151
3152 String opt;
3153 while ((opt = getNextOption()) != null) {
3154 switch (opt) {
3155 case "-s": {
3156 serviceName = getNextArgRequired();
3157 break;
3158 }
3159 }
3160 }
3161 Log.d(LOG_TAG, "handleSetSatelliteGatewayServicePackageNameCommand: serviceName="
3162 + serviceName);
3163
3164 try {
3165 boolean result = mInterface.setSatelliteGatewayServicePackageName(serviceName);
3166 if (VDBG) {
3167 Log.v(LOG_TAG, "setSatelliteGatewayServicePackageName " + serviceName
3168 + ", result = " + result);
3169 }
3170 getOutPrintWriter().println(result);
3171 } catch (RemoteException e) {
3172 Log.w(LOG_TAG, "setSatelliteGatewayServicePackageName: " + serviceName
3173 + ", error = " + e.getMessage());
3174 errPw.println("Exception: " + e.getMessage());
3175 return -1;
3176 }
3177 return 0;
3178 }
3179
Thomas Nguyen87dce732023-04-20 18:27:16 -07003180 private int handleSetSatellitePointingUiClassNameCommand() {
3181 PrintWriter errPw = getErrPrintWriter();
3182 String packageName = null;
3183 String className = null;
3184
3185 String opt;
3186 while ((opt = getNextOption()) != null) {
3187 switch (opt) {
3188 case "-p": {
3189 packageName = getNextArgRequired();
3190 break;
3191 }
3192 case "-c": {
3193 className = getNextArgRequired();
3194 break;
3195 }
3196 }
3197 }
3198 Log.d(LOG_TAG, "handleSetSatellitePointingUiClassNameCommand: packageName="
3199 + packageName + ", className=" + className);
3200
3201 try {
3202 boolean result = mInterface.setSatellitePointingUiClassName(packageName, className);
3203 if (VDBG) {
3204 Log.v(LOG_TAG, "setSatellitePointingUiClassName result =" + result);
3205 }
3206 getOutPrintWriter().println(result);
3207 } catch (RemoteException e) {
3208 Log.e(LOG_TAG, "setSatellitePointingUiClassName: " + packageName
3209 + ", error = " + e.getMessage());
3210 errPw.println("Exception: " + e.getMessage());
3211 return -1;
3212 }
3213 return 0;
3214 }
3215
Thomas Nguyenf9a533c2023-04-06 20:48:41 -07003216 private int handleSetSatelliteListeningTimeoutDuration() {
3217 PrintWriter errPw = getErrPrintWriter();
3218 long timeoutMillis = 0;
3219
3220 String opt;
3221 while ((opt = getNextOption()) != null) {
3222 switch (opt) {
3223 case "-t": {
3224 timeoutMillis = Long.parseLong(getNextArgRequired());
3225 break;
3226 }
3227 }
3228 }
3229 Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
3230 + timeoutMillis);
3231
3232 try {
3233 boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
3234 if (VDBG) {
3235 Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
3236 + ", result = " + result);
3237 }
3238 getOutPrintWriter().println(result);
3239 } catch (RemoteException e) {
3240 Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
3241 + ", error = " + e.getMessage());
3242 errPw.println("Exception: " + e.getMessage());
3243 return -1;
3244 }
3245 return 0;
3246 }
3247
arunvoddud7401012022-12-15 16:08:12 +00003248 private int handleCarrierRestrictionStatusCommand() {
3249 try {
3250 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3251 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3252 mInterface.getModemService()))) {
3253 Log.v(LOG_TAG,
3254 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3255 + " checkShellUid fails");
3256 return -1;
3257 }
3258 } catch (RemoteException ex) {
3259 ex.printStackTrace();
3260 }
3261 String callerInfo = getNextOption();
3262 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3263 if (TextUtils.isEmpty(callerInfo)) {
3264 // reset the Json content after testing
3265 allowListInfo.updateJsonForTest(null);
3266 return 0;
3267 }
3268 if (callerInfo.startsWith("--")) {
3269 callerInfo = callerInfo.replace("--", "");
3270 }
3271 String params[] = callerInfo.split(",");
3272 StringBuffer jsonStrBuffer = new StringBuffer();
3273 String tokens;
3274 for (int index = 0; index < params.length; index++) {
3275 tokens = convertToJsonString(index, params[index]);
3276 if (TextUtils.isEmpty(tokens)) {
3277 // received wrong format from CTS
3278 if (VDBG) {
3279 Log.v(LOG_TAG,
3280 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3281 }
3282 return -1;
3283 }
3284 jsonStrBuffer.append(tokens);
3285 }
3286 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3287 return result;
3288 }
3289
Benedict Wong66477622023-02-03 23:30:57 +00003290 // set-carrier-service-package-override
3291 private int setCarrierServicePackageOverride() {
3292 PrintWriter errPw = getErrPrintWriter();
3293 int subId = SubscriptionManager.getDefaultSubscriptionId();
3294
3295 String opt;
3296 while ((opt = getNextOption()) != null) {
3297 switch (opt) {
3298 case "-s":
3299 try {
3300 subId = Integer.parseInt(getNextArgRequired());
3301 } catch (NumberFormatException e) {
3302 errPw.println(
3303 "set-carrier-service-package-override requires an integer as a"
3304 + " subscription ID.");
3305 return -1;
3306 }
3307 break;
3308 }
3309 }
3310
3311 String packageName = getNextArg();
3312 if (packageName == null) {
3313 errPw.println("set-carrier-service-package-override requires a override package name.");
3314 return -1;
3315 }
3316
3317 try {
3318 mInterface.setCarrierServicePackageOverride(
3319 subId, packageName, mContext.getOpPackageName());
3320
3321 if (VDBG) {
3322 Log.v(
3323 LOG_TAG,
3324 "set-carrier-service-package-override -s " + subId + " " + packageName);
3325 }
3326 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3327 Log.w(
3328 LOG_TAG,
3329 "set-carrier-service-package-override -s "
3330 + subId
3331 + " "
3332 + packageName
3333 + ", error"
3334 + e.getMessage());
3335 errPw.println("Exception: " + e.getMessage());
3336 return -1;
3337 }
3338 return 0;
3339 }
3340
3341 // clear-carrier-service-package-override
3342 private int clearCarrierServicePackageOverride() {
3343 PrintWriter errPw = getErrPrintWriter();
3344 int subId = getDefaultSlot();
3345
3346 String opt;
3347 while ((opt = getNextOption()) != null) {
3348 switch (opt) {
3349 case "-s":
3350 try {
3351 subId = Integer.parseInt(getNextArgRequired());
3352 } catch (NumberFormatException e) {
3353 errPw.println(
3354 "clear-carrier-service-package-override requires an integer as a"
3355 + " subscription ID.");
3356 return -1;
3357 }
3358 break;
3359 }
3360 }
3361
3362 try {
3363 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3364
3365 if (VDBG) {
3366 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3367 }
3368 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3369 Log.w(
3370 LOG_TAG,
3371 "clear-carrier-service-package-override -s "
3372 + subId
3373 + ", error"
3374 + e.getMessage());
3375 errPw.println("Exception: " + e.getMessage());
3376 return -1;
3377 }
3378 return 0;
3379 }
arunvoddud7401012022-12-15 16:08:12 +00003380
3381 /**
3382 * Building the string that can be used to build the JsonObject which supports to stub the data
3383 * in CarrierAllowListInfo for CTS testing. sample format is like
3384 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3385 */
3386 private String convertToJsonString(int index, String param) {
3387
3388 String token[] = param.split(":");
3389 String jSonString;
3390 switch (index) {
3391 case 0:
3392 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3393 break;
3394 case 1:
3395 jSonString =
3396 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3397 break;
3398 case 2:
3399 jSonString =
3400 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3401 break;
3402 default:
3403 jSonString = null;
3404 }
3405 return jSonString;
3406 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003407}