blob: 3e3d31dd8c8676696b0855efbbfa8ce7c6b23496 [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;
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -080027import android.annotation.NonNull;
28import android.annotation.Nullable;
Hunsuk Choi13078be2023-09-13 10:55:21 +000029import android.content.ComponentName;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080031import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080032import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010033import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080034import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070035import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000036import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070037import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070038import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010039import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070040import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070041import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000042import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070043import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080044import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000045import android.telephony.ims.ImsException;
46import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080047import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080048import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000049import android.util.ArrayMap;
50import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070051import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070052import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070053
Brad Ebinger14d467f2021-02-12 06:18:28 +000054import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070055import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080056import com.android.internal.telephony.Phone;
57import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080058import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080059import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080060import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080061import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080062import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000063import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000064import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070065
Allen Xuee00f0e2022-03-14 21:04:49 +000066import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070067import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080068import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000069import java.util.Arrays;
70import java.util.Collections;
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -080071import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080072import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000073import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010074import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000075import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010076import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080077import java.util.UUID;
78import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070079
80/**
81 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
82 * permission checks have been done before onCommand was called. Make sure any commands processed
83 * here also contain the appropriate permissions checks.
84 */
85
Hall Liua1548bd2019-12-24 14:14:12 -080086public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070087
88 private static final String LOG_TAG = "TelephonyShellCommand";
89 // Don't commit with this true.
90 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070091 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070092
Hall Liuaa4211e2021-01-20 15:43:39 -080093 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070094 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080095 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080096 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080097 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070098 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000099 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +0000100 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100101 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -0800102 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -0800103 private static final String ENABLE = "enable";
104 private static final String DISABLE = "disable";
105 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000106 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000107 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
108 "set-carrier-service-package-override";
109 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
110 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000111 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800112
Hall Liu7135e502021-02-04 16:58:17 -0800113 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800114 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800115 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800116
Brad Ebinger999d3302020-11-25 14:31:39 -0800117 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
118 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
119 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700120 // Used to disable or enable processing of conference event package data from the network.
121 // This is handy for testing scenarios where CEP data does not exist on a network which does
122 // support CEP data.
123 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700124
Hall Liud892bec2018-11-30 14:51:45 -0800125 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800126 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800127
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100128 private static final String CC_GET_VALUE = "get-value";
129 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000130 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100131 private static final String CC_CLEAR_VALUES = "clear-values";
132
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000133 private static final String EUICC_SUBCOMMAND = "euicc";
134 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
135
Hui Wang641e81c2020-10-12 12:14:23 -0700136 private static final String GBA_SUBCOMMAND = "gba";
137 private static final String GBA_SET_SERVICE = "set-service";
138 private static final String GBA_GET_SERVICE = "get-service";
139 private static final String GBA_SET_RELEASE_TIME = "set-release";
140 private static final String GBA_GET_RELEASE_TIME = "get-release";
141
Hui Wang761a6682020-10-31 05:12:53 +0000142 private static final String SINGLE_REGISTATION_CONFIG = "src";
143 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
144 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
145 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
146 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800147 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
148 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800149 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
150 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000151
Tyler Gunn92479152021-01-20 16:30:10 -0800152 private static final String D2D_SUBCOMMAND = "d2d";
153 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800154 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700155 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800156
Nazanin014f41e2021-05-06 17:26:31 -0700157 private static final String BARRING_SUBCOMMAND = "barring";
158 private static final String BARRING_SEND_INFO = "send";
159
James.cf Linbcdf8b32021-01-14 16:44:13 +0800160 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800161 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800162 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800163 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800164 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
165 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000166 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
167 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800168 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
169 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800170 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
171 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800172
jimsun3b9ccac2021-10-26 15:01:23 +0800173 private static final String RADIO_SUBCOMMAND = "radio";
174 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
175 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
176
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800177 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
178 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
179
Jordan Liu0ccee222021-04-27 11:55:13 -0700180 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
181 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
182
Jack Nudelman644b91a2021-03-12 14:09:48 -0800183 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
184 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
185 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700186 private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
187 "set-satellite-service-package-name";
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700188 private static final String SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME =
189 "set-satellite-gateway-service-package-name";
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700190 private static final String SET_SATELLITE_LISTENING_TIMEOUT_DURATION =
191 "set-satellite-listening-timeout-duration";
Thomas Nguyen87dce732023-04-20 18:27:16 -0700192 private static final String SET_SATELLITE_POINTING_UI_CLASS_NAME =
193 "set-satellite-pointing-ui-class-name";
Hakjun Choiae365972023-04-25 11:00:31 +0000194 private static final String SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION =
195 "set-satellite-device-aligned-timeout-duration";
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700196 private static final String SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE =
197 "set-emergency-call-to-satellite-handover-type";
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800198 private static final String SET_COUNTRY_CODES = "set-country-codes";
199 private static final String SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS =
200 "set-satellite-access-control-overlay-configs";
Thomas Nguyen3d602742024-01-19 11:29:35 -0800201 private static final String SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS =
202 "set-oem-enabled-satellite-provision-status";
Hakjun Choibc6ce992023-11-07 16:04:33 +0000203 private static final String SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE =
204 "set-should-send-datagram-to-modem-in-demo-mode";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800205
Hunsuk Choi13078be2023-09-13 10:55:21 +0000206 private static final String DOMAIN_SELECTION_SUBCOMMAND = "domainselection";
207 private static final String DOMAIN_SELECTION_SET_SERVICE_OVERRIDE = "set-dss-override";
208 private static final String DOMAIN_SELECTION_CLEAR_SERVICE_OVERRIDE = "clear-dss-override";
209
Grant Menke567d48f2022-08-18 20:19:10 +0000210 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
211 + "'*', '#' or '+') needs to be specified after -a in the command ";
212
213 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
214 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
215 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
216
SongFerngWang98dd5992021-05-13 17:50:00 +0800217 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
218 "get-allowed-network-types-for-users";
219 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
220 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000221 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000222 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700223 // Take advantage of existing methods that already contain permissions checks when possible.
224 private final ITelephony mInterface;
225
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100226 private SubscriptionManager mSubscriptionManager;
227 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700228 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700229 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100230
231 private enum CcType {
232 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000233 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100234 }
235
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100236 private class CcOptionParseResult {
237 public int mSubId;
238 public boolean mPersistent;
239 }
240
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100241 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
242 // keys by looking at the end of the string which usually tells the type.
243 // For instance: "xxxx_string", "xxxx_string_array", etc.
244 // The carrier config keys in this map does not follow this convention. It is therefore not
245 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700246 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
247 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
248 CcType.STRING),
249 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
250 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
251 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
252 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
253 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
254 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
255 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
256 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
257 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
258 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
259 CcType.STRING),
260 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
261 CcType.STRING_ARRAY),
262 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
263 CcType.STRING_ARRAY),
264 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
265 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
266 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
267 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
268 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
269 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
270 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
271 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100272
Brad Ebinger14d467f2021-02-12 06:18:28 +0000273 /**
274 * Map from a shorthand string to the feature tags required in registration required in order
275 * for the RCS feature to be considered "capable".
276 */
277 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
278 static {
279 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
280 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
281 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
282 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
283 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
284 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
285 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
286 FeatureTags.FEATURE_TAG_VIDEO)));
287 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
288 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
289 map.put("call_comp",
290 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
291 map.put("call_comp_mmtel",
292 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
293 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
294 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
295 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
296 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
297 // version
298 map.put("chatbot", new ArraySet<>(Arrays.asList(
299 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
300 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
301 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
302 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000303 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000304 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
305 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
306 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
307 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
308 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000309 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000310 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
311 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
312 }
313
314
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100315 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700316 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100317 mCarrierConfigManager =
318 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
319 mSubscriptionManager = (SubscriptionManager)
320 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700321 mTelephonyRegistryManager = (TelephonyRegistryManager)
322 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700323 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700324 }
325
326 @Override
327 public int onCommand(String cmd) {
328 if (cmd == null) {
329 return handleDefaultCommands(null);
330 }
331
332 switch (cmd) {
333 case IMS_SUBCOMMAND: {
334 return handleImsCommand();
335 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800336 case RCS_UCE_COMMAND:
337 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800338 case NUMBER_VERIFICATION_SUBCOMMAND:
339 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800340 case EMERGENCY_CALLBACK_MODE:
341 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800342 case EMERGENCY_NUMBER_TEST_MODE:
343 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100344 case CARRIER_CONFIG_SUBCOMMAND: {
345 return handleCcCommand();
346 }
Shuo Qianf5125122019-12-16 17:03:07 -0800347 case DATA_TEST_MODE:
348 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700349 case END_BLOCK_SUPPRESSION:
350 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000351 case EUICC_SUBCOMMAND:
352 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700353 case GBA_SUBCOMMAND:
354 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800355 case D2D_SUBCOMMAND:
356 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700357 case BARRING_SUBCOMMAND:
358 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000359 case SINGLE_REGISTATION_CONFIG:
360 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000361 case RESTART_MODEM:
362 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800363 case CALL_COMPOSER_SUBCOMMAND:
364 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000365 case UNATTENDED_REBOOT:
366 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800367 case HAS_CARRIER_PRIVILEGES_COMMAND:
368 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800369 case THERMAL_MITIGATION_COMMAND:
370 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700371 case DISABLE_PHYSICAL_SUBSCRIPTION:
372 return handleEnablePhysicalSubscription(false);
373 case ENABLE_PHYSICAL_SUBSCRIPTION:
374 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800375 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
376 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
377 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000378 case GET_IMEI:
379 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000380 case GET_SIM_SLOTS_MAPPING:
381 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800382 case RADIO_SUBCOMMAND:
383 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000384 case CARRIER_RESTRICTION_STATUS_TEST:
385 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000386 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
387 return setCarrierServicePackageOverride();
388 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
389 return clearCarrierServicePackageOverride();
Hunsuk Choi13078be2023-09-13 10:55:21 +0000390 case DOMAIN_SELECTION_SUBCOMMAND:
391 return handleDomainSelectionCommand();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700392 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
393 return handleSetSatelliteServicePackageNameCommand();
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700394 case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
395 return handleSetSatelliteGatewayServicePackageNameCommand();
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700396 case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
397 return handleSetSatelliteListeningTimeoutDuration();
Thomas Nguyen87dce732023-04-20 18:27:16 -0700398 case SET_SATELLITE_POINTING_UI_CLASS_NAME:
399 return handleSetSatellitePointingUiClassNameCommand();
Hakjun Choiae365972023-04-25 11:00:31 +0000400 case SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION:
401 return handleSettSatelliteDeviceAlignedTimeoutDuration();
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700402 case SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE:
403 return handleSetEmergencyCallToSatelliteHandoverType();
Hakjun Choibc6ce992023-11-07 16:04:33 +0000404 case SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE:
405 return handleSetShouldSendDatagramToModemInDemoMode();
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800406 case SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS:
407 return handleSetSatelliteAccessControlOverlayConfigs();
408 case SET_COUNTRY_CODES:
409 return handleSetCountryCodes();
Thomas Nguyen3d602742024-01-19 11:29:35 -0800410 case SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS:
411 return handleSetOemEnabledSatelliteProvisionStatus();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700412 default: {
413 return handleDefaultCommands(cmd);
414 }
415 }
416 }
417
418 @Override
419 public void onHelp() {
420 PrintWriter pw = getOutPrintWriter();
421 pw.println("Telephony Commands:");
422 pw.println(" help");
423 pw.println(" Print this help text.");
424 pw.println(" ims");
425 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800426 pw.println(" uce");
427 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800428 pw.println(" emergency-number-test-mode");
429 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700430 pw.println(" end-block-suppression");
431 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800432 pw.println(" data");
433 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100434 pw.println(" cc");
435 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700436 pw.println(" gba");
437 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000438 pw.println(" src");
439 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000440 pw.println(" restart-modem");
441 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000442 pw.println(" unattended-reboot");
443 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800444 pw.println(" has-carrier-privileges [package]");
445 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800446 pw.println(" get-allowed-network-types-for-users");
447 pw.println(" Get the Allowed Network Types.");
448 pw.println(" set-allowed-network-types-for-users");
449 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800450 pw.println(" radio");
451 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700452 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800453 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800454 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700455 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800456 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100457 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700458 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000459 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800460 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700461 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800462 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800463 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000464 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700465 onHelpSatellite();
Hunsuk Choi13078be2023-09-13 10:55:21 +0000466 onHelpDomainSelection();
Tyler Gunn92479152021-01-20 16:30:10 -0800467 }
468
469 private void onHelpD2D() {
470 PrintWriter pw = getOutPrintWriter();
471 pw.println("D2D Comms Commands:");
472 pw.println(" d2d send TYPE VALUE");
473 pw.println(" Sends a D2D message of specified type and value.");
474 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
475 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
476 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
477 MESSAGE_CALL_AUDIO_CODEC));
478 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
479 + Communicator.messageToString(
480 MESSAGE_DEVICE_BATTERY_STATE));
481 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
482 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800483 pw.println(" d2d transport TYPE");
484 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
485 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700486 pw.println(" d2d set-device-support true/default");
487 pw.println(" true - forces device support to be enabled for D2D.");
488 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
489 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700490 }
491
Nazanin014f41e2021-05-06 17:26:31 -0700492 private void onHelpBarring() {
493 PrintWriter pw = getOutPrintWriter();
494 pw.println("Barring Commands:");
495 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
496 + " -t CONDITIONAL_BARRING_TIME_SECS");
497 pw.println(" Notifies of a barring info change for the specified slot id.");
498 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
499 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
500 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
501 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
502 }
503
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700504 private void onHelpIms() {
505 PrintWriter pw = getOutPrintWriter();
506 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800507 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700508 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
509 pw.println(" ImsService. Options are:");
510 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
511 pw.println(" is specified, it will choose the default voice SIM slot.");
512 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
513 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800514 pw.println(" -f: Set the feature that this override if for, if no option is");
515 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700516 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
517 pw.println(" Gets the package name of the currently defined ImsService.");
518 pw.println(" Options are:");
519 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
520 pw.println(" is specified, it will choose the default voice SIM slot.");
521 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000522 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800523 pw.println(" -f: The feature type that the query will be requested for. If none is");
524 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800525 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
526 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
527 pw.println(" configuration overrides. Options are:");
528 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
529 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700530 pw.println(" ims enable [-s SLOT_ID]");
531 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
532 pw.println(" if none is specified.");
533 pw.println(" ims disable [-s SLOT_ID]");
534 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
535 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700536 pw.println(" ims conference-event-package [enable/disable]");
537 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700538 }
539
James.cf Linbcdf8b32021-01-14 16:44:13 +0800540 private void onHelpUce() {
541 PrintWriter pw = getOutPrintWriter();
542 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800543 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
544 pw.println(" Get the EAB contacts from the EAB database.");
545 pw.println(" Options are:");
546 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
547 pw.println(" Expected output format :");
548 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800549 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
550 pw.println(" Remove the EAB contacts from the EAB database.");
551 pw.println(" Options are:");
552 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
553 pw.println(" is specified, it will choose the default voice SIM slot.");
554 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800555 pw.println(" uce get-device-enabled");
556 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
557 pw.println(" uce set-device-enabled true|false");
558 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
559 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000560 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
561 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
562 pw.println(" Options are:");
563 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
564 pw.println(" is specified, it will choose the default voice SIM slot.");
565 pw.println(" add [CAPABILITY]: add a new capability");
566 pw.println(" remove [CAPABILITY]: remove a capability");
567 pw.println(" clear: clear all capability overrides");
568 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
569 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
570 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
571 pw.println(" chatbot_sa, chatbot_role] as well as full length");
572 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
573 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
574 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
575 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800576 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
577 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800578 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
579 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800580 }
581
Hall Liud892bec2018-11-30 14:51:45 -0800582 private void onHelpNumberVerification() {
583 PrintWriter pw = getOutPrintWriter();
584 pw.println("Number verification commands");
585 pw.println(" numverify override-package PACKAGE_NAME;");
586 pw.println(" Set the authorized package for number verification.");
587 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800588 pw.println(" numverify fake-call NUMBER;");
589 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
590 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800591 }
592
Jack Nudelman644b91a2021-03-12 14:09:48 -0800593 private void onHelpThermalMitigation() {
594 PrintWriter pw = getOutPrintWriter();
595 pw.println("Thermal mitigation commands");
596 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
597 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
598 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
599 pw.println(" Remove the package from one of the authorized packages for thermal "
600 + "mitigation.");
601 }
602
Jordan Liu0ccee222021-04-27 11:55:13 -0700603 private void onHelpDisableOrEnablePhysicalSubscription() {
604 PrintWriter pw = getOutPrintWriter();
605 pw.println("Disable or enable a physical subscription");
606 pw.println(" disable-physical-subscription SUB_ID");
607 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
608 pw.println(" enable-physical-subscription SUB_ID");
609 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
610 }
611
Shuo Qianf5125122019-12-16 17:03:07 -0800612 private void onHelpDataTestMode() {
613 PrintWriter pw = getOutPrintWriter();
614 pw.println("Mobile Data Test Mode Commands:");
615 pw.println(" data enable: enable mobile data connectivity");
616 pw.println(" data disable: disable mobile data connectivity");
617 }
618
sqian9d4df8b2019-01-15 18:32:07 -0800619 private void onHelpEmergencyNumber() {
620 PrintWriter pw = getOutPrintWriter();
621 pw.println("Emergency Number Test Mode Commands:");
622 pw.println(" emergency-number-test-mode ");
623 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
624 + " the test mode");
625 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700626 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800627 pw.println(" -c: clear the emergency number list in the test mode.");
628 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700629 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800630 pw.println(" -p: get the full emergency number list in the test mode.");
631 }
632
Shuo Qian489d9282020-07-09 11:30:03 -0700633 private void onHelpEndBlockSupperssion() {
634 PrintWriter pw = getOutPrintWriter();
635 pw.println("End Block Suppression command:");
636 pw.println(" end-block-suppression: disable suppressing blocking by contact");
637 pw.println(" with emergency services.");
638 }
639
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100640 private void onHelpCc() {
641 PrintWriter pw = getOutPrintWriter();
642 pw.println("Carrier Config Commands:");
643 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
644 pw.println(" Print carrier config values.");
645 pw.println(" Options are:");
646 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
647 pw.println(" is specified, it will choose the default voice SIM slot.");
648 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
649 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100650 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100651 pw.println(" Set carrier config KEY to NEW_VALUE.");
652 pw.println(" Options are:");
653 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
654 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100655 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100656 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
657 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
658 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
659 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000660 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
661 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
662 pw.println(" provided through standard input and follow CarrierConfig XML format.");
663 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
664 pw.println(" Options are:");
665 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
666 pw.println(" is specified, it will choose the default voice SIM slot.");
667 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100668 pw.println(" cc clear-values [-s SLOT_ID]");
669 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000670 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100671 pw.println(" Options are:");
672 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
673 pw.println(" is specified, it will choose the default voice SIM slot.");
674 }
675
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000676 private void onHelpEuicc() {
677 PrintWriter pw = getOutPrintWriter();
678 pw.println("Euicc Commands:");
679 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
680 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
681 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
682 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
683 }
684
Hui Wang641e81c2020-10-12 12:14:23 -0700685 private void onHelpGba() {
686 PrintWriter pw = getOutPrintWriter();
687 pw.println("Gba Commands:");
688 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
689 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
690 pw.println(" Options are:");
691 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
692 pw.println(" is specified, it will choose the default voice SIM slot.");
693 pw.println(" gba get-service [-s SLOT_ID]");
694 pw.println(" Gets the package name of the currently defined GbaService.");
695 pw.println(" Options are:");
696 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
697 pw.println(" is specified, it will choose the default voice SIM slot.");
698 pw.println(" gba set-release [-s SLOT_ID] n");
699 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
700 pw.println(" Do not release/unbind if n is -1.");
701 pw.println(" Options are:");
702 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
703 pw.println(" is specified, it will choose the default voice SIM slot.");
704 pw.println(" gba get-release [-s SLOT_ID]");
705 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
706 pw.println(" Options are:");
707 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
708 pw.println(" is specified, it will choose the default voice SIM slot.");
709 }
710
Hui Wang761a6682020-10-31 05:12:53 +0000711 private void onHelpSrc() {
712 PrintWriter pw = getOutPrintWriter();
713 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800714 pw.println(" src set-test-enabled true|false");
715 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
716 pw.println(" The value could be true, false, or null(undefined).");
717 pw.println(" src get-test-enabled");
718 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000719 pw.println(" src set-device-enabled true|false|null");
720 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
721 pw.println(" The value could be true, false, or null(undefined).");
722 pw.println(" src get-device-enabled");
723 pw.println(" Gets the device config for RCS VoLTE single registration.");
724 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
725 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
726 pw.println(" The value could be true, false, or null(undefined).");
727 pw.println(" Options are:");
728 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
729 pw.println(" is specified, it will choose the default voice SIM slot.");
730 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
731 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
732 pw.println(" Options are:");
733 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
734 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800735 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
736 pw.println(" Sets ims feature validation result.");
737 pw.println(" The value could be true, false, or null(undefined).");
738 pw.println(" Options are:");
739 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
740 pw.println(" is specified, it will choose the default voice SIM slot.");
741 pw.println(" src get-feature-validation [-s SLOT_ID]");
742 pw.println(" Gets ims feature validation override value.");
743 pw.println(" Options are:");
744 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
745 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000746 }
747
SongFerngWang98dd5992021-05-13 17:50:00 +0800748 private void onHelpAllowedNetworkTypes() {
749 PrintWriter pw = getOutPrintWriter();
750 pw.println("Allowed Network Types Commands:");
751 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
752 pw.println(" Print allowed network types value.");
753 pw.println(" Options are:");
754 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
755 pw.println(" option is specified, it will choose the default voice SIM slot.");
756 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
757 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
758 pw.println(" Options are:");
759 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
760 pw.println(" option is specified, it will choose the default voice SIM slot.");
761 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
762 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
763 pw.println(" at TelephonyManager.java");
764 pw.println(" For example:");
765 pw.println(" NR only : 10000000000000000000");
766 pw.println(" NR|LTE : 11000001000000000000");
767 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
768 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
769 pw.println(" LTE only : 01000001000000000000");
770 }
771
jimsun3b9ccac2021-10-26 15:01:23 +0800772 private void onHelpRadio() {
773 PrintWriter pw = getOutPrintWriter();
774 pw.println("Radio Commands:");
775 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
776 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
777 pw.println(" to be the bound. Options are:");
778 pw.println(" -s: the service name that the modem service should be bound for.");
779 pw.println(" If no option is specified, it will bind to the default.");
780 pw.println(" radio get-modem-service");
781 pw.println(" Gets the service name of the currently defined modem service.");
782 pw.println(" If it is binding to default, 'default' returns.");
783 pw.println(" If it doesn't bind to any modem service for some reasons,");
784 pw.println(" the result would be 'unknown'.");
785 }
786
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700787 private void onHelpSatellite() {
788 PrintWriter pw = getOutPrintWriter();
789 pw.println("Satellite Commands:");
790 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
791 pw.println(" Sets the package name of satellite service defined in");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700792 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700793 pw.println(" -s: the satellite service package name that Telephony will bind to.");
794 pw.println(" If no option is specified, it will bind to the default.");
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700795 pw.println(" set-satellite-gateway-service-package-name [-s SERVICE_PACKAGE_NAME]");
796 pw.println(" Sets the package name of satellite gateway service defined in");
797 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
798 pw.println(" -s: the satellite gateway service package name that Telephony will bind");
799 pw.println(" to. If no option is specified, it will bind to the default.");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700800 pw.println(" set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
801 pw.println(" Sets the timeout duration in millis that satellite will stay at listening");
802 pw.println(" mode. Options are:");
803 pw.println(" -t: the timeout duration in milliseconds.");
804 pw.println(" If no option is specified, it will use the default values.");
Thomas Nguyen87dce732023-04-20 18:27:16 -0700805 pw.println(" set-satellite-pointing-ui-class-name [-p PACKAGE_NAME -c CLASS_NAME]");
806 pw.println(" Sets the package and class name of satellite pointing UI app defined in");
807 pw.println(" PACKAGE_NAME and CLASS_NAME to be launched. Options are:");
808 pw.println(" -p: the satellite pointing UI app package name that Telephony will");
809 pw.println(" launch. If no option is specified, it will launch the default.");
810 pw.println(" -c: the satellite pointing UI app class name that Telephony will");
811 pw.println(" launch.");
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700812 pw.println(" set-emergency-call-to-satellite-handover-type [-t HANDOVER_TYPE ");
813 pw.println(" -d DELAY_SECONDS] Override connectivity status in monitoring emergency ");
814 pw.println(" call and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.");
815 pw.println(" Options are:");
816 pw.println(" -t: the emergency call to satellite handover type.");
817 pw.println(" If no option is specified, override is disabled.");
818 pw.println(" -d: the delay in seconds in sending EVENT_DISPLAY_EMERGENCY_MESSAGE.");
819 pw.println(" If no option is specified, there is no delay in sending the event.");
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800820 pw.println(" set-satellite-access-control-overlay-configs [-r -a -f SATELLITE_S2_FILE ");
821 pw.println(" -d LOCATION_FRESH_DURATION_NANOS -c COUNTRY_CODES] Override the overlay");
822 pw.println(" configs of satellite access controller.");
823 pw.println(" Options are:");
824 pw.println(" -r: clear the overriding. Absent means enable overriding.");
825 pw.println(" -a: the country codes is an allowed list. Absent means disallowed.");
826 pw.println(" -f: the satellite s2 file.");
827 pw.println(" -d: the location fresh duration nanos.");
828 pw.println(" -c: the list of satellite country codes separated by comma.");
829 pw.println(" set-country-codes [-r -n CURRENT_NETWORK_COUNTRY_CODES -c");
830 pw.println(" CACHED_NETWORK_COUNTRY_CODES -l LOCATION_COUNTRY_CODE -t");
831 pw.println(" LOCATION_COUNTRY_CODE_TIMESTAMP] ");
832 pw.println(" Override the cached location country code and its update timestamp. ");
833 pw.println(" Options are:");
834 pw.println(" -r: clear the overriding. Absent means enable overriding.");
835 pw.println(" -n: the current network country code ISOs.");
836 pw.println(" -c: the cached network country code ISOs.");
837 pw.println(" -l: the location country code ISO.");
838 pw.println(" -t: the update timestamp nanos of the location country code.");
Thomas Nguyen3d602742024-01-19 11:29:35 -0800839 pw.println(" set-oem-enabled-satellite-provision-status [-p true/false]");
840 pw.println(" Sets the OEM-enabled satellite provision status. Options are:");
841 pw.println(" -p: the overriding satellite provision status. If no option is ");
842 pw.println(" specified, reset the overridden provision status.");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700843 }
844
Ling Ma4fbab492022-01-25 22:36:16 +0000845 private void onHelpImei() {
846 PrintWriter pw = getOutPrintWriter();
847 pw.println("IMEI Commands:");
848 pw.println(" get-imei [-s SLOT_ID]");
849 pw.println(" Gets the device IMEI. Options are:");
850 pw.println(" -s: the slot ID to get the IMEI. If no option");
851 pw.println(" is specified, it will choose the default voice SIM slot.");
852 }
853
Hunsuk Choi13078be2023-09-13 10:55:21 +0000854 private void onHelpDomainSelection() {
855 PrintWriter pw = getOutPrintWriter();
856 pw.println("Domain Selection Commands:");
857 pw.println(" domainselection set-dss-override COMPONENT_NAME");
858 pw.println(" Sets the service defined in COMPONENT_NAME to be bound");
859 pw.println(" domainselection clear-dss-override");
860 pw.println(" Clears DomainSelectionService override.");
861 }
862
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700863 private int handleImsCommand() {
864 String arg = getNextArg();
865 if (arg == null) {
866 onHelpIms();
867 return 0;
868 }
869
870 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800871 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700872 return handleImsSetServiceCommand();
873 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800874 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700875 return handleImsGetServiceCommand();
876 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800877 case IMS_CLEAR_SERVICE_OVERRIDE: {
878 return handleImsClearCarrierServiceCommand();
879 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800880 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700881 return handleEnableIms();
882 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800883 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700884 return handleDisableIms();
885 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700886 case IMS_CEP: {
887 return handleCepChange();
888 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700889 }
890
891 return -1;
892 }
893
Shuo Qianf5125122019-12-16 17:03:07 -0800894 private int handleDataTestModeCommand() {
895 PrintWriter errPw = getErrPrintWriter();
896 String arg = getNextArgRequired();
897 if (arg == null) {
898 onHelpDataTestMode();
899 return 0;
900 }
901 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800902 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800903 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700904 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800905 } catch (RemoteException ex) {
906 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
907 errPw.println("Exception: " + ex.getMessage());
908 return -1;
909 }
910 break;
911 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800912 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800913 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700914 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800915 } catch (RemoteException ex) {
916 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
917 errPw.println("Exception: " + ex.getMessage());
918 return -1;
919 }
920 break;
921 }
922 default:
923 onHelpDataTestMode();
924 break;
925 }
926 return 0;
927 }
928
Shuo Qianccbaf742021-02-22 18:32:21 -0800929 private int handleEmergencyCallbackModeCommand() {
930 PrintWriter errPw = getErrPrintWriter();
931 try {
932 mInterface.startEmergencyCallbackMode();
933 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
934 } catch (RemoteException ex) {
935 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
936 errPw.println("Exception: " + ex.getMessage());
937 return -1;
938 }
939 return 0;
940 }
941
Grant Menke567d48f2022-08-18 20:19:10 +0000942 private void removeEmergencyNumberTestMode(String emergencyNumber) {
943 PrintWriter errPw = getErrPrintWriter();
944 for (int routingType : ROUTING_TYPES) {
945 try {
946 mInterface.updateEmergencyNumberListTestMode(
947 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
948 new EmergencyNumber(emergencyNumber, "", "",
949 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
950 new ArrayList<String>(),
951 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
952 routingType));
953 } catch (RemoteException ex) {
954 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
955 errPw.println("Exception: " + ex.getMessage());
956 }
957 }
958 }
959
sqian9d4df8b2019-01-15 18:32:07 -0800960 private int handleEmergencyNumberTestModeCommand() {
961 PrintWriter errPw = getErrPrintWriter();
962 String opt = getNextOption();
963 if (opt == null) {
964 onHelpEmergencyNumber();
965 return 0;
966 }
sqian9d4df8b2019-01-15 18:32:07 -0800967 switch (opt) {
968 case "-a": {
969 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000970 if (emergencyNumberCmd == null){
971 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800972 return -1;
973 }
Grant Menke567d48f2022-08-18 20:19:10 +0000974 String[] params = emergencyNumberCmd.split(":");
975 String emergencyNumber;
976 if (params[0] == null ||
977 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
978 errPw.println(INVALID_ENTRY_ERROR);
979 return -1;
980 } else {
981 emergencyNumber = params[0];
982 }
983 removeEmergencyNumberTestMode(emergencyNumber);
984 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
985 if (params.length > 1) {
986 switch (params[1].toLowerCase(Locale.ROOT)) {
987 case "emergency":
988 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
989 break;
990 case "normal":
991 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
992 break;
993 case "unknown":
994 break;
995 default:
996 errPw.println("\"" + params[1] + "\" is not a valid specification for "
997 + "emergency call routing. Please enter either \"normal\", "
998 + "\"unknown\", or \"emergency\" for call routing. "
999 + "(-a 1234:normal)");
1000 return -1;
1001 }
1002 }
sqian9d4df8b2019-01-15 18:32:07 -08001003 try {
1004 mInterface.updateEmergencyNumberListTestMode(
1005 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +00001006 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -08001007 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
1008 new ArrayList<String>(),
1009 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +00001010 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -08001011 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +00001012 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -08001013 + ", error " + ex.getMessage());
1014 errPw.println("Exception: " + ex.getMessage());
1015 return -1;
1016 }
1017 break;
1018 }
1019 case "-c": {
1020 try {
1021 mInterface.updateEmergencyNumberListTestMode(
1022 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
1023 } catch (RemoteException ex) {
1024 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
1025 errPw.println("Exception: " + ex.getMessage());
1026 return -1;
1027 }
1028 break;
1029 }
1030 case "-r": {
1031 String emergencyNumberCmd = getNextArgRequired();
1032 if (emergencyNumberCmd == null
1033 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -07001034 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -08001035 + " to be specified after -r in the command ");
1036 return -1;
1037 }
Grant Menke567d48f2022-08-18 20:19:10 +00001038 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -08001039 break;
1040 }
1041 case "-p": {
1042 try {
1043 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
1044 } catch (RemoteException ex) {
1045 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
1046 errPw.println("Exception: " + ex.getMessage());
1047 return -1;
1048 }
1049 break;
1050 }
1051 default:
1052 onHelpEmergencyNumber();
1053 break;
1054 }
1055 return 0;
1056 }
1057
Hall Liud892bec2018-11-30 14:51:45 -08001058 private int handleNumberVerificationCommand() {
1059 String arg = getNextArg();
1060 if (arg == null) {
1061 onHelpNumberVerification();
1062 return 0;
1063 }
1064
Hall Liuca5af3a2018-12-04 16:58:23 -08001065 if (!checkShellUid()) {
1066 return -1;
1067 }
1068
Hall Liud892bec2018-11-30 14:51:45 -08001069 switch (arg) {
1070 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -08001071 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
1072 return 0;
1073 }
Hall Liuca5af3a2018-12-04 16:58:23 -08001074 case NUMBER_VERIFICATION_FAKE_CALL: {
1075 boolean val = NumberVerificationManager.getInstance()
1076 .checkIncomingCall(getNextArg());
1077 getOutPrintWriter().println(val ? "1" : "0");
1078 return 0;
1079 }
Hall Liud892bec2018-11-30 14:51:45 -08001080 }
1081
1082 return -1;
1083 }
1084
Jordan Liu0ccee222021-04-27 11:55:13 -07001085 private boolean subIsEsim(int subId) {
1086 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
1087 if (info != null) {
1088 return info.isEmbedded();
1089 }
1090 return false;
1091 }
1092
1093 private int handleEnablePhysicalSubscription(boolean enable) {
1094 PrintWriter errPw = getErrPrintWriter();
1095 int subId = 0;
1096 try {
1097 subId = Integer.parseInt(getNextArgRequired());
1098 } catch (NumberFormatException e) {
1099 errPw.println((enable ? "enable" : "disable")
1100 + "-physical-subscription requires an integer as a subId.");
1101 return -1;
1102 }
1103 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1104 // non user build.
1105 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1106 errPw.println("cc: Permission denied.");
1107 return -1;
1108 }
1109 // Verify that the subId represents a physical sub
1110 if (subIsEsim(subId)) {
1111 errPw.println("SubId " + subId + " is not for a physical subscription");
1112 return -1;
1113 }
1114 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1115 + " physical subscription with subId=" + subId);
1116 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1117 return 0;
1118 }
1119
Jack Nudelman644b91a2021-03-12 14:09:48 -08001120 private int handleThermalMitigationCommand() {
1121 String arg = getNextArg();
1122 String packageName = getNextArg();
1123 if (arg == null || packageName == null) {
1124 onHelpThermalMitigation();
1125 return 0;
1126 }
1127
1128 if (!checkShellUid()) {
1129 return -1;
1130 }
1131
1132 switch (arg) {
1133 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1134 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1135 return 0;
1136 }
1137 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1138 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1139 mContext);
1140 return 0;
1141 }
1142 default:
1143 onHelpThermalMitigation();
1144 }
1145
1146 return -1;
1147
1148 }
1149
Tyler Gunn92479152021-01-20 16:30:10 -08001150 private int handleD2dCommand() {
1151 String arg = getNextArg();
1152 if (arg == null) {
1153 onHelpD2D();
1154 return 0;
1155 }
1156
1157 switch (arg) {
1158 case D2D_SEND: {
1159 return handleD2dSendCommand();
1160 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001161 case D2D_TRANSPORT: {
1162 return handleD2dTransportCommand();
1163 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001164 case D2D_SET_DEVICE_SUPPORT: {
1165 return handleD2dDeviceSupportedCommand();
1166 }
Tyler Gunn92479152021-01-20 16:30:10 -08001167 }
1168
1169 return -1;
1170 }
1171
1172 private int handleD2dSendCommand() {
1173 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001174 int messageType = -1;
1175 int messageValue = -1;
1176
Tyler Gunn92479152021-01-20 16:30:10 -08001177 String arg = getNextArg();
1178 if (arg == null) {
1179 onHelpD2D();
1180 return 0;
1181 }
1182 try {
1183 messageType = Integer.parseInt(arg);
1184 } catch (NumberFormatException e) {
1185 errPw.println("message type must be a valid integer");
1186 return -1;
1187 }
1188
1189 arg = getNextArg();
1190 if (arg == null) {
1191 onHelpD2D();
1192 return 0;
1193 }
1194 try {
1195 messageValue = Integer.parseInt(arg);
1196 } catch (NumberFormatException e) {
1197 errPw.println("message value must be a valid integer");
1198 return -1;
1199 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001200
Tyler Gunn92479152021-01-20 16:30:10 -08001201 try {
1202 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1203 } catch (RemoteException e) {
1204 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1205 errPw.println("Exception: " + e.getMessage());
1206 return -1;
1207 }
1208
1209 return 0;
1210 }
1211
Tyler Gunnbabbda02021-02-10 11:05:02 -08001212 private int handleD2dTransportCommand() {
1213 PrintWriter errPw = getErrPrintWriter();
1214
1215 String arg = getNextArg();
1216 if (arg == null) {
1217 onHelpD2D();
1218 return 0;
1219 }
1220
1221 try {
1222 mInterface.setActiveDeviceToDeviceTransport(arg);
1223 } catch (RemoteException e) {
1224 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1225 errPw.println("Exception: " + e.getMessage());
1226 return -1;
1227 }
1228 return 0;
1229 }
Nazanin014f41e2021-05-06 17:26:31 -07001230 private int handleBarringCommand() {
1231 String arg = getNextArg();
1232 if (arg == null) {
1233 onHelpBarring();
1234 return 0;
1235 }
1236
1237 switch (arg) {
1238 case BARRING_SEND_INFO: {
1239 return handleBarringSendCommand();
1240 }
1241 }
1242 return -1;
1243 }
1244
1245 private int handleBarringSendCommand() {
1246 PrintWriter errPw = getErrPrintWriter();
1247 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001248 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001249 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1250 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1251 boolean isConditionallyBarred = false;
1252 int conditionalBarringTimeSeconds = 0;
1253
1254 String opt;
1255 while ((opt = getNextOption()) != null) {
1256 switch (opt) {
1257 case "-s": {
1258 try {
1259 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001260 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001261 } catch (NumberFormatException e) {
1262 errPw.println("barring send requires an integer as a SLOT_ID.");
1263 return -1;
1264 }
1265 break;
1266 }
1267 case "-b": {
1268 try {
1269 barringType = Integer.parseInt(getNextArgRequired());
1270 if (barringType < -1 || barringType > 2) {
1271 throw new NumberFormatException();
1272 }
1273
1274 } catch (NumberFormatException e) {
1275 errPw.println("barring send requires an integer in range [-1,2] as "
1276 + "a BARRING_TYPE.");
1277 return -1;
1278 }
1279 break;
1280 }
1281 case "-c": {
1282 try {
1283 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1284 } catch (Exception e) {
1285 errPw.println("barring send requires a boolean after -c indicating"
1286 + " conditional barring");
1287 return -1;
1288 }
1289 break;
1290 }
1291 case "-t": {
1292 try {
1293 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1294 } catch (NumberFormatException e) {
1295 errPw.println("barring send requires an integer for time of barring"
1296 + " in seconds after -t for conditional barring");
1297 return -1;
1298 }
1299 break;
1300 }
1301 }
1302 }
1303 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1304 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1305 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1306 barringServiceInfos.append(0, bsi);
1307 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1308 try {
1309 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1310 } catch (Exception e) {
1311 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1312 errPw.println("Exception: " + e.getMessage());
1313 return -1;
1314 }
1315 return 0;
1316 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001317
Tyler Gunnd4575212021-05-03 14:46:49 -07001318 private int handleD2dDeviceSupportedCommand() {
1319 PrintWriter errPw = getErrPrintWriter();
1320
1321 String arg = getNextArg();
1322 if (arg == null) {
1323 onHelpD2D();
1324 return 0;
1325 }
1326
Jack Yua533d632022-09-30 13:53:46 -07001327 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001328 try {
1329 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1330 } catch (RemoteException e) {
1331 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1332 errPw.println("Exception: " + e.getMessage());
1333 return -1;
1334 }
1335 return 0;
1336 }
1337
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001338 // ims set-ims-service
1339 private int handleImsSetServiceCommand() {
1340 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001341 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001342 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001343 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001344
1345 String opt;
1346 while ((opt = getNextOption()) != null) {
1347 switch (opt) {
1348 case "-s": {
1349 try {
1350 slotId = Integer.parseInt(getNextArgRequired());
1351 } catch (NumberFormatException e) {
1352 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1353 return -1;
1354 }
1355 break;
1356 }
1357 case "-c": {
1358 isCarrierService = true;
1359 break;
1360 }
1361 case "-d": {
1362 isCarrierService = false;
1363 break;
1364 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001365 case "-f": {
1366 String featureString = getNextArgRequired();
1367 String[] features = featureString.split(",");
1368 for (int i = 0; i < features.length; i++) {
1369 try {
1370 Integer result = Integer.parseInt(features[i]);
1371 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1372 || result >= ImsFeature.FEATURE_MAX) {
1373 errPw.println("ims set-ims-service -f " + result
1374 + " is an invalid feature.");
1375 return -1;
1376 }
1377 featuresList.add(result);
1378 } catch (NumberFormatException e) {
1379 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1380 + " as an integer.");
1381 return -1;
1382 }
1383 }
1384 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001385 }
1386 }
1387 // Mandatory param, either -c or -d
1388 if (isCarrierService == null) {
1389 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1390 return -1;
1391 }
1392
1393 String packageName = getNextArg();
1394
1395 try {
1396 if (packageName == null) {
1397 packageName = "";
1398 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001399 int[] featureArray = new int[featuresList.size()];
1400 for (int i = 0; i < featuresList.size(); i++) {
1401 featureArray[i] = featuresList.get(i);
1402 }
1403 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1404 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001405 if (VDBG) {
1406 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001407 + (isCarrierService ? "-c " : "-d ")
1408 + "-f " + featuresList + " "
1409 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001410 }
1411 getOutPrintWriter().println(result);
1412 } catch (RemoteException e) {
1413 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001414 + (isCarrierService ? "-c " : "-d ")
1415 + "-f " + featuresList + " "
1416 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001417 errPw.println("Exception: " + e.getMessage());
1418 return -1;
1419 }
1420 return 0;
1421 }
1422
Brad Ebinger999d3302020-11-25 14:31:39 -08001423 // ims clear-ims-service-override
1424 private int handleImsClearCarrierServiceCommand() {
1425 PrintWriter errPw = getErrPrintWriter();
1426 int slotId = getDefaultSlot();
1427
1428 String opt;
1429 while ((opt = getNextOption()) != null) {
1430 switch (opt) {
1431 case "-s": {
1432 try {
1433 slotId = Integer.parseInt(getNextArgRequired());
1434 } catch (NumberFormatException e) {
1435 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1436 return -1;
1437 }
1438 break;
1439 }
1440 }
1441 }
1442
1443 try {
1444 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1445 if (VDBG) {
1446 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1447 + ", result=" + result);
1448 }
1449 getOutPrintWriter().println(result);
1450 } catch (RemoteException e) {
1451 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1452 + ", error" + e.getMessage());
1453 errPw.println("Exception: " + e.getMessage());
1454 return -1;
1455 }
1456 return 0;
1457 }
1458
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001459 // ims get-ims-service
1460 private int handleImsGetServiceCommand() {
1461 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001462 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001463 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001464 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001465
1466 String opt;
1467 while ((opt = getNextOption()) != null) {
1468 switch (opt) {
1469 case "-s": {
1470 try {
1471 slotId = Integer.parseInt(getNextArgRequired());
1472 } catch (NumberFormatException e) {
1473 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1474 return -1;
1475 }
1476 break;
1477 }
1478 case "-c": {
1479 isCarrierService = true;
1480 break;
1481 }
1482 case "-d": {
1483 isCarrierService = false;
1484 break;
1485 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001486 case "-f": {
1487 try {
1488 featureType = Integer.parseInt(getNextArg());
1489 } catch (NumberFormatException e) {
1490 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1491 return -1;
1492 }
1493 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1494 || featureType >= ImsFeature.FEATURE_MAX) {
1495 errPw.println("ims get-ims-service -f invalid feature.");
1496 return -1;
1497 }
1498 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001499 }
1500 }
1501 // Mandatory param, either -c or -d
1502 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001503 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001504 return -1;
1505 }
1506
1507 String result;
1508 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001509 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001510 } catch (RemoteException e) {
1511 return -1;
1512 }
1513 if (VDBG) {
1514 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001515 + (isCarrierService ? "-c " : "-d ")
1516 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1517 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001518 }
1519 getOutPrintWriter().println(result);
1520 return 0;
1521 }
1522
1523 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001524 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001525 String opt;
1526 while ((opt = getNextOption()) != null) {
1527 switch (opt) {
1528 case "-s": {
1529 try {
1530 slotId = Integer.parseInt(getNextArgRequired());
1531 } catch (NumberFormatException e) {
1532 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1533 return -1;
1534 }
1535 break;
1536 }
1537 }
1538 }
1539 try {
1540 mInterface.enableIms(slotId);
1541 } catch (RemoteException e) {
1542 return -1;
1543 }
1544 if (VDBG) {
1545 Log.v(LOG_TAG, "ims enable -s " + slotId);
1546 }
1547 return 0;
1548 }
1549
1550 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001551 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001552 String opt;
1553 while ((opt = getNextOption()) != null) {
1554 switch (opt) {
1555 case "-s": {
1556 try {
1557 slotId = Integer.parseInt(getNextArgRequired());
1558 } catch (NumberFormatException e) {
1559 getErrPrintWriter().println(
1560 "ims disable requires an integer as a SLOT_ID.");
1561 return -1;
1562 }
1563 break;
1564 }
1565 }
1566 }
1567 try {
1568 mInterface.disableIms(slotId);
1569 } catch (RemoteException e) {
1570 return -1;
1571 }
1572 if (VDBG) {
1573 Log.v(LOG_TAG, "ims disable -s " + slotId);
1574 }
1575 return 0;
1576 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001577
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001578 private int handleCepChange() {
1579 Log.i(LOG_TAG, "handleCepChange");
1580 String opt = getNextArg();
1581 if (opt == null) {
1582 return -1;
1583 }
1584 boolean isCepEnabled = opt.equals("enable");
1585
1586 try {
1587 mInterface.setCepEnabled(isCepEnabled);
1588 } catch (RemoteException e) {
1589 return -1;
1590 }
1591 return 0;
1592 }
1593
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001594 private int getDefaultSlot() {
1595 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1596 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1597 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1598 // If there is no default, default to slot 0.
1599 slotId = DEFAULT_PHONE_ID;
1600 }
1601 return slotId;
1602 }
sqian2fff4a32018-11-05 14:18:37 -08001603
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001604 // Parse options related to Carrier Config Commands.
1605 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001606 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001607 CcOptionParseResult result = new CcOptionParseResult();
1608 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1609 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001610
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001611 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001612 while ((opt = getNextOption()) != null) {
1613 switch (opt) {
1614 case "-s": {
1615 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001616 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1617 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1618 errPw.println(tag + "No valid subscription found.");
1619 return null;
1620 }
1621
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001622 } catch (IllegalArgumentException e) {
1623 // Missing slot id
1624 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001625 return null;
1626 }
1627 break;
1628 }
1629 case "-p": {
1630 if (allowOptionPersistent) {
1631 result.mPersistent = true;
1632 } else {
1633 errPw.println(tag + "Unexpected option " + opt);
1634 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001635 }
1636 break;
1637 }
1638 default: {
1639 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001640 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001641 }
1642 }
1643 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001644 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001645 }
1646
1647 private int slotStringToSubId(String tag, String slotString) {
1648 int slotId = -1;
1649 try {
1650 slotId = Integer.parseInt(slotString);
1651 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001652 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1653 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1654 }
1655
1656 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001657 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1658 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1659 }
1660
Qiong Liuf25799b2020-09-10 10:13:46 +08001661 Phone phone = PhoneFactory.getPhone(slotId);
1662 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001663 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1664 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1665 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001666 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001667 }
1668
Hall Liud892bec2018-11-30 14:51:45 -08001669 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001670 // adb can run as root or as shell, depending on whether the device is rooted.
1671 return Binder.getCallingUid() == Process.SHELL_UID
1672 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001673 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001674
1675 private int handleCcCommand() {
1676 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1677 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001678 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001679 getErrPrintWriter().println("cc: Permission denied.");
1680 return -1;
1681 }
1682
1683 String arg = getNextArg();
1684 if (arg == null) {
1685 onHelpCc();
1686 return 0;
1687 }
1688
1689 switch (arg) {
1690 case CC_GET_VALUE: {
1691 return handleCcGetValue();
1692 }
1693 case CC_SET_VALUE: {
1694 return handleCcSetValue();
1695 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001696 case CC_SET_VALUES_FROM_XML: {
1697 return handleCcSetValuesFromXml();
1698 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001699 case CC_CLEAR_VALUES: {
1700 return handleCcClearValues();
1701 }
1702 default: {
1703 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1704 }
1705 }
1706 return -1;
1707 }
1708
1709 // cc get-value
1710 private int handleCcGetValue() {
1711 PrintWriter errPw = getErrPrintWriter();
1712 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1713 String key = null;
1714
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001715 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001716 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001717 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001718 return -1;
1719 }
1720
1721 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001722 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001723 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001724 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001725 return -1;
1726 }
1727
1728 // Get the key.
1729 key = getNextArg();
1730 if (key != null) {
1731 // A key was provided. Verify if it is a valid key
1732 if (!bundle.containsKey(key)) {
1733 errPw.println(tag + key + " is not a valid key.");
1734 return -1;
1735 }
1736
1737 // Print the carrier config value for key.
1738 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1739 } else {
1740 // No key provided. Show all values.
1741 // Iterate over a sorted list of all carrier config keys and print them.
1742 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1743 for (String k : sortedSet) {
1744 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1745 }
1746 }
1747 return 0;
1748 }
1749
1750 // cc set-value
1751 private int handleCcSetValue() {
1752 PrintWriter errPw = getErrPrintWriter();
1753 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1754
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001755 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001756 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001757 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001758 return -1;
1759 }
1760
1761 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001762 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001763 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001764 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001765 return -1;
1766 }
1767
1768 // Get the key.
1769 String key = getNextArg();
1770 if (key == null || key.equals("")) {
1771 errPw.println(tag + "KEY is missing");
1772 return -1;
1773 }
1774
1775 // Verify if the key is valid
1776 if (!originalValues.containsKey(key)) {
1777 errPw.println(tag + key + " is not a valid key.");
1778 return -1;
1779 }
1780
1781 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1782 ArrayList<String> valueList = new ArrayList<String>();
1783 while (peekNextArg() != null) {
1784 valueList.add(getNextArg());
1785 }
1786
1787 // Find the type of the carrier config value
1788 CcType type = getType(tag, key, originalValues);
1789 if (type == CcType.UNKNOWN) {
1790 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1791 return -1;
1792 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001793 if (type == CcType.PERSISTABLE_BUNDLE) {
1794 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1795 + "Use set-values-from-xml instead.");
1796 return -1;
1797 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001798
1799 // Create an override bundle containing the key and value that should be overriden.
1800 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1801 if (overrideBundle == null) {
1802 return -1;
1803 }
1804
1805 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001806 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001807
1808 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001809 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001810 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001811 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001812 return -1;
1813 }
1814
1815 // Print the original and new value.
1816 String originalValueString = ccValueToString(key, type, originalValues);
1817 String newValueString = ccValueToString(key, type, newValues);
1818 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1819 getOutPrintWriter().println("New value: \n" + newValueString);
1820
1821 return 0;
1822 }
1823
Allen Xuee00f0e2022-03-14 21:04:49 +00001824 // cc set-values-from-xml
1825 private int handleCcSetValuesFromXml() {
1826 PrintWriter errPw = getErrPrintWriter();
1827 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1828
1829 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001830 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001831 if (options == null) {
1832 return -1;
1833 }
1834
1835 // Get bundle containing all current carrier configuration values.
1836 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1837 if (originalValues == null) {
1838 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1839 return -1;
1840 }
1841
1842 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1843 if (overrideBundle == null) {
1844 return -1;
1845 }
1846
1847 // Verify all values are valid types
1848 for (String key : overrideBundle.keySet()) {
1849 CcType type = getType(tag, key, originalValues);
1850 if (type == CcType.UNKNOWN) {
1851 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1852 return -1;
1853 }
1854 }
1855
1856 // Override the value
1857 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1858
1859 // Find bundle containing all new carrier configuration values after the override.
1860 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1861 if (newValues == null) {
1862 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1863 return -1;
1864 }
1865
1866 // Print the original and new values
1867 overrideBundle.keySet().forEach(key -> {
1868 CcType type = getType(tag, key, originalValues);
1869 String originalValueString = ccValueToString(key, type, originalValues);
1870 String newValueString = ccValueToString(key, type, newValues);
1871 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1872 getOutPrintWriter().println("New value: \n" + newValueString);
1873 });
1874
1875 return 0;
1876 }
1877
1878 private PersistableBundle readPersistableBundleFromXml(String tag) {
1879 PersistableBundle subIdBundles;
1880 try {
1881 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1882 } catch (IOException | RuntimeException e) {
1883 PrintWriter errPw = getErrPrintWriter();
1884 errPw.println(tag + e);
1885 return null;
1886 }
1887
1888 return subIdBundles;
1889 }
1890
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001891 // cc clear-values
1892 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001893 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1894
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001895 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001896 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001897 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001898 return -1;
1899 }
1900
1901 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001902 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001903 getOutPrintWriter()
1904 .println("All previously set carrier config override values has been cleared");
1905 return 0;
1906 }
1907
1908 private CcType getType(String tag, String key, PersistableBundle bundle) {
1909 // Find the type by checking the type of the current value stored in the bundle.
1910 Object value = bundle.get(key);
1911
1912 if (CC_TYPE_MAP.containsKey(key)) {
1913 return CC_TYPE_MAP.get(key);
1914 } else if (value != null) {
1915 if (value instanceof Boolean) {
1916 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001917 }
1918 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001919 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001920 }
1921 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001922 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001923 }
1924 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001925 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001926 }
1927 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001928 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001929 }
1930 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001931 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001932 }
1933 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001934 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001935 }
1936 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001937 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001938 }
1939 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001940 return CcType.STRING_ARRAY;
1941 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001942 if (value instanceof PersistableBundle) {
1943 return CcType.PERSISTABLE_BUNDLE;
1944 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001945 } else {
1946 // Current value was null and can therefore not be used in order to find the type.
1947 // Check the name of the key to infer the type. This check is not needed for primitive
1948 // data types (boolean, double, int and long), since they can not be null.
1949 if (key.endsWith("double_array")) {
1950 return CcType.DOUBLE_ARRAY;
1951 }
1952 if (key.endsWith("int_array")) {
1953 return CcType.INT_ARRAY;
1954 }
1955 if (key.endsWith("long_array")) {
1956 return CcType.LONG_ARRAY;
1957 }
1958 if (key.endsWith("string")) {
1959 return CcType.STRING;
1960 }
1961 if (key.endsWith("string_array") || key.endsWith("strings")) {
1962 return CcType.STRING_ARRAY;
1963 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001964 if (key.endsWith("bundle")) {
1965 return CcType.PERSISTABLE_BUNDLE;
1966 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001967 }
1968
1969 // Not possible to infer the type by looking at the current value or the key.
1970 PrintWriter errPw = getErrPrintWriter();
1971 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1972 return CcType.UNKNOWN;
1973 }
1974
1975 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1976 String result;
1977 StringBuilder valueString = new StringBuilder();
1978 String typeString = type.toString();
1979 Object value = bundle.get(key);
1980
1981 if (value == null) {
1982 valueString.append("null");
1983 } else {
1984 switch (type) {
1985 case DOUBLE_ARRAY: {
1986 // Format the string representation of the int array as value1 value2......
1987 double[] valueArray = (double[]) value;
1988 for (int i = 0; i < valueArray.length; i++) {
1989 if (i != 0) {
1990 valueString.append(" ");
1991 }
1992 valueString.append(valueArray[i]);
1993 }
1994 break;
1995 }
1996 case INT_ARRAY: {
1997 // Format the string representation of the int array as value1 value2......
1998 int[] valueArray = (int[]) value;
1999 for (int i = 0; i < valueArray.length; i++) {
2000 if (i != 0) {
2001 valueString.append(" ");
2002 }
2003 valueString.append(valueArray[i]);
2004 }
2005 break;
2006 }
2007 case LONG_ARRAY: {
2008 // Format the string representation of the int array as value1 value2......
2009 long[] valueArray = (long[]) value;
2010 for (int i = 0; i < valueArray.length; i++) {
2011 if (i != 0) {
2012 valueString.append(" ");
2013 }
2014 valueString.append(valueArray[i]);
2015 }
2016 break;
2017 }
2018 case STRING: {
2019 valueString.append("\"" + value.toString() + "\"");
2020 break;
2021 }
2022 case STRING_ARRAY: {
2023 // Format the string representation of the string array as "value1" "value2"....
2024 String[] valueArray = (String[]) value;
2025 for (int i = 0; i < valueArray.length; i++) {
2026 if (i != 0) {
2027 valueString.append(" ");
2028 }
2029 if (valueArray[i] != null) {
2030 valueString.append("\"" + valueArray[i] + "\"");
2031 } else {
2032 valueString.append("null");
2033 }
2034 }
2035 break;
2036 }
2037 default: {
2038 valueString.append(value.toString());
2039 }
2040 }
2041 }
2042 return String.format("%-70s %-15s %s", key, typeString, valueString);
2043 }
2044
2045 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
2046 ArrayList<String> valueList) {
2047 PrintWriter errPw = getErrPrintWriter();
2048 PersistableBundle bundle = new PersistableBundle();
2049
2050 // First verify that a valid number of values has been provided for the type.
2051 switch (type) {
2052 case BOOLEAN:
2053 case DOUBLE:
2054 case INT:
2055 case LONG: {
2056 if (valueList.size() != 1) {
2057 errPw.println(tag + "Expected 1 value for type " + type
2058 + ". Found: " + valueList.size());
2059 return null;
2060 }
2061 break;
2062 }
2063 case STRING: {
2064 if (valueList.size() > 1) {
2065 errPw.println(tag + "Expected 0 or 1 values for type " + type
2066 + ". Found: " + valueList.size());
2067 return null;
2068 }
2069 break;
2070 }
2071 }
2072
2073 // Parse the value according to type and add it to the Bundle.
2074 switch (type) {
2075 case BOOLEAN: {
2076 if ("true".equalsIgnoreCase(valueList.get(0))) {
2077 bundle.putBoolean(key, true);
2078 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
2079 bundle.putBoolean(key, false);
2080 } else {
2081 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2082 return null;
2083 }
2084 break;
2085 }
2086 case DOUBLE: {
2087 try {
2088 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
2089 } catch (NumberFormatException nfe) {
2090 // Not a valid double
2091 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2092 return null;
2093 }
2094 break;
2095 }
2096 case DOUBLE_ARRAY: {
2097 double[] valueDoubleArray = null;
2098 if (valueList.size() > 0) {
2099 valueDoubleArray = new double[valueList.size()];
2100 for (int i = 0; i < valueList.size(); i++) {
2101 try {
2102 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2103 } catch (NumberFormatException nfe) {
2104 // Not a valid double
2105 errPw.println(
2106 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2107 return null;
2108 }
2109 }
2110 }
2111 bundle.putDoubleArray(key, valueDoubleArray);
2112 break;
2113 }
2114 case INT: {
2115 try {
2116 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2117 } catch (NumberFormatException nfe) {
2118 // Not a valid integer
2119 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2120 return null;
2121 }
2122 break;
2123 }
2124 case INT_ARRAY: {
2125 int[] valueIntArray = null;
2126 if (valueList.size() > 0) {
2127 valueIntArray = new int[valueList.size()];
2128 for (int i = 0; i < valueList.size(); i++) {
2129 try {
2130 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2131 } catch (NumberFormatException nfe) {
2132 // Not a valid integer
2133 errPw.println(tag
2134 + "Unable to parse " + valueList.get(i) + " as an integer.");
2135 return null;
2136 }
2137 }
2138 }
2139 bundle.putIntArray(key, valueIntArray);
2140 break;
2141 }
2142 case LONG: {
2143 try {
2144 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2145 } catch (NumberFormatException nfe) {
2146 // Not a valid long
2147 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2148 return null;
2149 }
2150 break;
2151 }
2152 case LONG_ARRAY: {
2153 long[] valueLongArray = null;
2154 if (valueList.size() > 0) {
2155 valueLongArray = new long[valueList.size()];
2156 for (int i = 0; i < valueList.size(); i++) {
2157 try {
2158 valueLongArray[i] = Long.parseLong(valueList.get(i));
2159 } catch (NumberFormatException nfe) {
2160 // Not a valid long
2161 errPw.println(
2162 tag + "Unable to parse " + valueList.get(i) + " as a long");
2163 return null;
2164 }
2165 }
2166 }
2167 bundle.putLongArray(key, valueLongArray);
2168 break;
2169 }
2170 case STRING: {
2171 String value = null;
2172 if (valueList.size() > 0) {
2173 value = valueList.get(0);
2174 }
2175 bundle.putString(key, value);
2176 break;
2177 }
2178 case STRING_ARRAY: {
2179 String[] valueStringArray = null;
2180 if (valueList.size() > 0) {
2181 valueStringArray = new String[valueList.size()];
2182 valueList.toArray(valueStringArray);
2183 }
2184 bundle.putStringArray(key, valueStringArray);
2185 break;
2186 }
2187 }
2188 return bundle;
2189 }
Shuo Qian489d9282020-07-09 11:30:03 -07002190
2191 private int handleEndBlockSuppressionCommand() {
2192 if (!checkShellUid()) {
2193 return -1;
2194 }
2195
2196 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2197 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2198 }
2199 return 0;
2200 }
Hui Wang641e81c2020-10-12 12:14:23 -07002201
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002202 private int handleEuiccCommand() {
2203 String arg = getNextArg();
2204 if (arg == null) {
2205 onHelpEuicc();
2206 return 0;
2207 }
2208
2209 switch (arg) {
2210 case EUICC_SET_UI_COMPONENT: {
2211 return handleEuiccServiceCommand();
2212 }
2213 }
2214 return -1;
2215 }
2216
2217 private int handleEuiccServiceCommand() {
2218 String uiComponent = getNextArg();
2219 String packageName = getNextArg();
2220 if (packageName == null || uiComponent == null) {
2221 return -1;
2222 }
2223 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2224 if (VDBG) {
2225 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2226 + packageName);
2227 }
2228 return 0;
2229 }
2230
Michele Berionne54af4632020-12-28 20:23:16 +00002231 private int handleRestartModemCommand() {
2232 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2233 // non user build.
2234 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2235 getErrPrintWriter().println("RestartModem: Permission denied.");
2236 return -1;
2237 }
2238
2239 boolean result = TelephonyManager.getDefault().rebootRadio();
2240 getOutPrintWriter().println(result);
2241
2242 return result ? 0 : -1;
2243 }
2244
Ling Ma4fbab492022-01-25 22:36:16 +00002245 private int handleGetImei() {
2246 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2247 // non user build.
2248 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2249 getErrPrintWriter().println("Device IMEI: Permission denied.");
2250 return -1;
2251 }
2252
2253 final long identity = Binder.clearCallingIdentity();
2254
2255 String imei = null;
2256 String arg = getNextArg();
2257 if (arg != null) {
2258 try {
2259 int specifiedSlotIndex = Integer.parseInt(arg);
2260 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2261 } catch (NumberFormatException exception) {
2262 PrintWriter errPw = getErrPrintWriter();
2263 errPw.println("-s requires an integer as slot index.");
2264 return -1;
2265 }
2266
2267 } else {
2268 imei = TelephonyManager.from(mContext).getImei();
2269 }
2270 getOutPrintWriter().println("Device IMEI: " + imei);
2271
2272 Binder.restoreCallingIdentity(identity);
2273 return 0;
2274 }
2275
Michele Berionne5e411512020-11-13 02:36:59 +00002276 private int handleUnattendedReboot() {
2277 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2278 // non user build.
2279 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2280 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2281 return -1;
2282 }
2283
2284 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2285 getOutPrintWriter().println("result: " + result);
2286
2287 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2288 }
2289
Aman Gupta07124872022-02-09 08:02:14 +00002290 private int handleGetSimSlotsMapping() {
2291 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2292 // non user build.
2293 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2294 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2295 return -1;
2296 }
2297 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2298 String result = telephonyManager.getSimSlotMapping().toString();
2299 getOutPrintWriter().println("simSlotsMapping: " + result);
2300
2301 return 0;
2302 }
2303
Hui Wang641e81c2020-10-12 12:14:23 -07002304 private int handleGbaCommand() {
2305 String arg = getNextArg();
2306 if (arg == null) {
2307 onHelpGba();
2308 return 0;
2309 }
2310
2311 switch (arg) {
2312 case GBA_SET_SERVICE: {
2313 return handleGbaSetServiceCommand();
2314 }
2315 case GBA_GET_SERVICE: {
2316 return handleGbaGetServiceCommand();
2317 }
2318 case GBA_SET_RELEASE_TIME: {
2319 return handleGbaSetReleaseCommand();
2320 }
2321 case GBA_GET_RELEASE_TIME: {
2322 return handleGbaGetReleaseCommand();
2323 }
2324 }
2325
2326 return -1;
2327 }
2328
2329 private int getSubId(String cmd) {
2330 int slotId = getDefaultSlot();
2331 String opt = getNextOption();
2332 if (opt != null && opt.equals("-s")) {
2333 try {
2334 slotId = Integer.parseInt(getNextArgRequired());
2335 } catch (NumberFormatException e) {
2336 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2337 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2338 }
2339 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002340 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002341 }
2342
2343 private int handleGbaSetServiceCommand() {
2344 int subId = getSubId("gba set-service");
2345 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2346 return -1;
2347 }
2348
2349 String packageName = getNextArg();
2350 try {
2351 if (packageName == null) {
2352 packageName = "";
2353 }
2354 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2355 if (VDBG) {
2356 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2357 + packageName + ", result=" + result);
2358 }
2359 getOutPrintWriter().println(result);
2360 } catch (RemoteException e) {
2361 Log.w(LOG_TAG, "gba set-service " + subId + " "
2362 + packageName + ", error" + e.getMessage());
2363 getErrPrintWriter().println("Exception: " + e.getMessage());
2364 return -1;
2365 }
2366 return 0;
2367 }
2368
2369 private int handleGbaGetServiceCommand() {
2370 String result;
2371
2372 int subId = getSubId("gba get-service");
2373 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2374 return -1;
2375 }
2376
2377 try {
2378 result = mInterface.getBoundGbaService(subId);
2379 } catch (RemoteException e) {
2380 return -1;
2381 }
2382 if (VDBG) {
2383 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2384 }
2385 getOutPrintWriter().println(result);
2386 return 0;
2387 }
2388
2389 private int handleGbaSetReleaseCommand() {
2390 //the release time value could be -1
2391 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2392 : SubscriptionManager.getDefaultSubscriptionId();
2393 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2394 return -1;
2395 }
2396
2397 String intervalStr = getNextArg();
2398 if (intervalStr == null) {
2399 return -1;
2400 }
2401
2402 try {
2403 int interval = Integer.parseInt(intervalStr);
2404 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2405 if (VDBG) {
2406 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2407 + intervalStr + ", result=" + result);
2408 }
2409 getOutPrintWriter().println(result);
2410 } catch (NumberFormatException | RemoteException e) {
2411 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2412 + intervalStr + ", error" + e.getMessage());
2413 getErrPrintWriter().println("Exception: " + e.getMessage());
2414 return -1;
2415 }
2416 return 0;
2417 }
2418
2419 private int handleGbaGetReleaseCommand() {
2420 int subId = getSubId("gba get-release");
2421 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2422 return -1;
2423 }
2424
2425 int result = 0;
2426 try {
2427 result = mInterface.getGbaReleaseTime(subId);
2428 } catch (RemoteException e) {
2429 return -1;
2430 }
2431 if (VDBG) {
2432 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2433 }
2434 getOutPrintWriter().println(result);
2435 return 0;
2436 }
Hui Wang761a6682020-10-31 05:12:53 +00002437
2438 private int handleSingleRegistrationConfigCommand() {
2439 String arg = getNextArg();
2440 if (arg == null) {
2441 onHelpSrc();
2442 return 0;
2443 }
2444
2445 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002446 case SRC_SET_TEST_ENABLED: {
2447 return handleSrcSetTestEnabledCommand();
2448 }
2449 case SRC_GET_TEST_ENABLED: {
2450 return handleSrcGetTestEnabledCommand();
2451 }
Hui Wang761a6682020-10-31 05:12:53 +00002452 case SRC_SET_DEVICE_ENABLED: {
2453 return handleSrcSetDeviceEnabledCommand();
2454 }
2455 case SRC_GET_DEVICE_ENABLED: {
2456 return handleSrcGetDeviceEnabledCommand();
2457 }
2458 case SRC_SET_CARRIER_ENABLED: {
2459 return handleSrcSetCarrierEnabledCommand();
2460 }
2461 case SRC_GET_CARRIER_ENABLED: {
2462 return handleSrcGetCarrierEnabledCommand();
2463 }
Hui Wangb647abe2021-02-26 09:33:38 -08002464 case SRC_SET_FEATURE_ENABLED: {
2465 return handleSrcSetFeatureValidationCommand();
2466 }
2467 case SRC_GET_FEATURE_ENABLED: {
2468 return handleSrcGetFeatureValidationCommand();
2469 }
Hui Wang761a6682020-10-31 05:12:53 +00002470 }
2471
2472 return -1;
2473 }
2474
James.cf Linbcdf8b32021-01-14 16:44:13 +08002475 private int handleRcsUceCommand() {
2476 String arg = getNextArg();
2477 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002478 onHelpUce();
2479 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002480 }
2481
2482 switch (arg) {
2483 case UCE_REMOVE_EAB_CONTACT:
2484 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002485 case UCE_GET_EAB_CONTACT:
2486 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002487 case UCE_GET_EAB_CAPABILITY:
2488 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002489 case UCE_GET_DEVICE_ENABLED:
2490 return handleUceGetDeviceEnabledCommand();
2491 case UCE_SET_DEVICE_ENABLED:
2492 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002493 case UCE_OVERRIDE_PUBLISH_CAPS:
2494 return handleUceOverridePublishCaps();
2495 case UCE_GET_LAST_PIDF_XML:
2496 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002497 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2498 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002499 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2500 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002501 }
2502 return -1;
2503 }
2504
2505 private int handleRemovingEabContactCommand() {
2506 int subId = getSubId("uce remove-eab-contact");
2507 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2508 return -1;
2509 }
2510
2511 String phoneNumber = getNextArgRequired();
2512 if (TextUtils.isEmpty(phoneNumber)) {
2513 return -1;
2514 }
2515 int result = 0;
2516 try {
2517 result = mInterface.removeContactFromEab(subId, phoneNumber);
2518 } catch (RemoteException e) {
2519 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2520 getErrPrintWriter().println("Exception: " + e.getMessage());
2521 return -1;
2522 }
2523
2524 if (VDBG) {
2525 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2526 }
calvinpan293ea1b2021-02-04 17:52:13 +08002527 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002528 }
2529
calvinpane4a8a1d2021-01-25 13:51:18 +08002530 private int handleGettingEabContactCommand() {
2531 String phoneNumber = getNextArgRequired();
2532 if (TextUtils.isEmpty(phoneNumber)) {
2533 return -1;
2534 }
2535 String result = "";
2536 try {
2537 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002538 } catch (RemoteException e) {
2539 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2540 getErrPrintWriter().println("Exception: " + e.getMessage());
2541 return -1;
2542 }
2543
2544 if (VDBG) {
2545 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2546 }
calvinpan293ea1b2021-02-04 17:52:13 +08002547 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002548 return 0;
2549 }
2550
Calvin Pana1434322021-07-01 19:27:01 +08002551 private int handleGettingEabCapabilityCommand() {
2552 String phoneNumber = getNextArgRequired();
2553 if (TextUtils.isEmpty(phoneNumber)) {
2554 return -1;
2555 }
2556 String result = "";
2557 try {
2558 result = mInterface.getCapabilityFromEab(phoneNumber);
2559 } catch (RemoteException e) {
2560 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2561 getErrPrintWriter().println("Exception: " + e.getMessage());
2562 return -1;
2563 }
2564
2565 if (VDBG) {
2566 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2567 }
2568 getOutPrintWriter().println(result);
2569 return 0;
2570 }
2571
James.cf Lin4b784aa2021-01-31 03:25:15 +08002572 private int handleUceGetDeviceEnabledCommand() {
2573 boolean result = false;
2574 try {
2575 result = mInterface.getDeviceUceEnabled();
2576 } catch (RemoteException e) {
2577 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2578 return -1;
2579 }
2580 if (VDBG) {
2581 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2582 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002583 getOutPrintWriter().println(result);
2584 return 0;
2585 }
2586
James.cf Lin4b784aa2021-01-31 03:25:15 +08002587 private int handleUceSetDeviceEnabledCommand() {
2588 String enabledStr = getNextArg();
2589 if (TextUtils.isEmpty(enabledStr)) {
2590 return -1;
2591 }
2592
2593 try {
2594 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2595 mInterface.setDeviceUceEnabled(isEnabled);
2596 if (VDBG) {
2597 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2598 }
2599 } catch (NumberFormatException | RemoteException e) {
2600 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2601 getErrPrintWriter().println("Exception: " + e.getMessage());
2602 return -1;
2603 }
2604 return 0;
2605 }
2606
James.cf Line8713a42021-04-29 16:04:26 +08002607 private int handleUceRemoveRequestDisallowedStatus() {
2608 int subId = getSubId("uce remove-request-disallowed-status");
2609 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2610 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2611 return -1;
2612 }
2613 boolean result;
2614 try {
2615 result = mInterface.removeUceRequestDisallowedStatus(subId);
2616 } catch (RemoteException e) {
2617 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2618 return -1;
2619 }
2620 if (VDBG) {
2621 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2622 }
2623 getOutPrintWriter().println(result);
2624 return 0;
2625 }
2626
James.cf Lin0fc71b02021-05-25 01:37:38 +08002627 private int handleUceSetCapRequestTimeout() {
2628 int subId = getSubId("uce set-capabilities-request-timeout");
2629 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2630 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2631 return -1;
2632 }
2633 long timeoutAfterMs = Long.valueOf(getNextArg());
2634 boolean result;
2635 try {
2636 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2637 } catch (RemoteException e) {
2638 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2639 return -1;
2640 }
2641 if (VDBG) {
2642 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2643 }
2644 getOutPrintWriter().println(result);
2645 return 0;
2646 }
2647
Hui Wangbaaee6a2021-02-19 20:45:36 -08002648 private int handleSrcSetTestEnabledCommand() {
2649 String enabledStr = getNextArg();
2650 if (enabledStr == null) {
2651 return -1;
2652 }
2653
2654 try {
2655 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2656 if (VDBG) {
2657 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2658 }
2659 getOutPrintWriter().println("Done");
2660 } catch (NumberFormatException | RemoteException e) {
2661 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2662 getErrPrintWriter().println("Exception: " + e.getMessage());
2663 return -1;
2664 }
2665 return 0;
2666 }
2667
2668 private int handleSrcGetTestEnabledCommand() {
2669 boolean result = false;
2670 try {
2671 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2672 } catch (RemoteException e) {
2673 return -1;
2674 }
2675 if (VDBG) {
2676 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2677 }
2678 getOutPrintWriter().println(result);
2679 return 0;
2680 }
2681
Brad Ebinger14d467f2021-02-12 06:18:28 +00002682 private int handleUceOverridePublishCaps() {
2683 int subId = getSubId("uce override-published-caps");
2684 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2685 return -1;
2686 }
2687 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2688 String operation = getNextArgRequired();
2689 String caps = getNextArg();
2690 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2691 && !"list".equals(operation)) {
2692 getErrPrintWriter().println("Invalid operation: " + operation);
2693 return -1;
2694 }
2695
2696 // add/remove requires capabilities to be specified.
2697 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2698 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2699 + "specified");
2700 return -1;
2701 }
2702
2703 ArraySet<String> capSet = new ArraySet<>();
2704 if (!TextUtils.isEmpty(caps)) {
2705 String[] capArray = caps.split(":");
2706 for (String cap : capArray) {
2707 // Allow unknown tags to be passed in as well.
2708 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2709 }
2710 }
2711
2712 RcsContactUceCapability result = null;
2713 try {
2714 switch (operation) {
2715 case "add":
2716 result = mInterface.addUceRegistrationOverrideShell(subId,
2717 new ArrayList<>(capSet));
2718 break;
2719 case "remove":
2720 result = mInterface.removeUceRegistrationOverrideShell(subId,
2721 new ArrayList<>(capSet));
2722 break;
2723 case "clear":
2724 result = mInterface.clearUceRegistrationOverrideShell(subId);
2725 break;
2726 case "list":
2727 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2728 break;
2729 }
2730 } catch (RemoteException e) {
2731 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2732 getErrPrintWriter().println("Exception: " + e.getMessage());
2733 return -1;
2734 } catch (ServiceSpecificException sse) {
2735 // Reconstruct ImsException
2736 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2737 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2738 getErrPrintWriter().println("Exception: " + imsException);
2739 return -1;
2740 }
2741 if (result == null) {
2742 getErrPrintWriter().println("Service not available");
2743 return -1;
2744 }
2745 getOutPrintWriter().println(result);
2746 return 0;
2747 }
2748
2749 private int handleUceGetPidfXml() {
2750 int subId = getSubId("uce get-last-publish-pidf");
2751 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2752 return -1;
2753 }
2754
2755 String result;
2756 try {
2757 result = mInterface.getLastUcePidfXmlShell(subId);
2758 } catch (RemoteException e) {
2759 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2760 getErrPrintWriter().println("Exception: " + e.getMessage());
2761 return -1;
2762 } catch (ServiceSpecificException sse) {
2763 // Reconstruct ImsException
2764 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2765 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2766 getErrPrintWriter().println("Exception: " + imsException);
2767 return -1;
2768 }
2769 if (result == null) {
2770 getErrPrintWriter().println("Service not available");
2771 return -1;
2772 }
2773 getOutPrintWriter().println(result);
2774 return 0;
2775 }
2776
Hui Wang761a6682020-10-31 05:12:53 +00002777 private int handleSrcSetDeviceEnabledCommand() {
2778 String enabledStr = getNextArg();
2779 if (enabledStr == null) {
2780 return -1;
2781 }
2782
2783 try {
2784 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2785 if (VDBG) {
2786 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2787 }
2788 getOutPrintWriter().println("Done");
2789 } catch (NumberFormatException | RemoteException e) {
2790 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2791 getErrPrintWriter().println("Exception: " + e.getMessage());
2792 return -1;
2793 }
2794 return 0;
2795 }
2796
2797 private int handleSrcGetDeviceEnabledCommand() {
2798 boolean result = false;
2799 try {
2800 result = mInterface.getDeviceSingleRegistrationEnabled();
2801 } catch (RemoteException e) {
2802 return -1;
2803 }
2804 if (VDBG) {
2805 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2806 }
2807 getOutPrintWriter().println(result);
2808 return 0;
2809 }
2810
2811 private int handleSrcSetCarrierEnabledCommand() {
2812 //the release time value could be -1
2813 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2814 : SubscriptionManager.getDefaultSubscriptionId();
2815 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2816 return -1;
2817 }
2818
2819 String enabledStr = getNextArg();
2820 if (enabledStr == null) {
2821 return -1;
2822 }
2823
2824 try {
2825 boolean result =
2826 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2827 if (VDBG) {
2828 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2829 + enabledStr + ", result=" + result);
2830 }
2831 getOutPrintWriter().println(result);
2832 } catch (NumberFormatException | RemoteException e) {
2833 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2834 + enabledStr + ", error" + e.getMessage());
2835 getErrPrintWriter().println("Exception: " + e.getMessage());
2836 return -1;
2837 }
2838 return 0;
2839 }
2840
2841 private int handleSrcGetCarrierEnabledCommand() {
2842 int subId = getSubId("src get-carrier-enabled");
2843 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2844 return -1;
2845 }
2846
2847 boolean result = false;
2848 try {
2849 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2850 } catch (RemoteException e) {
2851 return -1;
2852 }
2853 if (VDBG) {
2854 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2855 }
2856 getOutPrintWriter().println(result);
2857 return 0;
2858 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002859
Hui Wangb647abe2021-02-26 09:33:38 -08002860 private int handleSrcSetFeatureValidationCommand() {
2861 //the release time value could be -1
2862 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2863 : SubscriptionManager.getDefaultSubscriptionId();
2864 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2865 return -1;
2866 }
2867
2868 String enabledStr = getNextArg();
2869 if (enabledStr == null) {
2870 return -1;
2871 }
2872
2873 try {
2874 boolean result =
2875 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2876 if (VDBG) {
2877 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2878 + enabledStr + ", result=" + result);
2879 }
2880 getOutPrintWriter().println(result);
2881 } catch (NumberFormatException | RemoteException e) {
2882 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2883 + enabledStr + ", error" + e.getMessage());
2884 getErrPrintWriter().println("Exception: " + e.getMessage());
2885 return -1;
2886 }
2887 return 0;
2888 }
2889
2890 private int handleSrcGetFeatureValidationCommand() {
2891 int subId = getSubId("src get-feature-validation");
2892 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2893 return -1;
2894 }
2895
2896 Boolean result = false;
2897 try {
2898 result = mInterface.getImsFeatureValidationOverride(subId);
2899 } catch (RemoteException e) {
2900 return -1;
2901 }
2902 if (VDBG) {
2903 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2904 }
2905 getOutPrintWriter().println(result);
2906 return 0;
2907 }
2908
2909
Hall Liuaa4211e2021-01-20 15:43:39 -08002910 private void onHelpCallComposer() {
2911 PrintWriter pw = getOutPrintWriter();
2912 pw.println("Call composer commands");
2913 pw.println(" callcomposer test-mode enable|disable|query");
2914 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2915 pw.println(" upload/download from carrier servers is disabled, and operations are");
2916 pw.println(" performed using emulated local files instead.");
2917 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2918 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2919 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002920 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2921 pw.println(" Enables or disables the user setting for call composer, as set by");
2922 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002923 }
2924
2925 private int handleCallComposerCommand() {
2926 String arg = getNextArg();
2927 if (arg == null) {
2928 onHelpCallComposer();
2929 return 0;
2930 }
2931
2932 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2933 "MODIFY_PHONE_STATE required for call composer shell cmds");
2934 switch (arg) {
2935 case CALL_COMPOSER_TEST_MODE: {
2936 String enabledStr = getNextArg();
2937 if (ENABLE.equals(enabledStr)) {
2938 CallComposerPictureManager.sTestMode = true;
2939 } else if (DISABLE.equals(enabledStr)) {
2940 CallComposerPictureManager.sTestMode = false;
2941 } else if (QUERY.equals(enabledStr)) {
2942 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2943 } else {
2944 onHelpCallComposer();
2945 return 1;
2946 }
2947 break;
2948 }
2949 case CALL_COMPOSER_SIMULATE_CALL: {
2950 int subscriptionId = Integer.valueOf(getNextArg());
2951 String uuidString = getNextArg();
2952 UUID uuid = UUID.fromString(uuidString);
2953 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2954 Binder.withCleanCallingIdentity(() -> {
2955 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2956 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2957 });
2958 try {
2959 Uri uri = storageUriFuture.get();
2960 getOutPrintWriter().println(String.valueOf(uri));
2961 } catch (Exception e) {
2962 throw new RuntimeException(e);
2963 }
2964 break;
2965 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002966 case CALL_COMPOSER_USER_SETTING: {
2967 try {
2968 int subscriptionId = Integer.valueOf(getNextArg());
2969 String enabledStr = getNextArg();
2970 if (ENABLE.equals(enabledStr)) {
2971 mInterface.setCallComposerStatus(subscriptionId,
2972 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2973 } else if (DISABLE.equals(enabledStr)) {
2974 mInterface.setCallComposerStatus(subscriptionId,
2975 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2976 } else if (QUERY.equals(enabledStr)) {
2977 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2978 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2979 } else {
2980 onHelpCallComposer();
2981 return 1;
2982 }
2983 } catch (RemoteException e) {
2984 e.printStackTrace(getOutPrintWriter());
2985 return 1;
2986 }
2987 break;
2988 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002989 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002990 return 0;
2991 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002992
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002993 private int handleHasCarrierPrivilegesCommand() {
2994 String packageName = getNextArgRequired();
2995
2996 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002997 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002998 try {
2999 hasCarrierPrivileges =
3000 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
3001 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
3002 } catch (RemoteException e) {
3003 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
3004 getErrPrintWriter().println("Exception: " + e.getMessage());
3005 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07003006 } finally {
3007 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08003008 }
3009
3010 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08003011 return 0;
3012 }
SongFerngWang98dd5992021-05-13 17:50:00 +08003013
3014 private int handleAllowedNetworkTypesCommand(String command) {
3015 if (!checkShellUid()) {
3016 return -1;
3017 }
3018
3019 PrintWriter errPw = getErrPrintWriter();
3020 String tag = command + ": ";
3021 String opt;
3022 int subId = -1;
3023 Log.v(LOG_TAG, command + " start");
3024
3025 while ((opt = getNextOption()) != null) {
3026 if (opt.equals("-s")) {
3027 try {
3028 subId = slotStringToSubId(tag, getNextArgRequired());
3029 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3030 errPw.println(tag + "No valid subscription found.");
3031 return -1;
3032 }
3033 } catch (IllegalArgumentException e) {
3034 // Missing slot id
3035 errPw.println(tag + "SLOT_ID expected after -s.");
3036 return -1;
3037 }
3038 } else {
3039 errPw.println(tag + "Unknown option " + opt);
3040 return -1;
3041 }
3042 }
3043
3044 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
3045 return handleGetAllowedNetworkTypesCommand(subId);
3046 }
3047 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
3048 return handleSetAllowedNetworkTypesCommand(subId);
3049 }
3050 return -1;
3051 }
3052
3053 private int handleGetAllowedNetworkTypesCommand(int subId) {
3054 PrintWriter errPw = getErrPrintWriter();
3055
3056 long result = -1;
3057 try {
3058 if (mInterface != null) {
3059 result = mInterface.getAllowedNetworkTypesForReason(subId,
3060 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
3061 } else {
3062 throw new IllegalStateException("telephony service is null.");
3063 }
3064 } catch (RemoteException e) {
3065 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
3066 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
3067 return -1;
3068 }
3069
3070 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
3071 return 0;
3072 }
3073
3074 private int handleSetAllowedNetworkTypesCommand(int subId) {
3075 PrintWriter errPw = getErrPrintWriter();
3076
3077 String bitmaskString = getNextArg();
3078 if (TextUtils.isEmpty(bitmaskString)) {
3079 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
3080 return -1;
3081 }
3082 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
3083 if (allowedNetworkTypes < 0) {
3084 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
3085 return -1;
3086 }
3087 boolean result = false;
3088 try {
3089 if (mInterface != null) {
3090 result = mInterface.setAllowedNetworkTypesForReason(subId,
3091 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
3092 } else {
3093 throw new IllegalStateException("telephony service is null.");
3094 }
3095 } catch (RemoteException e) {
3096 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
3097 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
3098 return -1;
3099 }
3100
3101 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
3102 if (result) {
3103 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3104 }
3105 getOutPrintWriter().println(resultMessage);
3106 return 0;
3107 }
3108
3109 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3110 if (TextUtils.isEmpty(bitmaskString)) {
3111 return -1;
3112 }
3113 if (VDBG) {
3114 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3115 + ", length: " + bitmaskString.length());
3116 }
3117 try {
3118 return Long.parseLong(bitmaskString, 2);
3119 } catch (NumberFormatException e) {
3120 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3121 return -1;
3122 }
3123 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003124
jimsun3b9ccac2021-10-26 15:01:23 +08003125 private int handleRadioSetModemServiceCommand() {
3126 PrintWriter errPw = getErrPrintWriter();
3127 String serviceName = null;
3128
3129 String opt;
3130 while ((opt = getNextOption()) != null) {
3131 switch (opt) {
3132 case "-s": {
3133 serviceName = getNextArgRequired();
3134 break;
3135 }
3136 }
3137 }
3138
3139 try {
3140 boolean result = mInterface.setModemService(serviceName);
3141 if (VDBG) {
3142 Log.v(LOG_TAG,
3143 "RadioSetModemService " + serviceName + ", result = " + result);
3144 }
3145 getOutPrintWriter().println(result);
3146 } catch (RemoteException e) {
3147 Log.w(LOG_TAG,
3148 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3149 errPw.println("Exception: " + e.getMessage());
3150 return -1;
3151 }
3152 return 0;
3153 }
3154
3155 private int handleRadioGetModemServiceCommand() {
3156 PrintWriter errPw = getErrPrintWriter();
3157 String result;
3158
3159 try {
3160 result = mInterface.getModemService();
3161 getOutPrintWriter().println(result);
3162 } catch (RemoteException e) {
3163 errPw.println("Exception: " + e.getMessage());
3164 return -1;
3165 }
3166 if (VDBG) {
3167 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3168 }
3169 return 0;
3170 }
3171
3172 private int handleRadioCommand() {
3173 String arg = getNextArg();
3174 if (arg == null) {
3175 onHelpRadio();
3176 return 0;
3177 }
3178
3179 switch (arg) {
3180 case RADIO_SET_MODEM_SERVICE:
3181 return handleRadioSetModemServiceCommand();
3182
3183 case RADIO_GET_MODEM_SERVICE:
3184 return handleRadioGetModemServiceCommand();
3185 }
3186
3187 return -1;
3188 }
arunvoddud7401012022-12-15 16:08:12 +00003189
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003190 private int handleSetSatelliteServicePackageNameCommand() {
3191 PrintWriter errPw = getErrPrintWriter();
3192 String serviceName = null;
3193
3194 String opt;
3195 while ((opt = getNextOption()) != null) {
3196 switch (opt) {
3197 case "-s": {
3198 serviceName = getNextArgRequired();
3199 break;
3200 }
3201 }
3202 }
3203 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3204 + serviceName);
3205
3206 try {
3207 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3208 if (VDBG) {
3209 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3210 + ", result = " + result);
3211 }
3212 getOutPrintWriter().println(result);
3213 } catch (RemoteException e) {
3214 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3215 + ", error = " + e.getMessage());
3216 errPw.println("Exception: " + e.getMessage());
3217 return -1;
3218 }
3219 return 0;
3220 }
3221
Thomas Nguyen1854a5a2023-04-04 09:31:47 -07003222 private int handleSetSatelliteGatewayServicePackageNameCommand() {
3223 PrintWriter errPw = getErrPrintWriter();
3224 String serviceName = null;
3225
3226 String opt;
3227 while ((opt = getNextOption()) != null) {
3228 switch (opt) {
3229 case "-s": {
3230 serviceName = getNextArgRequired();
3231 break;
3232 }
3233 }
3234 }
3235 Log.d(LOG_TAG, "handleSetSatelliteGatewayServicePackageNameCommand: serviceName="
3236 + serviceName);
3237
3238 try {
3239 boolean result = mInterface.setSatelliteGatewayServicePackageName(serviceName);
3240 if (VDBG) {
3241 Log.v(LOG_TAG, "setSatelliteGatewayServicePackageName " + serviceName
3242 + ", result = " + result);
3243 }
3244 getOutPrintWriter().println(result);
3245 } catch (RemoteException e) {
3246 Log.w(LOG_TAG, "setSatelliteGatewayServicePackageName: " + serviceName
3247 + ", error = " + e.getMessage());
3248 errPw.println("Exception: " + e.getMessage());
3249 return -1;
3250 }
3251 return 0;
3252 }
3253
Thomas Nguyen87dce732023-04-20 18:27:16 -07003254 private int handleSetSatellitePointingUiClassNameCommand() {
3255 PrintWriter errPw = getErrPrintWriter();
3256 String packageName = null;
3257 String className = null;
3258
3259 String opt;
3260 while ((opt = getNextOption()) != null) {
3261 switch (opt) {
3262 case "-p": {
3263 packageName = getNextArgRequired();
3264 break;
3265 }
3266 case "-c": {
3267 className = getNextArgRequired();
3268 break;
3269 }
3270 }
3271 }
3272 Log.d(LOG_TAG, "handleSetSatellitePointingUiClassNameCommand: packageName="
3273 + packageName + ", className=" + className);
3274
3275 try {
3276 boolean result = mInterface.setSatellitePointingUiClassName(packageName, className);
3277 if (VDBG) {
3278 Log.v(LOG_TAG, "setSatellitePointingUiClassName result =" + result);
3279 }
3280 getOutPrintWriter().println(result);
3281 } catch (RemoteException e) {
3282 Log.e(LOG_TAG, "setSatellitePointingUiClassName: " + packageName
3283 + ", error = " + e.getMessage());
3284 errPw.println("Exception: " + e.getMessage());
3285 return -1;
3286 }
3287 return 0;
3288 }
3289
Thomas Nguyen11a051f2023-10-25 10:14:55 -07003290 private int handleSetEmergencyCallToSatelliteHandoverType() {
3291 PrintWriter errPw = getErrPrintWriter();
3292 int handoverType = -1;
3293 int delaySeconds = 0;
3294
3295 String opt;
3296 while ((opt = getNextOption()) != null) {
3297 switch (opt) {
3298 case "-t": {
3299 try {
3300 handoverType = Integer.parseInt(getNextArgRequired());
3301 } catch (NumberFormatException e) {
3302 errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
3303 + " for handoverType");
3304 return -1;
3305 }
3306 break;
3307 }
3308 case "-d": {
3309 try {
3310 delaySeconds = Integer.parseInt(getNextArgRequired());
3311 } catch (NumberFormatException e) {
3312 errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
3313 + " for delaySeconds");
3314 return -1;
3315 }
3316 break;
3317 }
3318 }
3319 }
3320 Log.d(LOG_TAG, "handleSetEmergencyCallToSatelliteHandoverType: handoverType="
3321 + handoverType + ", delaySeconds=" + delaySeconds);
3322
3323 try {
3324 boolean result =
3325 mInterface.setEmergencyCallToSatelliteHandoverType(handoverType, delaySeconds);
3326 if (VDBG) {
3327 Log.v(LOG_TAG, "setEmergencyCallToSatelliteHandoverType result =" + result);
3328 }
3329 getOutPrintWriter().println(result);
3330 } catch (RemoteException e) {
3331 Log.e(LOG_TAG, "setEmergencyCallToSatelliteHandoverType: " + handoverType
3332 + ", error = " + e.getMessage());
3333 errPw.println("Exception: " + e.getMessage());
3334 return -1;
3335 }
3336 return 0;
3337 }
3338
Thomas Nguyenf9a533c2023-04-06 20:48:41 -07003339 private int handleSetSatelliteListeningTimeoutDuration() {
3340 PrintWriter errPw = getErrPrintWriter();
3341 long timeoutMillis = 0;
3342
3343 String opt;
3344 while ((opt = getNextOption()) != null) {
3345 switch (opt) {
3346 case "-t": {
3347 timeoutMillis = Long.parseLong(getNextArgRequired());
3348 break;
3349 }
3350 }
3351 }
3352 Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
3353 + timeoutMillis);
3354
3355 try {
3356 boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
3357 if (VDBG) {
3358 Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
3359 + ", result = " + result);
3360 }
3361 getOutPrintWriter().println(result);
3362 } catch (RemoteException e) {
3363 Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
3364 + ", error = " + e.getMessage());
3365 errPw.println("Exception: " + e.getMessage());
3366 return -1;
3367 }
3368 return 0;
3369 }
3370
Hakjun Choiae365972023-04-25 11:00:31 +00003371 private int handleSettSatelliteDeviceAlignedTimeoutDuration() {
3372 PrintWriter errPw = getErrPrintWriter();
3373 long timeoutMillis = 0;
3374
3375 String opt;
3376 while ((opt = getNextOption()) != null) {
3377 switch (opt) {
3378 case "-t": {
3379 timeoutMillis = Long.parseLong(getNextArgRequired());
3380 break;
3381 }
3382 }
3383 }
3384 Log.d(LOG_TAG, "handleSettSatelliteDeviceAlignedTimeoutDuration: timeoutMillis="
3385 + timeoutMillis);
3386
3387 try {
3388 boolean result = mInterface.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis);
3389 if (VDBG) {
3390 Log.v(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration " + timeoutMillis
3391 + ", result = " + result);
3392 }
3393 getOutPrintWriter().println(result);
3394 } catch (RemoteException e) {
3395 Log.w(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration: " + timeoutMillis
3396 + ", error = " + e.getMessage());
3397 errPw.println("Exception: " + e.getMessage());
3398 return -1;
3399 }
3400 return 0;
3401 }
3402
Hakjun Choibc6ce992023-11-07 16:04:33 +00003403 private int handleSetShouldSendDatagramToModemInDemoMode() {
3404 PrintWriter errPw = getErrPrintWriter();
3405 String opt;
3406 boolean shouldSendToDemoMode;
3407
3408 if ((opt = getNextArg()) == null) {
3409 errPw.println(
3410 "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
3411 + " Invalid Argument");
3412 return -1;
3413 } else {
3414 switch (opt) {
3415 case "true": {
3416 shouldSendToDemoMode = true;
3417 break;
3418 }
3419 case "false": {
3420 shouldSendToDemoMode = false;
3421 break;
3422 }
3423 default:
3424 errPw.println(
3425 "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
3426 + " Invalid Argument");
3427 return -1;
3428 }
3429 }
3430
3431 Log.d(LOG_TAG,
3432 "handleSetShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode + ")");
3433
3434 try {
3435 boolean result = mInterface.setShouldSendDatagramToModemInDemoMode(
3436 shouldSendToDemoMode);
3437 if (VDBG) {
3438 Log.v(LOG_TAG, "handleSetShouldSendDatagramToModemInDemoMode returns: "
3439 + result);
3440 }
3441 getOutPrintWriter().println(false);
3442 } catch (RemoteException e) {
3443 Log.w(LOG_TAG, "setShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode
3444 + "), error = " + e.getMessage());
3445 errPw.println("Exception: " + e.getMessage());
3446 return -1;
3447 }
3448 return 0;
3449 }
3450
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -08003451 private int handleSetSatelliteAccessControlOverlayConfigs() {
3452 PrintWriter errPw = getErrPrintWriter();
3453 boolean reset = false;
3454 boolean isAllowed = false;
3455 String s2CellFile = null;
3456 long locationFreshDurationNanos = 0;
3457 List<String> satelliteCountryCodes = null;
3458
3459 String opt;
3460 while ((opt = getNextOption()) != null) {
3461 switch (opt) {
3462 case "-r": {
3463 reset = true;
3464 break;
3465 }
3466 case "-a": {
3467 isAllowed = true;
3468 break;
3469 }
3470 case "-f": {
3471 s2CellFile = getNextArgRequired();
3472 break;
3473 }
3474 case "-d": {
3475 locationFreshDurationNanos = Long.parseLong(getNextArgRequired());
3476 break;
3477 }
3478 case "-c": {
3479 String countryCodeStr = getNextArgRequired();
3480 satelliteCountryCodes = Arrays.asList(countryCodeStr.split(","));
3481 break;
3482 }
3483 }
3484 }
3485 Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: reset=" + reset
3486 + ", isAllowed=" + isAllowed + ", s2CellFile=" + s2CellFile
3487 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
3488 + ", satelliteCountryCodes=" + satelliteCountryCodes);
3489
3490 try {
3491 boolean result = mInterface.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
3492 s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
3493 if (VDBG) {
3494 Log.v(LOG_TAG, "setSatelliteAccessControlOverlayConfigs result =" + result);
3495 }
3496 getOutPrintWriter().println(result);
3497 } catch (RemoteException e) {
3498 Log.e(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: ex=" + e.getMessage());
3499 errPw.println("Exception: " + e.getMessage());
3500 return -1;
3501 }
3502 return 0;
3503 }
3504
3505 private int handleSetCountryCodes() {
3506 PrintWriter errPw = getErrPrintWriter();
3507 List<String> currentNetworkCountryCodes = new ArrayList<>();
3508 String locationCountryCode = null;
3509 long locationCountryCodeTimestampNanos = 0;
3510 Map<String, Long> cachedNetworkCountryCodes = new HashMap<>();
3511 boolean reset = false;
3512
3513 String opt;
3514 while ((opt = getNextOption()) != null) {
3515 switch (opt) {
3516 case "-r": {
3517 reset = true;
3518 break;
3519 }
3520 case "-n": {
3521 String countryCodeStr = getNextArgRequired();
3522 currentNetworkCountryCodes = Arrays.asList(countryCodeStr.split(","));
3523 break;
3524 }
3525 case "-c": {
3526 String cachedNetworkCountryCodeStr = getNextArgRequired();
3527 cachedNetworkCountryCodes = parseStringLongMap(cachedNetworkCountryCodeStr);
3528 break;
3529 }
3530 case "-l": {
3531 locationCountryCode = getNextArgRequired();
3532 break;
3533 }
3534 case "-t": {
3535 locationCountryCodeTimestampNanos = Long.parseLong(getNextArgRequired());
3536 break;
3537 }
3538 }
3539 }
3540 Log.d(LOG_TAG, "setCountryCodes: locationCountryCode="
3541 + locationCountryCode + ", locationCountryCodeTimestampNanos="
3542 + locationCountryCodeTimestampNanos + ", currentNetworkCountryCodes="
3543 + currentNetworkCountryCodes);
3544
3545 try {
3546 boolean result = mInterface.setCountryCodes(reset, currentNetworkCountryCodes,
3547 cachedNetworkCountryCodes, locationCountryCode,
3548 locationCountryCodeTimestampNanos);
3549 if (VDBG) {
3550 Log.v(LOG_TAG, "setCountryCodes result =" + result);
3551 }
3552 getOutPrintWriter().println(result);
3553 } catch (RemoteException e) {
3554 Log.e(LOG_TAG, "setCountryCodes: ex=" + e.getMessage());
3555 errPw.println("Exception: " + e.getMessage());
3556 return -1;
3557 }
3558 return 0;
3559 }
3560
Thomas Nguyen3d602742024-01-19 11:29:35 -08003561 private int handleSetOemEnabledSatelliteProvisionStatus() {
3562 PrintWriter errPw = getErrPrintWriter();
3563 boolean isProvisioned = false;
3564 boolean reset = true;
3565
3566 String opt;
3567 while ((opt = getNextOption()) != null) {
3568 switch (opt) {
3569 case "-p": {
3570 try {
3571 isProvisioned = Boolean.parseBoolean(getNextArgRequired());
3572 reset = false;
3573 } catch (Exception e) {
3574 errPw.println("setOemEnabledSatelliteProvisionStatus requires a boolean "
3575 + "after -p indicating provision status");
3576 return -1;
3577 }
3578 }
3579 }
3580 }
3581 Log.d(LOG_TAG, "setOemEnabledSatelliteProvisionStatus: reset=" + reset
3582 + ", isProvisioned=" + isProvisioned);
3583
3584 try {
3585 boolean result = mInterface.setOemEnabledSatelliteProvisionStatus(reset, isProvisioned);
3586 if (VDBG) {
3587 Log.v(LOG_TAG, "setOemEnabledSatelliteProvisionStatus result = " + result);
3588 }
3589 getOutPrintWriter().println(result);
3590 } catch (RemoteException e) {
3591 Log.w(LOG_TAG, "setOemEnabledSatelliteProvisionStatus: error = " + e.getMessage());
3592 errPw.println("Exception: " + e.getMessage());
3593 return -1;
3594 }
3595 return 0;
3596 }
3597
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -08003598 /**
3599 * Sample inputStr = "US,UK,CA;2,1,3"
3600 * Sample output: {[US,2], [UK,1], [CA,3]}
3601 */
3602 @NonNull private Map<String, Long> parseStringLongMap(@Nullable String inputStr) {
3603 Map<String, Long> result = new HashMap<>();
3604 if (!TextUtils.isEmpty(inputStr)) {
3605 String[] stringLongArr = inputStr.split(";");
3606 if (stringLongArr.length != 2) {
3607 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
3608 return result;
3609 }
3610
3611 String[] stringArr = stringLongArr[0].split(",");
3612 String[] longArr = stringLongArr[1].split(",");
3613 if (stringArr.length != longArr.length) {
3614 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
3615 return result;
3616 }
3617
3618 for (int i = 0; i < stringArr.length; i++) {
3619 try {
3620 result.put(stringArr[i], Long.parseLong(longArr[i]));
3621 } catch (Exception ex) {
3622 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr
3623 + ", ex=" + ex);
3624 return result;
3625 }
3626 }
3627 }
3628 return result;
3629 }
3630
arunvoddud7401012022-12-15 16:08:12 +00003631 private int handleCarrierRestrictionStatusCommand() {
3632 try {
3633 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3634 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3635 mInterface.getModemService()))) {
3636 Log.v(LOG_TAG,
3637 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3638 + " checkShellUid fails");
3639 return -1;
3640 }
3641 } catch (RemoteException ex) {
3642 ex.printStackTrace();
3643 }
3644 String callerInfo = getNextOption();
3645 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3646 if (TextUtils.isEmpty(callerInfo)) {
3647 // reset the Json content after testing
3648 allowListInfo.updateJsonForTest(null);
3649 return 0;
3650 }
3651 if (callerInfo.startsWith("--")) {
3652 callerInfo = callerInfo.replace("--", "");
3653 }
3654 String params[] = callerInfo.split(",");
3655 StringBuffer jsonStrBuffer = new StringBuffer();
3656 String tokens;
3657 for (int index = 0; index < params.length; index++) {
3658 tokens = convertToJsonString(index, params[index]);
3659 if (TextUtils.isEmpty(tokens)) {
3660 // received wrong format from CTS
3661 if (VDBG) {
3662 Log.v(LOG_TAG,
3663 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3664 }
3665 return -1;
3666 }
3667 jsonStrBuffer.append(tokens);
3668 }
3669 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3670 return result;
3671 }
3672
Benedict Wong66477622023-02-03 23:30:57 +00003673 // set-carrier-service-package-override
3674 private int setCarrierServicePackageOverride() {
3675 PrintWriter errPw = getErrPrintWriter();
3676 int subId = SubscriptionManager.getDefaultSubscriptionId();
3677
3678 String opt;
3679 while ((opt = getNextOption()) != null) {
3680 switch (opt) {
3681 case "-s":
3682 try {
3683 subId = Integer.parseInt(getNextArgRequired());
3684 } catch (NumberFormatException e) {
3685 errPw.println(
3686 "set-carrier-service-package-override requires an integer as a"
3687 + " subscription ID.");
3688 return -1;
3689 }
3690 break;
3691 }
3692 }
3693
3694 String packageName = getNextArg();
3695 if (packageName == null) {
3696 errPw.println("set-carrier-service-package-override requires a override package name.");
3697 return -1;
3698 }
3699
3700 try {
3701 mInterface.setCarrierServicePackageOverride(
3702 subId, packageName, mContext.getOpPackageName());
3703
3704 if (VDBG) {
3705 Log.v(
3706 LOG_TAG,
3707 "set-carrier-service-package-override -s " + subId + " " + packageName);
3708 }
3709 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3710 Log.w(
3711 LOG_TAG,
3712 "set-carrier-service-package-override -s "
3713 + subId
3714 + " "
3715 + packageName
3716 + ", error"
3717 + e.getMessage());
3718 errPw.println("Exception: " + e.getMessage());
3719 return -1;
3720 }
3721 return 0;
3722 }
3723
3724 // clear-carrier-service-package-override
3725 private int clearCarrierServicePackageOverride() {
3726 PrintWriter errPw = getErrPrintWriter();
Chalard Jean71706f42023-09-22 18:22:47 +09003727 int subId = SubscriptionManager.getDefaultSubscriptionId();
Benedict Wong66477622023-02-03 23:30:57 +00003728
3729 String opt;
3730 while ((opt = getNextOption()) != null) {
3731 switch (opt) {
3732 case "-s":
3733 try {
3734 subId = Integer.parseInt(getNextArgRequired());
3735 } catch (NumberFormatException e) {
3736 errPw.println(
3737 "clear-carrier-service-package-override requires an integer as a"
3738 + " subscription ID.");
3739 return -1;
3740 }
3741 break;
3742 }
3743 }
3744
3745 try {
3746 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3747
3748 if (VDBG) {
3749 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3750 }
3751 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3752 Log.w(
3753 LOG_TAG,
3754 "clear-carrier-service-package-override -s "
3755 + subId
3756 + ", error"
3757 + e.getMessage());
3758 errPw.println("Exception: " + e.getMessage());
3759 return -1;
3760 }
3761 return 0;
3762 }
arunvoddud7401012022-12-15 16:08:12 +00003763
Hunsuk Choi13078be2023-09-13 10:55:21 +00003764 private int handleDomainSelectionCommand() {
3765 String arg = getNextArg();
3766 if (arg == null) {
3767 onHelpDomainSelection();
3768 return 0;
3769 }
3770
3771 switch (arg) {
3772 case DOMAIN_SELECTION_SET_SERVICE_OVERRIDE: {
3773 return handleDomainSelectionSetServiceOverrideCommand();
3774 }
3775 case DOMAIN_SELECTION_CLEAR_SERVICE_OVERRIDE: {
3776 return handleDomainSelectionClearServiceOverrideCommand();
3777 }
3778 }
3779
3780 return -1;
3781 }
3782
3783 // domainselection set-dss-override
3784 private int handleDomainSelectionSetServiceOverrideCommand() {
3785 PrintWriter errPw = getErrPrintWriter();
3786
3787 String componentName = getNextArg();
3788
3789 try {
3790 boolean result = mInterface.setDomainSelectionServiceOverride(
3791 ComponentName.unflattenFromString(componentName));
3792 if (VDBG) {
3793 Log.v(LOG_TAG, "domainselection set-dss-override "
3794 + componentName + ", result=" + result);
3795 }
3796 getOutPrintWriter().println(result);
3797 } catch (Exception e) {
3798 Log.w(LOG_TAG, "domainselection set-dss-override "
3799 + componentName + ", error=" + e.getMessage());
3800 errPw.println("Exception: " + e.getMessage());
3801 return -1;
3802 }
3803 return 0;
3804 }
3805
3806 // domainselection clear-dss-override
3807 private int handleDomainSelectionClearServiceOverrideCommand() {
3808 PrintWriter errPw = getErrPrintWriter();
3809
3810 try {
3811 boolean result = mInterface.clearDomainSelectionServiceOverride();
3812 if (VDBG) {
3813 Log.v(LOG_TAG, "domainselection clear-dss-override result=" + result);
3814 }
3815 getOutPrintWriter().println(result);
3816 } catch (RemoteException e) {
3817 Log.w(LOG_TAG, "domainselection clear-dss-override error=" + e.getMessage());
3818 errPw.println("Exception: " + e.getMessage());
3819 return -1;
3820 }
3821 return 0;
3822 }
3823
arunvoddud7401012022-12-15 16:08:12 +00003824 /**
3825 * Building the string that can be used to build the JsonObject which supports to stub the data
3826 * in CarrierAllowListInfo for CTS testing. sample format is like
3827 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3828 */
3829 private String convertToJsonString(int index, String param) {
3830
3831 String token[] = param.split(":");
3832 String jSonString;
3833 switch (index) {
3834 case 0:
3835 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3836 break;
3837 case 1:
3838 jSonString =
3839 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3840 break;
3841 case 2:
3842 jSonString =
3843 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3844 break;
3845 default:
3846 jSonString = null;
3847 }
3848 return jSonString;
3849 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003850}