blob: f7a3640db36feaf70e4f36818b021e1be7f81db9 [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;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010029import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080030import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080031import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010032import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080033import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070034import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000035import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070036import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070037import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010038import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070039import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070040import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000041import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070042import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080043import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000044import android.telephony.ims.ImsException;
45import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080046import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080047import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000048import android.util.ArrayMap;
49import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070051import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052
Brad Ebinger14d467f2021-02-12 06:18:28 +000053import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070054import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080055import com.android.internal.telephony.Phone;
56import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080057import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080058import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080059import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080060import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080061import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000062import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000063import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064
Allen Xuee00f0e2022-03-14 21:04:49 +000065import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070066import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080067import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000068import java.util.Arrays;
69import java.util.Collections;
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -080070import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080071import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000072import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010073import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000074import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010075import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080076import java.util.UUID;
77import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070078
79/**
80 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
81 * permission checks have been done before onCommand was called. Make sure any commands processed
82 * here also contain the appropriate permissions checks.
83 */
84
Hall Liua1548bd2019-12-24 14:14:12 -080085public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070086
87 private static final String LOG_TAG = "TelephonyShellCommand";
88 // Don't commit with this true.
89 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070090 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070091
Hall Liuaa4211e2021-01-20 15:43:39 -080092 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070093 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080094 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080095 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080096 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070097 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000098 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000099 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100100 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -0800101 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -0800102 private static final String ENABLE = "enable";
103 private static final String DISABLE = "disable";
104 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000105 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000106 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
107 "set-carrier-service-package-override";
108 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
109 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000110 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800111
Hall Liu7135e502021-02-04 16:58:17 -0800112 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800113 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800114 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800115
Brad Ebinger999d3302020-11-25 14:31:39 -0800116 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
117 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
118 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700119 // Used to disable or enable processing of conference event package data from the network.
120 // This is handy for testing scenarios where CEP data does not exist on a network which does
121 // support CEP data.
122 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700123
Hall Liud892bec2018-11-30 14:51:45 -0800124 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800125 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800126
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private static final String CC_GET_VALUE = "get-value";
128 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000129 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100130 private static final String CC_CLEAR_VALUES = "clear-values";
131
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000132 private static final String EUICC_SUBCOMMAND = "euicc";
133 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
134
Hui Wang641e81c2020-10-12 12:14:23 -0700135 private static final String GBA_SUBCOMMAND = "gba";
136 private static final String GBA_SET_SERVICE = "set-service";
137 private static final String GBA_GET_SERVICE = "get-service";
138 private static final String GBA_SET_RELEASE_TIME = "set-release";
139 private static final String GBA_GET_RELEASE_TIME = "get-release";
140
Hui Wang761a6682020-10-31 05:12:53 +0000141 private static final String SINGLE_REGISTATION_CONFIG = "src";
142 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
143 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
144 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
145 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800146 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
147 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800148 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
149 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000150
Tyler Gunn92479152021-01-20 16:30:10 -0800151 private static final String D2D_SUBCOMMAND = "d2d";
152 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800153 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700154 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800155
Nazanin014f41e2021-05-06 17:26:31 -0700156 private static final String BARRING_SUBCOMMAND = "barring";
157 private static final String BARRING_SEND_INFO = "send";
158
James.cf Linbcdf8b32021-01-14 16:44:13 +0800159 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800160 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800161 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800162 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800163 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
164 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000165 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
166 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800167 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
168 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800169 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
170 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800171
jimsun3b9ccac2021-10-26 15:01:23 +0800172 private static final String RADIO_SUBCOMMAND = "radio";
173 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
174 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
175
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800176 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
177 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
178
Jordan Liu0ccee222021-04-27 11:55:13 -0700179 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
180 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
181
Jack Nudelman644b91a2021-03-12 14:09:48 -0800182 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
183 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
184 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700185 private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
186 "set-satellite-service-package-name";
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700187 private static final String SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME =
188 "set-satellite-gateway-service-package-name";
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700189 private static final String SET_SATELLITE_LISTENING_TIMEOUT_DURATION =
190 "set-satellite-listening-timeout-duration";
Thomas Nguyen87dce732023-04-20 18:27:16 -0700191 private static final String SET_SATELLITE_POINTING_UI_CLASS_NAME =
192 "set-satellite-pointing-ui-class-name";
Hakjun Choiae365972023-04-25 11:00:31 +0000193 private static final String SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION =
194 "set-satellite-device-aligned-timeout-duration";
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700195 private static final String SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE =
196 "set-emergency-call-to-satellite-handover-type";
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800197 private static final String SET_COUNTRY_CODES = "set-country-codes";
198 private static final String SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS =
199 "set-satellite-access-control-overlay-configs";
Thomas Nguyen3d602742024-01-19 11:29:35 -0800200 private static final String SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS =
201 "set-oem-enabled-satellite-provision-status";
Hakjun Choibc6ce992023-11-07 16:04:33 +0000202 private static final String SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE =
203 "set-should-send-datagram-to-modem-in-demo-mode";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800204
Grant Menke567d48f2022-08-18 20:19:10 +0000205 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
206 + "'*', '#' or '+') needs to be specified after -a in the command ";
207
208 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
209 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
210 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
211
SongFerngWang98dd5992021-05-13 17:50:00 +0800212 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
213 "get-allowed-network-types-for-users";
214 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
215 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000216 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000217 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700218 // Take advantage of existing methods that already contain permissions checks when possible.
219 private final ITelephony mInterface;
220
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100221 private SubscriptionManager mSubscriptionManager;
222 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700223 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700224 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100225
226 private enum CcType {
227 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000228 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100229 }
230
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100231 private class CcOptionParseResult {
232 public int mSubId;
233 public boolean mPersistent;
234 }
235
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100236 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
237 // keys by looking at the end of the string which usually tells the type.
238 // For instance: "xxxx_string", "xxxx_string_array", etc.
239 // The carrier config keys in this map does not follow this convention. It is therefore not
240 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700241 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
242 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
243 CcType.STRING),
244 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
245 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
246 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
247 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
248 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
249 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
250 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
251 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
252 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
253 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
254 CcType.STRING),
255 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
256 CcType.STRING_ARRAY),
257 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
258 CcType.STRING_ARRAY),
259 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
260 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
261 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
262 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
263 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
264 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
265 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
266 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100267
Brad Ebinger14d467f2021-02-12 06:18:28 +0000268 /**
269 * Map from a shorthand string to the feature tags required in registration required in order
270 * for the RCS feature to be considered "capable".
271 */
272 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
273 static {
274 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
275 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
276 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
277 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
278 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
279 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
280 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
281 FeatureTags.FEATURE_TAG_VIDEO)));
282 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
283 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
284 map.put("call_comp",
285 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
286 map.put("call_comp_mmtel",
287 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
288 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
289 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
290 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
291 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
292 // version
293 map.put("chatbot", new ArraySet<>(Arrays.asList(
294 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
295 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
296 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
297 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000298 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000299 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
300 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
301 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
302 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
303 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000304 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000305 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
306 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
307 }
308
309
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100310 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700311 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100312 mCarrierConfigManager =
313 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
314 mSubscriptionManager = (SubscriptionManager)
315 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700316 mTelephonyRegistryManager = (TelephonyRegistryManager)
317 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700318 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700319 }
320
321 @Override
322 public int onCommand(String cmd) {
323 if (cmd == null) {
324 return handleDefaultCommands(null);
325 }
326
327 switch (cmd) {
328 case IMS_SUBCOMMAND: {
329 return handleImsCommand();
330 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800331 case RCS_UCE_COMMAND:
332 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800333 case NUMBER_VERIFICATION_SUBCOMMAND:
334 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800335 case EMERGENCY_CALLBACK_MODE:
336 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800337 case EMERGENCY_NUMBER_TEST_MODE:
338 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100339 case CARRIER_CONFIG_SUBCOMMAND: {
340 return handleCcCommand();
341 }
Shuo Qianf5125122019-12-16 17:03:07 -0800342 case DATA_TEST_MODE:
343 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700344 case END_BLOCK_SUPPRESSION:
345 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000346 case EUICC_SUBCOMMAND:
347 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700348 case GBA_SUBCOMMAND:
349 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800350 case D2D_SUBCOMMAND:
351 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700352 case BARRING_SUBCOMMAND:
353 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000354 case SINGLE_REGISTATION_CONFIG:
355 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000356 case RESTART_MODEM:
357 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800358 case CALL_COMPOSER_SUBCOMMAND:
359 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000360 case UNATTENDED_REBOOT:
361 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800362 case HAS_CARRIER_PRIVILEGES_COMMAND:
363 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800364 case THERMAL_MITIGATION_COMMAND:
365 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700366 case DISABLE_PHYSICAL_SUBSCRIPTION:
367 return handleEnablePhysicalSubscription(false);
368 case ENABLE_PHYSICAL_SUBSCRIPTION:
369 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800370 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
371 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
372 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000373 case GET_IMEI:
374 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000375 case GET_SIM_SLOTS_MAPPING:
376 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800377 case RADIO_SUBCOMMAND:
378 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000379 case CARRIER_RESTRICTION_STATUS_TEST:
380 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000381 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
382 return setCarrierServicePackageOverride();
383 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
384 return clearCarrierServicePackageOverride();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700385 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
386 return handleSetSatelliteServicePackageNameCommand();
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700387 case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
388 return handleSetSatelliteGatewayServicePackageNameCommand();
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700389 case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
390 return handleSetSatelliteListeningTimeoutDuration();
Thomas Nguyen87dce732023-04-20 18:27:16 -0700391 case SET_SATELLITE_POINTING_UI_CLASS_NAME:
392 return handleSetSatellitePointingUiClassNameCommand();
Hakjun Choiae365972023-04-25 11:00:31 +0000393 case SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION:
394 return handleSettSatelliteDeviceAlignedTimeoutDuration();
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700395 case SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE:
396 return handleSetEmergencyCallToSatelliteHandoverType();
Hakjun Choibc6ce992023-11-07 16:04:33 +0000397 case SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE:
398 return handleSetShouldSendDatagramToModemInDemoMode();
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800399 case SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS:
400 return handleSetSatelliteAccessControlOverlayConfigs();
401 case SET_COUNTRY_CODES:
402 return handleSetCountryCodes();
Thomas Nguyen3d602742024-01-19 11:29:35 -0800403 case SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS:
404 return handleSetOemEnabledSatelliteProvisionStatus();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700405 default: {
406 return handleDefaultCommands(cmd);
407 }
408 }
409 }
410
411 @Override
412 public void onHelp() {
413 PrintWriter pw = getOutPrintWriter();
414 pw.println("Telephony Commands:");
415 pw.println(" help");
416 pw.println(" Print this help text.");
417 pw.println(" ims");
418 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800419 pw.println(" uce");
420 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800421 pw.println(" emergency-number-test-mode");
422 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700423 pw.println(" end-block-suppression");
424 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800425 pw.println(" data");
426 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100427 pw.println(" cc");
428 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700429 pw.println(" gba");
430 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000431 pw.println(" src");
432 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000433 pw.println(" restart-modem");
434 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000435 pw.println(" unattended-reboot");
436 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800437 pw.println(" has-carrier-privileges [package]");
438 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800439 pw.println(" get-allowed-network-types-for-users");
440 pw.println(" Get the Allowed Network Types.");
441 pw.println(" set-allowed-network-types-for-users");
442 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800443 pw.println(" radio");
444 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700445 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800446 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800447 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700448 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800449 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100450 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700451 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000452 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800453 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700454 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800455 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800456 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000457 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700458 onHelpSatellite();
Tyler Gunn92479152021-01-20 16:30:10 -0800459 }
460
461 private void onHelpD2D() {
462 PrintWriter pw = getOutPrintWriter();
463 pw.println("D2D Comms Commands:");
464 pw.println(" d2d send TYPE VALUE");
465 pw.println(" Sends a D2D message of specified type and value.");
466 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
467 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
468 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
469 MESSAGE_CALL_AUDIO_CODEC));
470 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
471 + Communicator.messageToString(
472 MESSAGE_DEVICE_BATTERY_STATE));
473 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
474 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800475 pw.println(" d2d transport TYPE");
476 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
477 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700478 pw.println(" d2d set-device-support true/default");
479 pw.println(" true - forces device support to be enabled for D2D.");
480 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
481 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700482 }
483
Nazanin014f41e2021-05-06 17:26:31 -0700484 private void onHelpBarring() {
485 PrintWriter pw = getOutPrintWriter();
486 pw.println("Barring Commands:");
487 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
488 + " -t CONDITIONAL_BARRING_TIME_SECS");
489 pw.println(" Notifies of a barring info change for the specified slot id.");
490 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
491 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
492 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
493 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
494 }
495
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700496 private void onHelpIms() {
497 PrintWriter pw = getOutPrintWriter();
498 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800499 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700500 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
501 pw.println(" ImsService. Options are:");
502 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
503 pw.println(" is specified, it will choose the default voice SIM slot.");
504 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
505 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800506 pw.println(" -f: Set the feature that this override if for, if no option is");
507 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700508 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
509 pw.println(" Gets the package name of the currently defined ImsService.");
510 pw.println(" Options are:");
511 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
512 pw.println(" is specified, it will choose the default voice SIM slot.");
513 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000514 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800515 pw.println(" -f: The feature type that the query will be requested for. If none is");
516 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800517 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
518 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
519 pw.println(" configuration overrides. Options are:");
520 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
521 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700522 pw.println(" ims enable [-s SLOT_ID]");
523 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
524 pw.println(" if none is specified.");
525 pw.println(" ims disable [-s SLOT_ID]");
526 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
527 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700528 pw.println(" ims conference-event-package [enable/disable]");
529 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700530 }
531
James.cf Linbcdf8b32021-01-14 16:44:13 +0800532 private void onHelpUce() {
533 PrintWriter pw = getOutPrintWriter();
534 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800535 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
536 pw.println(" Get the EAB contacts from the EAB database.");
537 pw.println(" Options are:");
538 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
539 pw.println(" Expected output format :");
540 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800541 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
542 pw.println(" Remove the EAB contacts from the EAB database.");
543 pw.println(" Options are:");
544 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
545 pw.println(" is specified, it will choose the default voice SIM slot.");
546 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800547 pw.println(" uce get-device-enabled");
548 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
549 pw.println(" uce set-device-enabled true|false");
550 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
551 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000552 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
553 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
554 pw.println(" Options are:");
555 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
556 pw.println(" is specified, it will choose the default voice SIM slot.");
557 pw.println(" add [CAPABILITY]: add a new capability");
558 pw.println(" remove [CAPABILITY]: remove a capability");
559 pw.println(" clear: clear all capability overrides");
560 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
561 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
562 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
563 pw.println(" chatbot_sa, chatbot_role] as well as full length");
564 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
565 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
566 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
567 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800568 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
569 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800570 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
571 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800572 }
573
Hall Liud892bec2018-11-30 14:51:45 -0800574 private void onHelpNumberVerification() {
575 PrintWriter pw = getOutPrintWriter();
576 pw.println("Number verification commands");
577 pw.println(" numverify override-package PACKAGE_NAME;");
578 pw.println(" Set the authorized package for number verification.");
579 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800580 pw.println(" numverify fake-call NUMBER;");
581 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
582 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800583 }
584
Jack Nudelman644b91a2021-03-12 14:09:48 -0800585 private void onHelpThermalMitigation() {
586 PrintWriter pw = getOutPrintWriter();
587 pw.println("Thermal mitigation commands");
588 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
589 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
590 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
591 pw.println(" Remove the package from one of the authorized packages for thermal "
592 + "mitigation.");
593 }
594
Jordan Liu0ccee222021-04-27 11:55:13 -0700595 private void onHelpDisableOrEnablePhysicalSubscription() {
596 PrintWriter pw = getOutPrintWriter();
597 pw.println("Disable or enable a physical subscription");
598 pw.println(" disable-physical-subscription SUB_ID");
599 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
600 pw.println(" enable-physical-subscription SUB_ID");
601 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
602 }
603
Shuo Qianf5125122019-12-16 17:03:07 -0800604 private void onHelpDataTestMode() {
605 PrintWriter pw = getOutPrintWriter();
606 pw.println("Mobile Data Test Mode Commands:");
607 pw.println(" data enable: enable mobile data connectivity");
608 pw.println(" data disable: disable mobile data connectivity");
609 }
610
sqian9d4df8b2019-01-15 18:32:07 -0800611 private void onHelpEmergencyNumber() {
612 PrintWriter pw = getOutPrintWriter();
613 pw.println("Emergency Number Test Mode Commands:");
614 pw.println(" emergency-number-test-mode ");
615 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
616 + " the test mode");
617 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700618 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800619 pw.println(" -c: clear the emergency number list in the test mode.");
620 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700621 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800622 pw.println(" -p: get the full emergency number list in the test mode.");
623 }
624
Shuo Qian489d9282020-07-09 11:30:03 -0700625 private void onHelpEndBlockSupperssion() {
626 PrintWriter pw = getOutPrintWriter();
627 pw.println("End Block Suppression command:");
628 pw.println(" end-block-suppression: disable suppressing blocking by contact");
629 pw.println(" with emergency services.");
630 }
631
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100632 private void onHelpCc() {
633 PrintWriter pw = getOutPrintWriter();
634 pw.println("Carrier Config Commands:");
635 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
636 pw.println(" Print carrier config values.");
637 pw.println(" Options are:");
638 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
639 pw.println(" is specified, it will choose the default voice SIM slot.");
640 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
641 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100642 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100643 pw.println(" Set carrier config KEY to NEW_VALUE.");
644 pw.println(" Options are:");
645 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
646 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100647 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100648 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
649 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
650 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
651 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000652 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
653 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
654 pw.println(" provided through standard input and follow CarrierConfig XML format.");
655 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
656 pw.println(" Options are:");
657 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
658 pw.println(" is specified, it will choose the default voice SIM slot.");
659 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100660 pw.println(" cc clear-values [-s SLOT_ID]");
661 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000662 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100663 pw.println(" Options are:");
664 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
665 pw.println(" is specified, it will choose the default voice SIM slot.");
666 }
667
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000668 private void onHelpEuicc() {
669 PrintWriter pw = getOutPrintWriter();
670 pw.println("Euicc Commands:");
671 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
672 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
673 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
674 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
675 }
676
Hui Wang641e81c2020-10-12 12:14:23 -0700677 private void onHelpGba() {
678 PrintWriter pw = getOutPrintWriter();
679 pw.println("Gba Commands:");
680 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
681 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
682 pw.println(" Options are:");
683 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
684 pw.println(" is specified, it will choose the default voice SIM slot.");
685 pw.println(" gba get-service [-s SLOT_ID]");
686 pw.println(" Gets the package name of the currently defined GbaService.");
687 pw.println(" Options are:");
688 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
689 pw.println(" is specified, it will choose the default voice SIM slot.");
690 pw.println(" gba set-release [-s SLOT_ID] n");
691 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
692 pw.println(" Do not release/unbind if n is -1.");
693 pw.println(" Options are:");
694 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
695 pw.println(" is specified, it will choose the default voice SIM slot.");
696 pw.println(" gba get-release [-s SLOT_ID]");
697 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
698 pw.println(" Options are:");
699 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
700 pw.println(" is specified, it will choose the default voice SIM slot.");
701 }
702
Hui Wang761a6682020-10-31 05:12:53 +0000703 private void onHelpSrc() {
704 PrintWriter pw = getOutPrintWriter();
705 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800706 pw.println(" src set-test-enabled true|false");
707 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
708 pw.println(" The value could be true, false, or null(undefined).");
709 pw.println(" src get-test-enabled");
710 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000711 pw.println(" src set-device-enabled true|false|null");
712 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
713 pw.println(" The value could be true, false, or null(undefined).");
714 pw.println(" src get-device-enabled");
715 pw.println(" Gets the device config for RCS VoLTE single registration.");
716 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
717 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
718 pw.println(" The value could be true, false, or null(undefined).");
719 pw.println(" Options are:");
720 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
721 pw.println(" is specified, it will choose the default voice SIM slot.");
722 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
723 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
724 pw.println(" Options are:");
725 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
726 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800727 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
728 pw.println(" Sets ims feature validation result.");
729 pw.println(" The value could be true, false, or null(undefined).");
730 pw.println(" Options are:");
731 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
732 pw.println(" is specified, it will choose the default voice SIM slot.");
733 pw.println(" src get-feature-validation [-s SLOT_ID]");
734 pw.println(" Gets ims feature validation override value.");
735 pw.println(" Options are:");
736 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
737 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000738 }
739
SongFerngWang98dd5992021-05-13 17:50:00 +0800740 private void onHelpAllowedNetworkTypes() {
741 PrintWriter pw = getOutPrintWriter();
742 pw.println("Allowed Network Types Commands:");
743 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
744 pw.println(" Print allowed network types value.");
745 pw.println(" Options are:");
746 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
747 pw.println(" option is specified, it will choose the default voice SIM slot.");
748 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
749 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
750 pw.println(" Options are:");
751 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
752 pw.println(" option is specified, it will choose the default voice SIM slot.");
753 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
754 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
755 pw.println(" at TelephonyManager.java");
756 pw.println(" For example:");
757 pw.println(" NR only : 10000000000000000000");
758 pw.println(" NR|LTE : 11000001000000000000");
759 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
760 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
761 pw.println(" LTE only : 01000001000000000000");
762 }
763
jimsun3b9ccac2021-10-26 15:01:23 +0800764 private void onHelpRadio() {
765 PrintWriter pw = getOutPrintWriter();
766 pw.println("Radio Commands:");
767 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
768 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
769 pw.println(" to be the bound. Options are:");
770 pw.println(" -s: the service name that the modem service should be bound for.");
771 pw.println(" If no option is specified, it will bind to the default.");
772 pw.println(" radio get-modem-service");
773 pw.println(" Gets the service name of the currently defined modem service.");
774 pw.println(" If it is binding to default, 'default' returns.");
775 pw.println(" If it doesn't bind to any modem service for some reasons,");
776 pw.println(" the result would be 'unknown'.");
777 }
778
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700779 private void onHelpSatellite() {
780 PrintWriter pw = getOutPrintWriter();
781 pw.println("Satellite Commands:");
782 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
783 pw.println(" Sets the package name of satellite service defined in");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700784 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700785 pw.println(" -s: the satellite service package name that Telephony will bind to.");
786 pw.println(" If no option is specified, it will bind to the default.");
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700787 pw.println(" set-satellite-gateway-service-package-name [-s SERVICE_PACKAGE_NAME]");
788 pw.println(" Sets the package name of satellite gateway service defined in");
789 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
790 pw.println(" -s: the satellite gateway service package name that Telephony will bind");
791 pw.println(" to. If no option is specified, it will bind to the default.");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700792 pw.println(" set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
793 pw.println(" Sets the timeout duration in millis that satellite will stay at listening");
794 pw.println(" mode. Options are:");
795 pw.println(" -t: the timeout duration in milliseconds.");
796 pw.println(" If no option is specified, it will use the default values.");
Thomas Nguyen87dce732023-04-20 18:27:16 -0700797 pw.println(" set-satellite-pointing-ui-class-name [-p PACKAGE_NAME -c CLASS_NAME]");
798 pw.println(" Sets the package and class name of satellite pointing UI app defined in");
799 pw.println(" PACKAGE_NAME and CLASS_NAME to be launched. Options are:");
800 pw.println(" -p: the satellite pointing UI app package name that Telephony will");
801 pw.println(" launch. If no option is specified, it will launch the default.");
802 pw.println(" -c: the satellite pointing UI app class name that Telephony will");
803 pw.println(" launch.");
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700804 pw.println(" set-emergency-call-to-satellite-handover-type [-t HANDOVER_TYPE ");
805 pw.println(" -d DELAY_SECONDS] Override connectivity status in monitoring emergency ");
806 pw.println(" call and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.");
807 pw.println(" Options are:");
808 pw.println(" -t: the emergency call to satellite handover type.");
809 pw.println(" If no option is specified, override is disabled.");
810 pw.println(" -d: the delay in seconds in sending EVENT_DISPLAY_EMERGENCY_MESSAGE.");
811 pw.println(" If no option is specified, there is no delay in sending the event.");
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800812 pw.println(" set-satellite-access-control-overlay-configs [-r -a -f SATELLITE_S2_FILE ");
813 pw.println(" -d LOCATION_FRESH_DURATION_NANOS -c COUNTRY_CODES] Override the overlay");
814 pw.println(" configs of satellite access controller.");
815 pw.println(" Options are:");
816 pw.println(" -r: clear the overriding. Absent means enable overriding.");
817 pw.println(" -a: the country codes is an allowed list. Absent means disallowed.");
818 pw.println(" -f: the satellite s2 file.");
819 pw.println(" -d: the location fresh duration nanos.");
820 pw.println(" -c: the list of satellite country codes separated by comma.");
821 pw.println(" set-country-codes [-r -n CURRENT_NETWORK_COUNTRY_CODES -c");
822 pw.println(" CACHED_NETWORK_COUNTRY_CODES -l LOCATION_COUNTRY_CODE -t");
823 pw.println(" LOCATION_COUNTRY_CODE_TIMESTAMP] ");
824 pw.println(" Override the cached location country code and its update timestamp. ");
825 pw.println(" Options are:");
826 pw.println(" -r: clear the overriding. Absent means enable overriding.");
827 pw.println(" -n: the current network country code ISOs.");
828 pw.println(" -c: the cached network country code ISOs.");
829 pw.println(" -l: the location country code ISO.");
830 pw.println(" -t: the update timestamp nanos of the location country code.");
Thomas Nguyen3d602742024-01-19 11:29:35 -0800831 pw.println(" set-oem-enabled-satellite-provision-status [-p true/false]");
832 pw.println(" Sets the OEM-enabled satellite provision status. Options are:");
833 pw.println(" -p: the overriding satellite provision status. If no option is ");
834 pw.println(" specified, reset the overridden provision status.");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700835 }
836
Ling Ma4fbab492022-01-25 22:36:16 +0000837 private void onHelpImei() {
838 PrintWriter pw = getOutPrintWriter();
839 pw.println("IMEI Commands:");
840 pw.println(" get-imei [-s SLOT_ID]");
841 pw.println(" Gets the device IMEI. Options are:");
842 pw.println(" -s: the slot ID to get the IMEI. If no option");
843 pw.println(" is specified, it will choose the default voice SIM slot.");
844 }
845
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700846 private int handleImsCommand() {
847 String arg = getNextArg();
848 if (arg == null) {
849 onHelpIms();
850 return 0;
851 }
852
853 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800854 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700855 return handleImsSetServiceCommand();
856 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800857 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700858 return handleImsGetServiceCommand();
859 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800860 case IMS_CLEAR_SERVICE_OVERRIDE: {
861 return handleImsClearCarrierServiceCommand();
862 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800863 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700864 return handleEnableIms();
865 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800866 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700867 return handleDisableIms();
868 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700869 case IMS_CEP: {
870 return handleCepChange();
871 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700872 }
873
874 return -1;
875 }
876
Shuo Qianf5125122019-12-16 17:03:07 -0800877 private int handleDataTestModeCommand() {
878 PrintWriter errPw = getErrPrintWriter();
879 String arg = getNextArgRequired();
880 if (arg == null) {
881 onHelpDataTestMode();
882 return 0;
883 }
884 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800885 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800886 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700887 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800888 } catch (RemoteException ex) {
889 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
890 errPw.println("Exception: " + ex.getMessage());
891 return -1;
892 }
893 break;
894 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800895 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800896 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700897 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800898 } catch (RemoteException ex) {
899 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
900 errPw.println("Exception: " + ex.getMessage());
901 return -1;
902 }
903 break;
904 }
905 default:
906 onHelpDataTestMode();
907 break;
908 }
909 return 0;
910 }
911
Shuo Qianccbaf742021-02-22 18:32:21 -0800912 private int handleEmergencyCallbackModeCommand() {
913 PrintWriter errPw = getErrPrintWriter();
914 try {
915 mInterface.startEmergencyCallbackMode();
916 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
917 } catch (RemoteException ex) {
918 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
919 errPw.println("Exception: " + ex.getMessage());
920 return -1;
921 }
922 return 0;
923 }
924
Grant Menke567d48f2022-08-18 20:19:10 +0000925 private void removeEmergencyNumberTestMode(String emergencyNumber) {
926 PrintWriter errPw = getErrPrintWriter();
927 for (int routingType : ROUTING_TYPES) {
928 try {
929 mInterface.updateEmergencyNumberListTestMode(
930 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
931 new EmergencyNumber(emergencyNumber, "", "",
932 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
933 new ArrayList<String>(),
934 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
935 routingType));
936 } catch (RemoteException ex) {
937 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
938 errPw.println("Exception: " + ex.getMessage());
939 }
940 }
941 }
942
sqian9d4df8b2019-01-15 18:32:07 -0800943 private int handleEmergencyNumberTestModeCommand() {
944 PrintWriter errPw = getErrPrintWriter();
945 String opt = getNextOption();
946 if (opt == null) {
947 onHelpEmergencyNumber();
948 return 0;
949 }
sqian9d4df8b2019-01-15 18:32:07 -0800950 switch (opt) {
951 case "-a": {
952 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000953 if (emergencyNumberCmd == null){
954 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800955 return -1;
956 }
Grant Menke567d48f2022-08-18 20:19:10 +0000957 String[] params = emergencyNumberCmd.split(":");
958 String emergencyNumber;
959 if (params[0] == null ||
960 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
961 errPw.println(INVALID_ENTRY_ERROR);
962 return -1;
963 } else {
964 emergencyNumber = params[0];
965 }
966 removeEmergencyNumberTestMode(emergencyNumber);
967 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
968 if (params.length > 1) {
969 switch (params[1].toLowerCase(Locale.ROOT)) {
970 case "emergency":
971 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
972 break;
973 case "normal":
974 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
975 break;
976 case "unknown":
977 break;
978 default:
979 errPw.println("\"" + params[1] + "\" is not a valid specification for "
980 + "emergency call routing. Please enter either \"normal\", "
981 + "\"unknown\", or \"emergency\" for call routing. "
982 + "(-a 1234:normal)");
983 return -1;
984 }
985 }
sqian9d4df8b2019-01-15 18:32:07 -0800986 try {
987 mInterface.updateEmergencyNumberListTestMode(
988 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000989 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800990 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
991 new ArrayList<String>(),
992 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000993 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800994 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000995 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800996 + ", error " + ex.getMessage());
997 errPw.println("Exception: " + ex.getMessage());
998 return -1;
999 }
1000 break;
1001 }
1002 case "-c": {
1003 try {
1004 mInterface.updateEmergencyNumberListTestMode(
1005 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
1006 } catch (RemoteException ex) {
1007 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
1008 errPw.println("Exception: " + ex.getMessage());
1009 return -1;
1010 }
1011 break;
1012 }
1013 case "-r": {
1014 String emergencyNumberCmd = getNextArgRequired();
1015 if (emergencyNumberCmd == null
1016 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -07001017 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -08001018 + " to be specified after -r in the command ");
1019 return -1;
1020 }
Grant Menke567d48f2022-08-18 20:19:10 +00001021 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -08001022 break;
1023 }
1024 case "-p": {
1025 try {
1026 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
1027 } catch (RemoteException ex) {
1028 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
1029 errPw.println("Exception: " + ex.getMessage());
1030 return -1;
1031 }
1032 break;
1033 }
1034 default:
1035 onHelpEmergencyNumber();
1036 break;
1037 }
1038 return 0;
1039 }
1040
Hall Liud892bec2018-11-30 14:51:45 -08001041 private int handleNumberVerificationCommand() {
1042 String arg = getNextArg();
1043 if (arg == null) {
1044 onHelpNumberVerification();
1045 return 0;
1046 }
1047
Hall Liuca5af3a2018-12-04 16:58:23 -08001048 if (!checkShellUid()) {
1049 return -1;
1050 }
1051
Hall Liud892bec2018-11-30 14:51:45 -08001052 switch (arg) {
1053 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -08001054 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
1055 return 0;
1056 }
Hall Liuca5af3a2018-12-04 16:58:23 -08001057 case NUMBER_VERIFICATION_FAKE_CALL: {
1058 boolean val = NumberVerificationManager.getInstance()
1059 .checkIncomingCall(getNextArg());
1060 getOutPrintWriter().println(val ? "1" : "0");
1061 return 0;
1062 }
Hall Liud892bec2018-11-30 14:51:45 -08001063 }
1064
1065 return -1;
1066 }
1067
Jordan Liu0ccee222021-04-27 11:55:13 -07001068 private boolean subIsEsim(int subId) {
1069 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
1070 if (info != null) {
1071 return info.isEmbedded();
1072 }
1073 return false;
1074 }
1075
1076 private int handleEnablePhysicalSubscription(boolean enable) {
1077 PrintWriter errPw = getErrPrintWriter();
1078 int subId = 0;
1079 try {
1080 subId = Integer.parseInt(getNextArgRequired());
1081 } catch (NumberFormatException e) {
1082 errPw.println((enable ? "enable" : "disable")
1083 + "-physical-subscription requires an integer as a subId.");
1084 return -1;
1085 }
1086 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1087 // non user build.
1088 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1089 errPw.println("cc: Permission denied.");
1090 return -1;
1091 }
1092 // Verify that the subId represents a physical sub
1093 if (subIsEsim(subId)) {
1094 errPw.println("SubId " + subId + " is not for a physical subscription");
1095 return -1;
1096 }
1097 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1098 + " physical subscription with subId=" + subId);
1099 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1100 return 0;
1101 }
1102
Jack Nudelman644b91a2021-03-12 14:09:48 -08001103 private int handleThermalMitigationCommand() {
1104 String arg = getNextArg();
1105 String packageName = getNextArg();
1106 if (arg == null || packageName == null) {
1107 onHelpThermalMitigation();
1108 return 0;
1109 }
1110
1111 if (!checkShellUid()) {
1112 return -1;
1113 }
1114
1115 switch (arg) {
1116 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1117 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1118 return 0;
1119 }
1120 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1121 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1122 mContext);
1123 return 0;
1124 }
1125 default:
1126 onHelpThermalMitigation();
1127 }
1128
1129 return -1;
1130
1131 }
1132
Tyler Gunn92479152021-01-20 16:30:10 -08001133 private int handleD2dCommand() {
1134 String arg = getNextArg();
1135 if (arg == null) {
1136 onHelpD2D();
1137 return 0;
1138 }
1139
1140 switch (arg) {
1141 case D2D_SEND: {
1142 return handleD2dSendCommand();
1143 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001144 case D2D_TRANSPORT: {
1145 return handleD2dTransportCommand();
1146 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001147 case D2D_SET_DEVICE_SUPPORT: {
1148 return handleD2dDeviceSupportedCommand();
1149 }
Tyler Gunn92479152021-01-20 16:30:10 -08001150 }
1151
1152 return -1;
1153 }
1154
1155 private int handleD2dSendCommand() {
1156 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001157 int messageType = -1;
1158 int messageValue = -1;
1159
Tyler Gunn92479152021-01-20 16:30:10 -08001160 String arg = getNextArg();
1161 if (arg == null) {
1162 onHelpD2D();
1163 return 0;
1164 }
1165 try {
1166 messageType = Integer.parseInt(arg);
1167 } catch (NumberFormatException e) {
1168 errPw.println("message type must be a valid integer");
1169 return -1;
1170 }
1171
1172 arg = getNextArg();
1173 if (arg == null) {
1174 onHelpD2D();
1175 return 0;
1176 }
1177 try {
1178 messageValue = Integer.parseInt(arg);
1179 } catch (NumberFormatException e) {
1180 errPw.println("message value must be a valid integer");
1181 return -1;
1182 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001183
Tyler Gunn92479152021-01-20 16:30:10 -08001184 try {
1185 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1186 } catch (RemoteException e) {
1187 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1188 errPw.println("Exception: " + e.getMessage());
1189 return -1;
1190 }
1191
1192 return 0;
1193 }
1194
Tyler Gunnbabbda02021-02-10 11:05:02 -08001195 private int handleD2dTransportCommand() {
1196 PrintWriter errPw = getErrPrintWriter();
1197
1198 String arg = getNextArg();
1199 if (arg == null) {
1200 onHelpD2D();
1201 return 0;
1202 }
1203
1204 try {
1205 mInterface.setActiveDeviceToDeviceTransport(arg);
1206 } catch (RemoteException e) {
1207 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1208 errPw.println("Exception: " + e.getMessage());
1209 return -1;
1210 }
1211 return 0;
1212 }
Nazanin014f41e2021-05-06 17:26:31 -07001213 private int handleBarringCommand() {
1214 String arg = getNextArg();
1215 if (arg == null) {
1216 onHelpBarring();
1217 return 0;
1218 }
1219
1220 switch (arg) {
1221 case BARRING_SEND_INFO: {
1222 return handleBarringSendCommand();
1223 }
1224 }
1225 return -1;
1226 }
1227
1228 private int handleBarringSendCommand() {
1229 PrintWriter errPw = getErrPrintWriter();
1230 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001231 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001232 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1233 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1234 boolean isConditionallyBarred = false;
1235 int conditionalBarringTimeSeconds = 0;
1236
1237 String opt;
1238 while ((opt = getNextOption()) != null) {
1239 switch (opt) {
1240 case "-s": {
1241 try {
1242 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001243 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001244 } catch (NumberFormatException e) {
1245 errPw.println("barring send requires an integer as a SLOT_ID.");
1246 return -1;
1247 }
1248 break;
1249 }
1250 case "-b": {
1251 try {
1252 barringType = Integer.parseInt(getNextArgRequired());
1253 if (barringType < -1 || barringType > 2) {
1254 throw new NumberFormatException();
1255 }
1256
1257 } catch (NumberFormatException e) {
1258 errPw.println("barring send requires an integer in range [-1,2] as "
1259 + "a BARRING_TYPE.");
1260 return -1;
1261 }
1262 break;
1263 }
1264 case "-c": {
1265 try {
1266 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1267 } catch (Exception e) {
1268 errPw.println("barring send requires a boolean after -c indicating"
1269 + " conditional barring");
1270 return -1;
1271 }
1272 break;
1273 }
1274 case "-t": {
1275 try {
1276 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1277 } catch (NumberFormatException e) {
1278 errPw.println("barring send requires an integer for time of barring"
1279 + " in seconds after -t for conditional barring");
1280 return -1;
1281 }
1282 break;
1283 }
1284 }
1285 }
1286 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1287 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1288 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1289 barringServiceInfos.append(0, bsi);
1290 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1291 try {
1292 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1293 } catch (Exception e) {
1294 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1295 errPw.println("Exception: " + e.getMessage());
1296 return -1;
1297 }
1298 return 0;
1299 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001300
Tyler Gunnd4575212021-05-03 14:46:49 -07001301 private int handleD2dDeviceSupportedCommand() {
1302 PrintWriter errPw = getErrPrintWriter();
1303
1304 String arg = getNextArg();
1305 if (arg == null) {
1306 onHelpD2D();
1307 return 0;
1308 }
1309
Jack Yua533d632022-09-30 13:53:46 -07001310 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001311 try {
1312 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1313 } catch (RemoteException e) {
1314 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1315 errPw.println("Exception: " + e.getMessage());
1316 return -1;
1317 }
1318 return 0;
1319 }
1320
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001321 // ims set-ims-service
1322 private int handleImsSetServiceCommand() {
1323 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001324 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001325 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001326 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001327
1328 String opt;
1329 while ((opt = getNextOption()) != null) {
1330 switch (opt) {
1331 case "-s": {
1332 try {
1333 slotId = Integer.parseInt(getNextArgRequired());
1334 } catch (NumberFormatException e) {
1335 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1336 return -1;
1337 }
1338 break;
1339 }
1340 case "-c": {
1341 isCarrierService = true;
1342 break;
1343 }
1344 case "-d": {
1345 isCarrierService = false;
1346 break;
1347 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001348 case "-f": {
1349 String featureString = getNextArgRequired();
1350 String[] features = featureString.split(",");
1351 for (int i = 0; i < features.length; i++) {
1352 try {
1353 Integer result = Integer.parseInt(features[i]);
1354 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1355 || result >= ImsFeature.FEATURE_MAX) {
1356 errPw.println("ims set-ims-service -f " + result
1357 + " is an invalid feature.");
1358 return -1;
1359 }
1360 featuresList.add(result);
1361 } catch (NumberFormatException e) {
1362 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1363 + " as an integer.");
1364 return -1;
1365 }
1366 }
1367 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001368 }
1369 }
1370 // Mandatory param, either -c or -d
1371 if (isCarrierService == null) {
1372 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1373 return -1;
1374 }
1375
1376 String packageName = getNextArg();
1377
1378 try {
1379 if (packageName == null) {
1380 packageName = "";
1381 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001382 int[] featureArray = new int[featuresList.size()];
1383 for (int i = 0; i < featuresList.size(); i++) {
1384 featureArray[i] = featuresList.get(i);
1385 }
1386 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1387 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001388 if (VDBG) {
1389 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001390 + (isCarrierService ? "-c " : "-d ")
1391 + "-f " + featuresList + " "
1392 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001393 }
1394 getOutPrintWriter().println(result);
1395 } catch (RemoteException e) {
1396 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001397 + (isCarrierService ? "-c " : "-d ")
1398 + "-f " + featuresList + " "
1399 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001400 errPw.println("Exception: " + e.getMessage());
1401 return -1;
1402 }
1403 return 0;
1404 }
1405
Brad Ebinger999d3302020-11-25 14:31:39 -08001406 // ims clear-ims-service-override
1407 private int handleImsClearCarrierServiceCommand() {
1408 PrintWriter errPw = getErrPrintWriter();
1409 int slotId = getDefaultSlot();
1410
1411 String opt;
1412 while ((opt = getNextOption()) != null) {
1413 switch (opt) {
1414 case "-s": {
1415 try {
1416 slotId = Integer.parseInt(getNextArgRequired());
1417 } catch (NumberFormatException e) {
1418 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1419 return -1;
1420 }
1421 break;
1422 }
1423 }
1424 }
1425
1426 try {
1427 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1428 if (VDBG) {
1429 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1430 + ", result=" + result);
1431 }
1432 getOutPrintWriter().println(result);
1433 } catch (RemoteException e) {
1434 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1435 + ", error" + e.getMessage());
1436 errPw.println("Exception: " + e.getMessage());
1437 return -1;
1438 }
1439 return 0;
1440 }
1441
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001442 // ims get-ims-service
1443 private int handleImsGetServiceCommand() {
1444 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001445 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001446 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001447 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001448
1449 String opt;
1450 while ((opt = getNextOption()) != null) {
1451 switch (opt) {
1452 case "-s": {
1453 try {
1454 slotId = Integer.parseInt(getNextArgRequired());
1455 } catch (NumberFormatException e) {
1456 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1457 return -1;
1458 }
1459 break;
1460 }
1461 case "-c": {
1462 isCarrierService = true;
1463 break;
1464 }
1465 case "-d": {
1466 isCarrierService = false;
1467 break;
1468 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001469 case "-f": {
1470 try {
1471 featureType = Integer.parseInt(getNextArg());
1472 } catch (NumberFormatException e) {
1473 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1474 return -1;
1475 }
1476 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1477 || featureType >= ImsFeature.FEATURE_MAX) {
1478 errPw.println("ims get-ims-service -f invalid feature.");
1479 return -1;
1480 }
1481 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001482 }
1483 }
1484 // Mandatory param, either -c or -d
1485 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001486 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001487 return -1;
1488 }
1489
1490 String result;
1491 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001492 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001493 } catch (RemoteException e) {
1494 return -1;
1495 }
1496 if (VDBG) {
1497 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001498 + (isCarrierService ? "-c " : "-d ")
1499 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1500 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001501 }
1502 getOutPrintWriter().println(result);
1503 return 0;
1504 }
1505
1506 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001507 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001508 String opt;
1509 while ((opt = getNextOption()) != null) {
1510 switch (opt) {
1511 case "-s": {
1512 try {
1513 slotId = Integer.parseInt(getNextArgRequired());
1514 } catch (NumberFormatException e) {
1515 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1516 return -1;
1517 }
1518 break;
1519 }
1520 }
1521 }
1522 try {
1523 mInterface.enableIms(slotId);
1524 } catch (RemoteException e) {
1525 return -1;
1526 }
1527 if (VDBG) {
1528 Log.v(LOG_TAG, "ims enable -s " + slotId);
1529 }
1530 return 0;
1531 }
1532
1533 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001534 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001535 String opt;
1536 while ((opt = getNextOption()) != null) {
1537 switch (opt) {
1538 case "-s": {
1539 try {
1540 slotId = Integer.parseInt(getNextArgRequired());
1541 } catch (NumberFormatException e) {
1542 getErrPrintWriter().println(
1543 "ims disable requires an integer as a SLOT_ID.");
1544 return -1;
1545 }
1546 break;
1547 }
1548 }
1549 }
1550 try {
1551 mInterface.disableIms(slotId);
1552 } catch (RemoteException e) {
1553 return -1;
1554 }
1555 if (VDBG) {
1556 Log.v(LOG_TAG, "ims disable -s " + slotId);
1557 }
1558 return 0;
1559 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001560
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001561 private int handleCepChange() {
1562 Log.i(LOG_TAG, "handleCepChange");
1563 String opt = getNextArg();
1564 if (opt == null) {
1565 return -1;
1566 }
1567 boolean isCepEnabled = opt.equals("enable");
1568
1569 try {
1570 mInterface.setCepEnabled(isCepEnabled);
1571 } catch (RemoteException e) {
1572 return -1;
1573 }
1574 return 0;
1575 }
1576
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001577 private int getDefaultSlot() {
1578 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1579 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1580 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1581 // If there is no default, default to slot 0.
1582 slotId = DEFAULT_PHONE_ID;
1583 }
1584 return slotId;
1585 }
sqian2fff4a32018-11-05 14:18:37 -08001586
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001587 // Parse options related to Carrier Config Commands.
1588 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001589 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001590 CcOptionParseResult result = new CcOptionParseResult();
1591 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1592 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001593
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001594 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001595 while ((opt = getNextOption()) != null) {
1596 switch (opt) {
1597 case "-s": {
1598 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001599 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1600 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1601 errPw.println(tag + "No valid subscription found.");
1602 return null;
1603 }
1604
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001605 } catch (IllegalArgumentException e) {
1606 // Missing slot id
1607 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001608 return null;
1609 }
1610 break;
1611 }
1612 case "-p": {
1613 if (allowOptionPersistent) {
1614 result.mPersistent = true;
1615 } else {
1616 errPw.println(tag + "Unexpected option " + opt);
1617 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001618 }
1619 break;
1620 }
1621 default: {
1622 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001623 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001624 }
1625 }
1626 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001627 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001628 }
1629
1630 private int slotStringToSubId(String tag, String slotString) {
1631 int slotId = -1;
1632 try {
1633 slotId = Integer.parseInt(slotString);
1634 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001635 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1636 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1637 }
1638
1639 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001640 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1641 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1642 }
1643
Qiong Liuf25799b2020-09-10 10:13:46 +08001644 Phone phone = PhoneFactory.getPhone(slotId);
1645 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001646 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1647 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1648 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001649 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001650 }
1651
Hall Liud892bec2018-11-30 14:51:45 -08001652 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001653 // adb can run as root or as shell, depending on whether the device is rooted.
1654 return Binder.getCallingUid() == Process.SHELL_UID
1655 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001656 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001657
1658 private int handleCcCommand() {
1659 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1660 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001661 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001662 getErrPrintWriter().println("cc: Permission denied.");
1663 return -1;
1664 }
1665
1666 String arg = getNextArg();
1667 if (arg == null) {
1668 onHelpCc();
1669 return 0;
1670 }
1671
1672 switch (arg) {
1673 case CC_GET_VALUE: {
1674 return handleCcGetValue();
1675 }
1676 case CC_SET_VALUE: {
1677 return handleCcSetValue();
1678 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001679 case CC_SET_VALUES_FROM_XML: {
1680 return handleCcSetValuesFromXml();
1681 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001682 case CC_CLEAR_VALUES: {
1683 return handleCcClearValues();
1684 }
1685 default: {
1686 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1687 }
1688 }
1689 return -1;
1690 }
1691
1692 // cc get-value
1693 private int handleCcGetValue() {
1694 PrintWriter errPw = getErrPrintWriter();
1695 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1696 String key = null;
1697
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001698 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001699 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001700 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001701 return -1;
1702 }
1703
1704 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001705 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001706 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001707 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001708 return -1;
1709 }
1710
1711 // Get the key.
1712 key = getNextArg();
1713 if (key != null) {
1714 // A key was provided. Verify if it is a valid key
1715 if (!bundle.containsKey(key)) {
1716 errPw.println(tag + key + " is not a valid key.");
1717 return -1;
1718 }
1719
1720 // Print the carrier config value for key.
1721 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1722 } else {
1723 // No key provided. Show all values.
1724 // Iterate over a sorted list of all carrier config keys and print them.
1725 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1726 for (String k : sortedSet) {
1727 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1728 }
1729 }
1730 return 0;
1731 }
1732
1733 // cc set-value
1734 private int handleCcSetValue() {
1735 PrintWriter errPw = getErrPrintWriter();
1736 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1737
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001738 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001739 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001740 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001741 return -1;
1742 }
1743
1744 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001745 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001746 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001747 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001748 return -1;
1749 }
1750
1751 // Get the key.
1752 String key = getNextArg();
1753 if (key == null || key.equals("")) {
1754 errPw.println(tag + "KEY is missing");
1755 return -1;
1756 }
1757
1758 // Verify if the key is valid
1759 if (!originalValues.containsKey(key)) {
1760 errPw.println(tag + key + " is not a valid key.");
1761 return -1;
1762 }
1763
1764 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1765 ArrayList<String> valueList = new ArrayList<String>();
1766 while (peekNextArg() != null) {
1767 valueList.add(getNextArg());
1768 }
1769
1770 // Find the type of the carrier config value
1771 CcType type = getType(tag, key, originalValues);
1772 if (type == CcType.UNKNOWN) {
1773 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1774 return -1;
1775 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001776 if (type == CcType.PERSISTABLE_BUNDLE) {
1777 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1778 + "Use set-values-from-xml instead.");
1779 return -1;
1780 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001781
1782 // Create an override bundle containing the key and value that should be overriden.
1783 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1784 if (overrideBundle == null) {
1785 return -1;
1786 }
1787
1788 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001789 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001790
1791 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001792 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001793 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001794 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001795 return -1;
1796 }
1797
1798 // Print the original and new value.
1799 String originalValueString = ccValueToString(key, type, originalValues);
1800 String newValueString = ccValueToString(key, type, newValues);
1801 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1802 getOutPrintWriter().println("New value: \n" + newValueString);
1803
1804 return 0;
1805 }
1806
Allen Xuee00f0e2022-03-14 21:04:49 +00001807 // cc set-values-from-xml
1808 private int handleCcSetValuesFromXml() {
1809 PrintWriter errPw = getErrPrintWriter();
1810 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1811
1812 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001813 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001814 if (options == null) {
1815 return -1;
1816 }
1817
1818 // Get bundle containing all current carrier configuration values.
1819 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1820 if (originalValues == null) {
1821 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1822 return -1;
1823 }
1824
1825 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1826 if (overrideBundle == null) {
1827 return -1;
1828 }
1829
1830 // Verify all values are valid types
1831 for (String key : overrideBundle.keySet()) {
1832 CcType type = getType(tag, key, originalValues);
1833 if (type == CcType.UNKNOWN) {
1834 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1835 return -1;
1836 }
1837 }
1838
1839 // Override the value
1840 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1841
1842 // Find bundle containing all new carrier configuration values after the override.
1843 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1844 if (newValues == null) {
1845 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1846 return -1;
1847 }
1848
1849 // Print the original and new values
1850 overrideBundle.keySet().forEach(key -> {
1851 CcType type = getType(tag, key, originalValues);
1852 String originalValueString = ccValueToString(key, type, originalValues);
1853 String newValueString = ccValueToString(key, type, newValues);
1854 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1855 getOutPrintWriter().println("New value: \n" + newValueString);
1856 });
1857
1858 return 0;
1859 }
1860
1861 private PersistableBundle readPersistableBundleFromXml(String tag) {
1862 PersistableBundle subIdBundles;
1863 try {
1864 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1865 } catch (IOException | RuntimeException e) {
1866 PrintWriter errPw = getErrPrintWriter();
1867 errPw.println(tag + e);
1868 return null;
1869 }
1870
1871 return subIdBundles;
1872 }
1873
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001874 // cc clear-values
1875 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001876 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1877
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001878 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001879 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001880 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001881 return -1;
1882 }
1883
1884 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001885 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001886 getOutPrintWriter()
1887 .println("All previously set carrier config override values has been cleared");
1888 return 0;
1889 }
1890
1891 private CcType getType(String tag, String key, PersistableBundle bundle) {
1892 // Find the type by checking the type of the current value stored in the bundle.
1893 Object value = bundle.get(key);
1894
1895 if (CC_TYPE_MAP.containsKey(key)) {
1896 return CC_TYPE_MAP.get(key);
1897 } else if (value != null) {
1898 if (value instanceof Boolean) {
1899 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001900 }
1901 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001902 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001903 }
1904 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001905 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001906 }
1907 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001908 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001909 }
1910 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001911 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001912 }
1913 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001914 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001915 }
1916 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001917 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001918 }
1919 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001920 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001921 }
1922 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001923 return CcType.STRING_ARRAY;
1924 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001925 if (value instanceof PersistableBundle) {
1926 return CcType.PERSISTABLE_BUNDLE;
1927 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001928 } else {
1929 // Current value was null and can therefore not be used in order to find the type.
1930 // Check the name of the key to infer the type. This check is not needed for primitive
1931 // data types (boolean, double, int and long), since they can not be null.
1932 if (key.endsWith("double_array")) {
1933 return CcType.DOUBLE_ARRAY;
1934 }
1935 if (key.endsWith("int_array")) {
1936 return CcType.INT_ARRAY;
1937 }
1938 if (key.endsWith("long_array")) {
1939 return CcType.LONG_ARRAY;
1940 }
1941 if (key.endsWith("string")) {
1942 return CcType.STRING;
1943 }
1944 if (key.endsWith("string_array") || key.endsWith("strings")) {
1945 return CcType.STRING_ARRAY;
1946 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001947 if (key.endsWith("bundle")) {
1948 return CcType.PERSISTABLE_BUNDLE;
1949 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001950 }
1951
1952 // Not possible to infer the type by looking at the current value or the key.
1953 PrintWriter errPw = getErrPrintWriter();
1954 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1955 return CcType.UNKNOWN;
1956 }
1957
1958 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1959 String result;
1960 StringBuilder valueString = new StringBuilder();
1961 String typeString = type.toString();
1962 Object value = bundle.get(key);
1963
1964 if (value == null) {
1965 valueString.append("null");
1966 } else {
1967 switch (type) {
1968 case DOUBLE_ARRAY: {
1969 // Format the string representation of the int array as value1 value2......
1970 double[] valueArray = (double[]) value;
1971 for (int i = 0; i < valueArray.length; i++) {
1972 if (i != 0) {
1973 valueString.append(" ");
1974 }
1975 valueString.append(valueArray[i]);
1976 }
1977 break;
1978 }
1979 case INT_ARRAY: {
1980 // Format the string representation of the int array as value1 value2......
1981 int[] valueArray = (int[]) value;
1982 for (int i = 0; i < valueArray.length; i++) {
1983 if (i != 0) {
1984 valueString.append(" ");
1985 }
1986 valueString.append(valueArray[i]);
1987 }
1988 break;
1989 }
1990 case LONG_ARRAY: {
1991 // Format the string representation of the int array as value1 value2......
1992 long[] valueArray = (long[]) value;
1993 for (int i = 0; i < valueArray.length; i++) {
1994 if (i != 0) {
1995 valueString.append(" ");
1996 }
1997 valueString.append(valueArray[i]);
1998 }
1999 break;
2000 }
2001 case STRING: {
2002 valueString.append("\"" + value.toString() + "\"");
2003 break;
2004 }
2005 case STRING_ARRAY: {
2006 // Format the string representation of the string array as "value1" "value2"....
2007 String[] valueArray = (String[]) value;
2008 for (int i = 0; i < valueArray.length; i++) {
2009 if (i != 0) {
2010 valueString.append(" ");
2011 }
2012 if (valueArray[i] != null) {
2013 valueString.append("\"" + valueArray[i] + "\"");
2014 } else {
2015 valueString.append("null");
2016 }
2017 }
2018 break;
2019 }
2020 default: {
2021 valueString.append(value.toString());
2022 }
2023 }
2024 }
2025 return String.format("%-70s %-15s %s", key, typeString, valueString);
2026 }
2027
2028 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
2029 ArrayList<String> valueList) {
2030 PrintWriter errPw = getErrPrintWriter();
2031 PersistableBundle bundle = new PersistableBundle();
2032
2033 // First verify that a valid number of values has been provided for the type.
2034 switch (type) {
2035 case BOOLEAN:
2036 case DOUBLE:
2037 case INT:
2038 case LONG: {
2039 if (valueList.size() != 1) {
2040 errPw.println(tag + "Expected 1 value for type " + type
2041 + ". Found: " + valueList.size());
2042 return null;
2043 }
2044 break;
2045 }
2046 case STRING: {
2047 if (valueList.size() > 1) {
2048 errPw.println(tag + "Expected 0 or 1 values for type " + type
2049 + ". Found: " + valueList.size());
2050 return null;
2051 }
2052 break;
2053 }
2054 }
2055
2056 // Parse the value according to type and add it to the Bundle.
2057 switch (type) {
2058 case BOOLEAN: {
2059 if ("true".equalsIgnoreCase(valueList.get(0))) {
2060 bundle.putBoolean(key, true);
2061 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
2062 bundle.putBoolean(key, false);
2063 } else {
2064 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2065 return null;
2066 }
2067 break;
2068 }
2069 case DOUBLE: {
2070 try {
2071 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
2072 } catch (NumberFormatException nfe) {
2073 // Not a valid double
2074 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2075 return null;
2076 }
2077 break;
2078 }
2079 case DOUBLE_ARRAY: {
2080 double[] valueDoubleArray = null;
2081 if (valueList.size() > 0) {
2082 valueDoubleArray = new double[valueList.size()];
2083 for (int i = 0; i < valueList.size(); i++) {
2084 try {
2085 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2086 } catch (NumberFormatException nfe) {
2087 // Not a valid double
2088 errPw.println(
2089 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2090 return null;
2091 }
2092 }
2093 }
2094 bundle.putDoubleArray(key, valueDoubleArray);
2095 break;
2096 }
2097 case INT: {
2098 try {
2099 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2100 } catch (NumberFormatException nfe) {
2101 // Not a valid integer
2102 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2103 return null;
2104 }
2105 break;
2106 }
2107 case INT_ARRAY: {
2108 int[] valueIntArray = null;
2109 if (valueList.size() > 0) {
2110 valueIntArray = new int[valueList.size()];
2111 for (int i = 0; i < valueList.size(); i++) {
2112 try {
2113 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2114 } catch (NumberFormatException nfe) {
2115 // Not a valid integer
2116 errPw.println(tag
2117 + "Unable to parse " + valueList.get(i) + " as an integer.");
2118 return null;
2119 }
2120 }
2121 }
2122 bundle.putIntArray(key, valueIntArray);
2123 break;
2124 }
2125 case LONG: {
2126 try {
2127 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2128 } catch (NumberFormatException nfe) {
2129 // Not a valid long
2130 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2131 return null;
2132 }
2133 break;
2134 }
2135 case LONG_ARRAY: {
2136 long[] valueLongArray = null;
2137 if (valueList.size() > 0) {
2138 valueLongArray = new long[valueList.size()];
2139 for (int i = 0; i < valueList.size(); i++) {
2140 try {
2141 valueLongArray[i] = Long.parseLong(valueList.get(i));
2142 } catch (NumberFormatException nfe) {
2143 // Not a valid long
2144 errPw.println(
2145 tag + "Unable to parse " + valueList.get(i) + " as a long");
2146 return null;
2147 }
2148 }
2149 }
2150 bundle.putLongArray(key, valueLongArray);
2151 break;
2152 }
2153 case STRING: {
2154 String value = null;
2155 if (valueList.size() > 0) {
2156 value = valueList.get(0);
2157 }
2158 bundle.putString(key, value);
2159 break;
2160 }
2161 case STRING_ARRAY: {
2162 String[] valueStringArray = null;
2163 if (valueList.size() > 0) {
2164 valueStringArray = new String[valueList.size()];
2165 valueList.toArray(valueStringArray);
2166 }
2167 bundle.putStringArray(key, valueStringArray);
2168 break;
2169 }
2170 }
2171 return bundle;
2172 }
Shuo Qian489d9282020-07-09 11:30:03 -07002173
2174 private int handleEndBlockSuppressionCommand() {
2175 if (!checkShellUid()) {
2176 return -1;
2177 }
2178
2179 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2180 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2181 }
2182 return 0;
2183 }
Hui Wang641e81c2020-10-12 12:14:23 -07002184
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002185 private int handleEuiccCommand() {
2186 String arg = getNextArg();
2187 if (arg == null) {
2188 onHelpEuicc();
2189 return 0;
2190 }
2191
2192 switch (arg) {
2193 case EUICC_SET_UI_COMPONENT: {
2194 return handleEuiccServiceCommand();
2195 }
2196 }
2197 return -1;
2198 }
2199
2200 private int handleEuiccServiceCommand() {
2201 String uiComponent = getNextArg();
2202 String packageName = getNextArg();
2203 if (packageName == null || uiComponent == null) {
2204 return -1;
2205 }
2206 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2207 if (VDBG) {
2208 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2209 + packageName);
2210 }
2211 return 0;
2212 }
2213
Michele Berionne54af4632020-12-28 20:23:16 +00002214 private int handleRestartModemCommand() {
2215 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2216 // non user build.
2217 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2218 getErrPrintWriter().println("RestartModem: Permission denied.");
2219 return -1;
2220 }
2221
2222 boolean result = TelephonyManager.getDefault().rebootRadio();
2223 getOutPrintWriter().println(result);
2224
2225 return result ? 0 : -1;
2226 }
2227
Ling Ma4fbab492022-01-25 22:36:16 +00002228 private int handleGetImei() {
2229 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2230 // non user build.
2231 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2232 getErrPrintWriter().println("Device IMEI: Permission denied.");
2233 return -1;
2234 }
2235
2236 final long identity = Binder.clearCallingIdentity();
2237
2238 String imei = null;
2239 String arg = getNextArg();
2240 if (arg != null) {
2241 try {
2242 int specifiedSlotIndex = Integer.parseInt(arg);
2243 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2244 } catch (NumberFormatException exception) {
2245 PrintWriter errPw = getErrPrintWriter();
2246 errPw.println("-s requires an integer as slot index.");
2247 return -1;
2248 }
2249
2250 } else {
2251 imei = TelephonyManager.from(mContext).getImei();
2252 }
2253 getOutPrintWriter().println("Device IMEI: " + imei);
2254
2255 Binder.restoreCallingIdentity(identity);
2256 return 0;
2257 }
2258
Michele Berionne5e411512020-11-13 02:36:59 +00002259 private int handleUnattendedReboot() {
2260 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2261 // non user build.
2262 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2263 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2264 return -1;
2265 }
2266
2267 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2268 getOutPrintWriter().println("result: " + result);
2269
2270 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2271 }
2272
Aman Gupta07124872022-02-09 08:02:14 +00002273 private int handleGetSimSlotsMapping() {
2274 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2275 // non user build.
2276 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2277 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2278 return -1;
2279 }
2280 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2281 String result = telephonyManager.getSimSlotMapping().toString();
2282 getOutPrintWriter().println("simSlotsMapping: " + result);
2283
2284 return 0;
2285 }
2286
Hui Wang641e81c2020-10-12 12:14:23 -07002287 private int handleGbaCommand() {
2288 String arg = getNextArg();
2289 if (arg == null) {
2290 onHelpGba();
2291 return 0;
2292 }
2293
2294 switch (arg) {
2295 case GBA_SET_SERVICE: {
2296 return handleGbaSetServiceCommand();
2297 }
2298 case GBA_GET_SERVICE: {
2299 return handleGbaGetServiceCommand();
2300 }
2301 case GBA_SET_RELEASE_TIME: {
2302 return handleGbaSetReleaseCommand();
2303 }
2304 case GBA_GET_RELEASE_TIME: {
2305 return handleGbaGetReleaseCommand();
2306 }
2307 }
2308
2309 return -1;
2310 }
2311
2312 private int getSubId(String cmd) {
2313 int slotId = getDefaultSlot();
2314 String opt = getNextOption();
2315 if (opt != null && opt.equals("-s")) {
2316 try {
2317 slotId = Integer.parseInt(getNextArgRequired());
2318 } catch (NumberFormatException e) {
2319 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2320 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2321 }
2322 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002323 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002324 }
2325
2326 private int handleGbaSetServiceCommand() {
2327 int subId = getSubId("gba set-service");
2328 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2329 return -1;
2330 }
2331
2332 String packageName = getNextArg();
2333 try {
2334 if (packageName == null) {
2335 packageName = "";
2336 }
2337 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2338 if (VDBG) {
2339 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2340 + packageName + ", result=" + result);
2341 }
2342 getOutPrintWriter().println(result);
2343 } catch (RemoteException e) {
2344 Log.w(LOG_TAG, "gba set-service " + subId + " "
2345 + packageName + ", error" + e.getMessage());
2346 getErrPrintWriter().println("Exception: " + e.getMessage());
2347 return -1;
2348 }
2349 return 0;
2350 }
2351
2352 private int handleGbaGetServiceCommand() {
2353 String result;
2354
2355 int subId = getSubId("gba get-service");
2356 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2357 return -1;
2358 }
2359
2360 try {
2361 result = mInterface.getBoundGbaService(subId);
2362 } catch (RemoteException e) {
2363 return -1;
2364 }
2365 if (VDBG) {
2366 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2367 }
2368 getOutPrintWriter().println(result);
2369 return 0;
2370 }
2371
2372 private int handleGbaSetReleaseCommand() {
2373 //the release time value could be -1
2374 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2375 : SubscriptionManager.getDefaultSubscriptionId();
2376 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2377 return -1;
2378 }
2379
2380 String intervalStr = getNextArg();
2381 if (intervalStr == null) {
2382 return -1;
2383 }
2384
2385 try {
2386 int interval = Integer.parseInt(intervalStr);
2387 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2388 if (VDBG) {
2389 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2390 + intervalStr + ", result=" + result);
2391 }
2392 getOutPrintWriter().println(result);
2393 } catch (NumberFormatException | RemoteException e) {
2394 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2395 + intervalStr + ", error" + e.getMessage());
2396 getErrPrintWriter().println("Exception: " + e.getMessage());
2397 return -1;
2398 }
2399 return 0;
2400 }
2401
2402 private int handleGbaGetReleaseCommand() {
2403 int subId = getSubId("gba get-release");
2404 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2405 return -1;
2406 }
2407
2408 int result = 0;
2409 try {
2410 result = mInterface.getGbaReleaseTime(subId);
2411 } catch (RemoteException e) {
2412 return -1;
2413 }
2414 if (VDBG) {
2415 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2416 }
2417 getOutPrintWriter().println(result);
2418 return 0;
2419 }
Hui Wang761a6682020-10-31 05:12:53 +00002420
2421 private int handleSingleRegistrationConfigCommand() {
2422 String arg = getNextArg();
2423 if (arg == null) {
2424 onHelpSrc();
2425 return 0;
2426 }
2427
2428 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002429 case SRC_SET_TEST_ENABLED: {
2430 return handleSrcSetTestEnabledCommand();
2431 }
2432 case SRC_GET_TEST_ENABLED: {
2433 return handleSrcGetTestEnabledCommand();
2434 }
Hui Wang761a6682020-10-31 05:12:53 +00002435 case SRC_SET_DEVICE_ENABLED: {
2436 return handleSrcSetDeviceEnabledCommand();
2437 }
2438 case SRC_GET_DEVICE_ENABLED: {
2439 return handleSrcGetDeviceEnabledCommand();
2440 }
2441 case SRC_SET_CARRIER_ENABLED: {
2442 return handleSrcSetCarrierEnabledCommand();
2443 }
2444 case SRC_GET_CARRIER_ENABLED: {
2445 return handleSrcGetCarrierEnabledCommand();
2446 }
Hui Wangb647abe2021-02-26 09:33:38 -08002447 case SRC_SET_FEATURE_ENABLED: {
2448 return handleSrcSetFeatureValidationCommand();
2449 }
2450 case SRC_GET_FEATURE_ENABLED: {
2451 return handleSrcGetFeatureValidationCommand();
2452 }
Hui Wang761a6682020-10-31 05:12:53 +00002453 }
2454
2455 return -1;
2456 }
2457
James.cf Linbcdf8b32021-01-14 16:44:13 +08002458 private int handleRcsUceCommand() {
2459 String arg = getNextArg();
2460 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002461 onHelpUce();
2462 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002463 }
2464
2465 switch (arg) {
2466 case UCE_REMOVE_EAB_CONTACT:
2467 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002468 case UCE_GET_EAB_CONTACT:
2469 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002470 case UCE_GET_EAB_CAPABILITY:
2471 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002472 case UCE_GET_DEVICE_ENABLED:
2473 return handleUceGetDeviceEnabledCommand();
2474 case UCE_SET_DEVICE_ENABLED:
2475 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002476 case UCE_OVERRIDE_PUBLISH_CAPS:
2477 return handleUceOverridePublishCaps();
2478 case UCE_GET_LAST_PIDF_XML:
2479 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002480 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2481 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002482 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2483 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002484 }
2485 return -1;
2486 }
2487
2488 private int handleRemovingEabContactCommand() {
2489 int subId = getSubId("uce remove-eab-contact");
2490 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2491 return -1;
2492 }
2493
2494 String phoneNumber = getNextArgRequired();
2495 if (TextUtils.isEmpty(phoneNumber)) {
2496 return -1;
2497 }
2498 int result = 0;
2499 try {
2500 result = mInterface.removeContactFromEab(subId, phoneNumber);
2501 } catch (RemoteException e) {
2502 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2503 getErrPrintWriter().println("Exception: " + e.getMessage());
2504 return -1;
2505 }
2506
2507 if (VDBG) {
2508 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2509 }
calvinpan293ea1b2021-02-04 17:52:13 +08002510 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002511 }
2512
calvinpane4a8a1d2021-01-25 13:51:18 +08002513 private int handleGettingEabContactCommand() {
2514 String phoneNumber = getNextArgRequired();
2515 if (TextUtils.isEmpty(phoneNumber)) {
2516 return -1;
2517 }
2518 String result = "";
2519 try {
2520 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002521 } catch (RemoteException e) {
2522 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2523 getErrPrintWriter().println("Exception: " + e.getMessage());
2524 return -1;
2525 }
2526
2527 if (VDBG) {
2528 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2529 }
calvinpan293ea1b2021-02-04 17:52:13 +08002530 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002531 return 0;
2532 }
2533
Calvin Pana1434322021-07-01 19:27:01 +08002534 private int handleGettingEabCapabilityCommand() {
2535 String phoneNumber = getNextArgRequired();
2536 if (TextUtils.isEmpty(phoneNumber)) {
2537 return -1;
2538 }
2539 String result = "";
2540 try {
2541 result = mInterface.getCapabilityFromEab(phoneNumber);
2542 } catch (RemoteException e) {
2543 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2544 getErrPrintWriter().println("Exception: " + e.getMessage());
2545 return -1;
2546 }
2547
2548 if (VDBG) {
2549 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2550 }
2551 getOutPrintWriter().println(result);
2552 return 0;
2553 }
2554
James.cf Lin4b784aa2021-01-31 03:25:15 +08002555 private int handleUceGetDeviceEnabledCommand() {
2556 boolean result = false;
2557 try {
2558 result = mInterface.getDeviceUceEnabled();
2559 } catch (RemoteException e) {
2560 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2561 return -1;
2562 }
2563 if (VDBG) {
2564 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2565 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002566 getOutPrintWriter().println(result);
2567 return 0;
2568 }
2569
James.cf Lin4b784aa2021-01-31 03:25:15 +08002570 private int handleUceSetDeviceEnabledCommand() {
2571 String enabledStr = getNextArg();
2572 if (TextUtils.isEmpty(enabledStr)) {
2573 return -1;
2574 }
2575
2576 try {
2577 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2578 mInterface.setDeviceUceEnabled(isEnabled);
2579 if (VDBG) {
2580 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2581 }
2582 } catch (NumberFormatException | RemoteException e) {
2583 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2584 getErrPrintWriter().println("Exception: " + e.getMessage());
2585 return -1;
2586 }
2587 return 0;
2588 }
2589
James.cf Line8713a42021-04-29 16:04:26 +08002590 private int handleUceRemoveRequestDisallowedStatus() {
2591 int subId = getSubId("uce remove-request-disallowed-status");
2592 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2593 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2594 return -1;
2595 }
2596 boolean result;
2597 try {
2598 result = mInterface.removeUceRequestDisallowedStatus(subId);
2599 } catch (RemoteException e) {
2600 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2601 return -1;
2602 }
2603 if (VDBG) {
2604 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2605 }
2606 getOutPrintWriter().println(result);
2607 return 0;
2608 }
2609
James.cf Lin0fc71b02021-05-25 01:37:38 +08002610 private int handleUceSetCapRequestTimeout() {
2611 int subId = getSubId("uce set-capabilities-request-timeout");
2612 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2613 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2614 return -1;
2615 }
2616 long timeoutAfterMs = Long.valueOf(getNextArg());
2617 boolean result;
2618 try {
2619 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2620 } catch (RemoteException e) {
2621 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2622 return -1;
2623 }
2624 if (VDBG) {
2625 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2626 }
2627 getOutPrintWriter().println(result);
2628 return 0;
2629 }
2630
Hui Wangbaaee6a2021-02-19 20:45:36 -08002631 private int handleSrcSetTestEnabledCommand() {
2632 String enabledStr = getNextArg();
2633 if (enabledStr == null) {
2634 return -1;
2635 }
2636
2637 try {
2638 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2639 if (VDBG) {
2640 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2641 }
2642 getOutPrintWriter().println("Done");
2643 } catch (NumberFormatException | RemoteException e) {
2644 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2645 getErrPrintWriter().println("Exception: " + e.getMessage());
2646 return -1;
2647 }
2648 return 0;
2649 }
2650
2651 private int handleSrcGetTestEnabledCommand() {
2652 boolean result = false;
2653 try {
2654 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2655 } catch (RemoteException e) {
2656 return -1;
2657 }
2658 if (VDBG) {
2659 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2660 }
2661 getOutPrintWriter().println(result);
2662 return 0;
2663 }
2664
Brad Ebinger14d467f2021-02-12 06:18:28 +00002665 private int handleUceOverridePublishCaps() {
2666 int subId = getSubId("uce override-published-caps");
2667 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2668 return -1;
2669 }
2670 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2671 String operation = getNextArgRequired();
2672 String caps = getNextArg();
2673 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2674 && !"list".equals(operation)) {
2675 getErrPrintWriter().println("Invalid operation: " + operation);
2676 return -1;
2677 }
2678
2679 // add/remove requires capabilities to be specified.
2680 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2681 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2682 + "specified");
2683 return -1;
2684 }
2685
2686 ArraySet<String> capSet = new ArraySet<>();
2687 if (!TextUtils.isEmpty(caps)) {
2688 String[] capArray = caps.split(":");
2689 for (String cap : capArray) {
2690 // Allow unknown tags to be passed in as well.
2691 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2692 }
2693 }
2694
2695 RcsContactUceCapability result = null;
2696 try {
2697 switch (operation) {
2698 case "add":
2699 result = mInterface.addUceRegistrationOverrideShell(subId,
2700 new ArrayList<>(capSet));
2701 break;
2702 case "remove":
2703 result = mInterface.removeUceRegistrationOverrideShell(subId,
2704 new ArrayList<>(capSet));
2705 break;
2706 case "clear":
2707 result = mInterface.clearUceRegistrationOverrideShell(subId);
2708 break;
2709 case "list":
2710 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2711 break;
2712 }
2713 } catch (RemoteException e) {
2714 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2715 getErrPrintWriter().println("Exception: " + e.getMessage());
2716 return -1;
2717 } catch (ServiceSpecificException sse) {
2718 // Reconstruct ImsException
2719 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2720 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2721 getErrPrintWriter().println("Exception: " + imsException);
2722 return -1;
2723 }
2724 if (result == null) {
2725 getErrPrintWriter().println("Service not available");
2726 return -1;
2727 }
2728 getOutPrintWriter().println(result);
2729 return 0;
2730 }
2731
2732 private int handleUceGetPidfXml() {
2733 int subId = getSubId("uce get-last-publish-pidf");
2734 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2735 return -1;
2736 }
2737
2738 String result;
2739 try {
2740 result = mInterface.getLastUcePidfXmlShell(subId);
2741 } catch (RemoteException e) {
2742 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2743 getErrPrintWriter().println("Exception: " + e.getMessage());
2744 return -1;
2745 } catch (ServiceSpecificException sse) {
2746 // Reconstruct ImsException
2747 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2748 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2749 getErrPrintWriter().println("Exception: " + imsException);
2750 return -1;
2751 }
2752 if (result == null) {
2753 getErrPrintWriter().println("Service not available");
2754 return -1;
2755 }
2756 getOutPrintWriter().println(result);
2757 return 0;
2758 }
2759
Hui Wang761a6682020-10-31 05:12:53 +00002760 private int handleSrcSetDeviceEnabledCommand() {
2761 String enabledStr = getNextArg();
2762 if (enabledStr == null) {
2763 return -1;
2764 }
2765
2766 try {
2767 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2768 if (VDBG) {
2769 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2770 }
2771 getOutPrintWriter().println("Done");
2772 } catch (NumberFormatException | RemoteException e) {
2773 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2774 getErrPrintWriter().println("Exception: " + e.getMessage());
2775 return -1;
2776 }
2777 return 0;
2778 }
2779
2780 private int handleSrcGetDeviceEnabledCommand() {
2781 boolean result = false;
2782 try {
2783 result = mInterface.getDeviceSingleRegistrationEnabled();
2784 } catch (RemoteException e) {
2785 return -1;
2786 }
2787 if (VDBG) {
2788 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2789 }
2790 getOutPrintWriter().println(result);
2791 return 0;
2792 }
2793
2794 private int handleSrcSetCarrierEnabledCommand() {
2795 //the release time value could be -1
2796 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2797 : SubscriptionManager.getDefaultSubscriptionId();
2798 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2799 return -1;
2800 }
2801
2802 String enabledStr = getNextArg();
2803 if (enabledStr == null) {
2804 return -1;
2805 }
2806
2807 try {
2808 boolean result =
2809 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2810 if (VDBG) {
2811 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2812 + enabledStr + ", result=" + result);
2813 }
2814 getOutPrintWriter().println(result);
2815 } catch (NumberFormatException | RemoteException e) {
2816 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2817 + enabledStr + ", error" + e.getMessage());
2818 getErrPrintWriter().println("Exception: " + e.getMessage());
2819 return -1;
2820 }
2821 return 0;
2822 }
2823
2824 private int handleSrcGetCarrierEnabledCommand() {
2825 int subId = getSubId("src get-carrier-enabled");
2826 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2827 return -1;
2828 }
2829
2830 boolean result = false;
2831 try {
2832 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2833 } catch (RemoteException e) {
2834 return -1;
2835 }
2836 if (VDBG) {
2837 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2838 }
2839 getOutPrintWriter().println(result);
2840 return 0;
2841 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002842
Hui Wangb647abe2021-02-26 09:33:38 -08002843 private int handleSrcSetFeatureValidationCommand() {
2844 //the release time value could be -1
2845 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2846 : SubscriptionManager.getDefaultSubscriptionId();
2847 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2848 return -1;
2849 }
2850
2851 String enabledStr = getNextArg();
2852 if (enabledStr == null) {
2853 return -1;
2854 }
2855
2856 try {
2857 boolean result =
2858 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2859 if (VDBG) {
2860 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2861 + enabledStr + ", result=" + result);
2862 }
2863 getOutPrintWriter().println(result);
2864 } catch (NumberFormatException | RemoteException e) {
2865 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2866 + enabledStr + ", error" + e.getMessage());
2867 getErrPrintWriter().println("Exception: " + e.getMessage());
2868 return -1;
2869 }
2870 return 0;
2871 }
2872
2873 private int handleSrcGetFeatureValidationCommand() {
2874 int subId = getSubId("src get-feature-validation");
2875 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2876 return -1;
2877 }
2878
2879 Boolean result = false;
2880 try {
2881 result = mInterface.getImsFeatureValidationOverride(subId);
2882 } catch (RemoteException e) {
2883 return -1;
2884 }
2885 if (VDBG) {
2886 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2887 }
2888 getOutPrintWriter().println(result);
2889 return 0;
2890 }
2891
2892
Hall Liuaa4211e2021-01-20 15:43:39 -08002893 private void onHelpCallComposer() {
2894 PrintWriter pw = getOutPrintWriter();
2895 pw.println("Call composer commands");
2896 pw.println(" callcomposer test-mode enable|disable|query");
2897 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2898 pw.println(" upload/download from carrier servers is disabled, and operations are");
2899 pw.println(" performed using emulated local files instead.");
2900 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2901 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2902 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002903 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2904 pw.println(" Enables or disables the user setting for call composer, as set by");
2905 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002906 }
2907
2908 private int handleCallComposerCommand() {
2909 String arg = getNextArg();
2910 if (arg == null) {
2911 onHelpCallComposer();
2912 return 0;
2913 }
2914
2915 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2916 "MODIFY_PHONE_STATE required for call composer shell cmds");
2917 switch (arg) {
2918 case CALL_COMPOSER_TEST_MODE: {
2919 String enabledStr = getNextArg();
2920 if (ENABLE.equals(enabledStr)) {
2921 CallComposerPictureManager.sTestMode = true;
2922 } else if (DISABLE.equals(enabledStr)) {
2923 CallComposerPictureManager.sTestMode = false;
2924 } else if (QUERY.equals(enabledStr)) {
2925 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2926 } else {
2927 onHelpCallComposer();
2928 return 1;
2929 }
2930 break;
2931 }
2932 case CALL_COMPOSER_SIMULATE_CALL: {
2933 int subscriptionId = Integer.valueOf(getNextArg());
2934 String uuidString = getNextArg();
2935 UUID uuid = UUID.fromString(uuidString);
2936 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2937 Binder.withCleanCallingIdentity(() -> {
2938 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2939 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2940 });
2941 try {
2942 Uri uri = storageUriFuture.get();
2943 getOutPrintWriter().println(String.valueOf(uri));
2944 } catch (Exception e) {
2945 throw new RuntimeException(e);
2946 }
2947 break;
2948 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002949 case CALL_COMPOSER_USER_SETTING: {
2950 try {
2951 int subscriptionId = Integer.valueOf(getNextArg());
2952 String enabledStr = getNextArg();
2953 if (ENABLE.equals(enabledStr)) {
2954 mInterface.setCallComposerStatus(subscriptionId,
2955 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2956 } else if (DISABLE.equals(enabledStr)) {
2957 mInterface.setCallComposerStatus(subscriptionId,
2958 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2959 } else if (QUERY.equals(enabledStr)) {
2960 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2961 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2962 } else {
2963 onHelpCallComposer();
2964 return 1;
2965 }
2966 } catch (RemoteException e) {
2967 e.printStackTrace(getOutPrintWriter());
2968 return 1;
2969 }
2970 break;
2971 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002972 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002973 return 0;
2974 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002975
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002976 private int handleHasCarrierPrivilegesCommand() {
2977 String packageName = getNextArgRequired();
2978
2979 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002980 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002981 try {
2982 hasCarrierPrivileges =
2983 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2984 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2985 } catch (RemoteException e) {
2986 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2987 getErrPrintWriter().println("Exception: " + e.getMessage());
2988 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002989 } finally {
2990 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002991 }
2992
2993 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002994 return 0;
2995 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002996
2997 private int handleAllowedNetworkTypesCommand(String command) {
2998 if (!checkShellUid()) {
2999 return -1;
3000 }
3001
3002 PrintWriter errPw = getErrPrintWriter();
3003 String tag = command + ": ";
3004 String opt;
3005 int subId = -1;
3006 Log.v(LOG_TAG, command + " start");
3007
3008 while ((opt = getNextOption()) != null) {
3009 if (opt.equals("-s")) {
3010 try {
3011 subId = slotStringToSubId(tag, getNextArgRequired());
3012 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3013 errPw.println(tag + "No valid subscription found.");
3014 return -1;
3015 }
3016 } catch (IllegalArgumentException e) {
3017 // Missing slot id
3018 errPw.println(tag + "SLOT_ID expected after -s.");
3019 return -1;
3020 }
3021 } else {
3022 errPw.println(tag + "Unknown option " + opt);
3023 return -1;
3024 }
3025 }
3026
3027 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
3028 return handleGetAllowedNetworkTypesCommand(subId);
3029 }
3030 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
3031 return handleSetAllowedNetworkTypesCommand(subId);
3032 }
3033 return -1;
3034 }
3035
3036 private int handleGetAllowedNetworkTypesCommand(int subId) {
3037 PrintWriter errPw = getErrPrintWriter();
3038
3039 long result = -1;
3040 try {
3041 if (mInterface != null) {
3042 result = mInterface.getAllowedNetworkTypesForReason(subId,
3043 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
3044 } else {
3045 throw new IllegalStateException("telephony service is null.");
3046 }
3047 } catch (RemoteException e) {
3048 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
3049 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
3050 return -1;
3051 }
3052
3053 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
3054 return 0;
3055 }
3056
3057 private int handleSetAllowedNetworkTypesCommand(int subId) {
3058 PrintWriter errPw = getErrPrintWriter();
3059
3060 String bitmaskString = getNextArg();
3061 if (TextUtils.isEmpty(bitmaskString)) {
3062 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
3063 return -1;
3064 }
3065 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
3066 if (allowedNetworkTypes < 0) {
3067 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
3068 return -1;
3069 }
3070 boolean result = false;
3071 try {
3072 if (mInterface != null) {
3073 result = mInterface.setAllowedNetworkTypesForReason(subId,
3074 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
3075 } else {
3076 throw new IllegalStateException("telephony service is null.");
3077 }
3078 } catch (RemoteException e) {
3079 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
3080 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
3081 return -1;
3082 }
3083
3084 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
3085 if (result) {
3086 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3087 }
3088 getOutPrintWriter().println(resultMessage);
3089 return 0;
3090 }
3091
3092 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3093 if (TextUtils.isEmpty(bitmaskString)) {
3094 return -1;
3095 }
3096 if (VDBG) {
3097 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3098 + ", length: " + bitmaskString.length());
3099 }
3100 try {
3101 return Long.parseLong(bitmaskString, 2);
3102 } catch (NumberFormatException e) {
3103 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3104 return -1;
3105 }
3106 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003107
jimsun3b9ccac2021-10-26 15:01:23 +08003108 private int handleRadioSetModemServiceCommand() {
3109 PrintWriter errPw = getErrPrintWriter();
3110 String serviceName = null;
3111
3112 String opt;
3113 while ((opt = getNextOption()) != null) {
3114 switch (opt) {
3115 case "-s": {
3116 serviceName = getNextArgRequired();
3117 break;
3118 }
3119 }
3120 }
3121
3122 try {
3123 boolean result = mInterface.setModemService(serviceName);
3124 if (VDBG) {
3125 Log.v(LOG_TAG,
3126 "RadioSetModemService " + serviceName + ", result = " + result);
3127 }
3128 getOutPrintWriter().println(result);
3129 } catch (RemoteException e) {
3130 Log.w(LOG_TAG,
3131 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3132 errPw.println("Exception: " + e.getMessage());
3133 return -1;
3134 }
3135 return 0;
3136 }
3137
3138 private int handleRadioGetModemServiceCommand() {
3139 PrintWriter errPw = getErrPrintWriter();
3140 String result;
3141
3142 try {
3143 result = mInterface.getModemService();
3144 getOutPrintWriter().println(result);
3145 } catch (RemoteException e) {
3146 errPw.println("Exception: " + e.getMessage());
3147 return -1;
3148 }
3149 if (VDBG) {
3150 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3151 }
3152 return 0;
3153 }
3154
3155 private int handleRadioCommand() {
3156 String arg = getNextArg();
3157 if (arg == null) {
3158 onHelpRadio();
3159 return 0;
3160 }
3161
3162 switch (arg) {
3163 case RADIO_SET_MODEM_SERVICE:
3164 return handleRadioSetModemServiceCommand();
3165
3166 case RADIO_GET_MODEM_SERVICE:
3167 return handleRadioGetModemServiceCommand();
3168 }
3169
3170 return -1;
3171 }
arunvoddud7401012022-12-15 16:08:12 +00003172
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003173 private int handleSetSatelliteServicePackageNameCommand() {
3174 PrintWriter errPw = getErrPrintWriter();
3175 String serviceName = null;
3176
3177 String opt;
3178 while ((opt = getNextOption()) != null) {
3179 switch (opt) {
3180 case "-s": {
3181 serviceName = getNextArgRequired();
3182 break;
3183 }
3184 }
3185 }
3186 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3187 + serviceName);
3188
3189 try {
3190 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3191 if (VDBG) {
3192 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3193 + ", result = " + result);
3194 }
3195 getOutPrintWriter().println(result);
3196 } catch (RemoteException e) {
3197 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3198 + ", error = " + e.getMessage());
3199 errPw.println("Exception: " + e.getMessage());
3200 return -1;
3201 }
3202 return 0;
3203 }
3204
Thomas Nguyen1854a5a2023-04-04 09:31:47 -07003205 private int handleSetSatelliteGatewayServicePackageNameCommand() {
3206 PrintWriter errPw = getErrPrintWriter();
3207 String serviceName = null;
3208
3209 String opt;
3210 while ((opt = getNextOption()) != null) {
3211 switch (opt) {
3212 case "-s": {
3213 serviceName = getNextArgRequired();
3214 break;
3215 }
3216 }
3217 }
3218 Log.d(LOG_TAG, "handleSetSatelliteGatewayServicePackageNameCommand: serviceName="
3219 + serviceName);
3220
3221 try {
3222 boolean result = mInterface.setSatelliteGatewayServicePackageName(serviceName);
3223 if (VDBG) {
3224 Log.v(LOG_TAG, "setSatelliteGatewayServicePackageName " + serviceName
3225 + ", result = " + result);
3226 }
3227 getOutPrintWriter().println(result);
3228 } catch (RemoteException e) {
3229 Log.w(LOG_TAG, "setSatelliteGatewayServicePackageName: " + serviceName
3230 + ", error = " + e.getMessage());
3231 errPw.println("Exception: " + e.getMessage());
3232 return -1;
3233 }
3234 return 0;
3235 }
3236
Thomas Nguyen87dce732023-04-20 18:27:16 -07003237 private int handleSetSatellitePointingUiClassNameCommand() {
3238 PrintWriter errPw = getErrPrintWriter();
3239 String packageName = null;
3240 String className = null;
3241
3242 String opt;
3243 while ((opt = getNextOption()) != null) {
3244 switch (opt) {
3245 case "-p": {
3246 packageName = getNextArgRequired();
3247 break;
3248 }
3249 case "-c": {
3250 className = getNextArgRequired();
3251 break;
3252 }
3253 }
3254 }
3255 Log.d(LOG_TAG, "handleSetSatellitePointingUiClassNameCommand: packageName="
3256 + packageName + ", className=" + className);
3257
3258 try {
3259 boolean result = mInterface.setSatellitePointingUiClassName(packageName, className);
3260 if (VDBG) {
3261 Log.v(LOG_TAG, "setSatellitePointingUiClassName result =" + result);
3262 }
3263 getOutPrintWriter().println(result);
3264 } catch (RemoteException e) {
3265 Log.e(LOG_TAG, "setSatellitePointingUiClassName: " + packageName
3266 + ", error = " + e.getMessage());
3267 errPw.println("Exception: " + e.getMessage());
3268 return -1;
3269 }
3270 return 0;
3271 }
3272
Thomas Nguyen11a051f2023-10-25 10:14:55 -07003273 private int handleSetEmergencyCallToSatelliteHandoverType() {
3274 PrintWriter errPw = getErrPrintWriter();
3275 int handoverType = -1;
3276 int delaySeconds = 0;
3277
3278 String opt;
3279 while ((opt = getNextOption()) != null) {
3280 switch (opt) {
3281 case "-t": {
3282 try {
3283 handoverType = Integer.parseInt(getNextArgRequired());
3284 } catch (NumberFormatException e) {
3285 errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
3286 + " for handoverType");
3287 return -1;
3288 }
3289 break;
3290 }
3291 case "-d": {
3292 try {
3293 delaySeconds = Integer.parseInt(getNextArgRequired());
3294 } catch (NumberFormatException e) {
3295 errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
3296 + " for delaySeconds");
3297 return -1;
3298 }
3299 break;
3300 }
3301 }
3302 }
3303 Log.d(LOG_TAG, "handleSetEmergencyCallToSatelliteHandoverType: handoverType="
3304 + handoverType + ", delaySeconds=" + delaySeconds);
3305
3306 try {
3307 boolean result =
3308 mInterface.setEmergencyCallToSatelliteHandoverType(handoverType, delaySeconds);
3309 if (VDBG) {
3310 Log.v(LOG_TAG, "setEmergencyCallToSatelliteHandoverType result =" + result);
3311 }
3312 getOutPrintWriter().println(result);
3313 } catch (RemoteException e) {
3314 Log.e(LOG_TAG, "setEmergencyCallToSatelliteHandoverType: " + handoverType
3315 + ", error = " + e.getMessage());
3316 errPw.println("Exception: " + e.getMessage());
3317 return -1;
3318 }
3319 return 0;
3320 }
3321
Thomas Nguyenf9a533c2023-04-06 20:48:41 -07003322 private int handleSetSatelliteListeningTimeoutDuration() {
3323 PrintWriter errPw = getErrPrintWriter();
3324 long timeoutMillis = 0;
3325
3326 String opt;
3327 while ((opt = getNextOption()) != null) {
3328 switch (opt) {
3329 case "-t": {
3330 timeoutMillis = Long.parseLong(getNextArgRequired());
3331 break;
3332 }
3333 }
3334 }
3335 Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
3336 + timeoutMillis);
3337
3338 try {
3339 boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
3340 if (VDBG) {
3341 Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
3342 + ", result = " + result);
3343 }
3344 getOutPrintWriter().println(result);
3345 } catch (RemoteException e) {
3346 Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
3347 + ", error = " + e.getMessage());
3348 errPw.println("Exception: " + e.getMessage());
3349 return -1;
3350 }
3351 return 0;
3352 }
3353
Hakjun Choiae365972023-04-25 11:00:31 +00003354 private int handleSettSatelliteDeviceAlignedTimeoutDuration() {
3355 PrintWriter errPw = getErrPrintWriter();
3356 long timeoutMillis = 0;
3357
3358 String opt;
3359 while ((opt = getNextOption()) != null) {
3360 switch (opt) {
3361 case "-t": {
3362 timeoutMillis = Long.parseLong(getNextArgRequired());
3363 break;
3364 }
3365 }
3366 }
3367 Log.d(LOG_TAG, "handleSettSatelliteDeviceAlignedTimeoutDuration: timeoutMillis="
3368 + timeoutMillis);
3369
3370 try {
3371 boolean result = mInterface.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis);
3372 if (VDBG) {
3373 Log.v(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration " + timeoutMillis
3374 + ", result = " + result);
3375 }
3376 getOutPrintWriter().println(result);
3377 } catch (RemoteException e) {
3378 Log.w(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration: " + timeoutMillis
3379 + ", error = " + e.getMessage());
3380 errPw.println("Exception: " + e.getMessage());
3381 return -1;
3382 }
3383 return 0;
3384 }
3385
Hakjun Choibc6ce992023-11-07 16:04:33 +00003386 private int handleSetShouldSendDatagramToModemInDemoMode() {
3387 PrintWriter errPw = getErrPrintWriter();
3388 String opt;
3389 boolean shouldSendToDemoMode;
3390
3391 if ((opt = getNextArg()) == null) {
3392 errPw.println(
3393 "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
3394 + " Invalid Argument");
3395 return -1;
3396 } else {
3397 switch (opt) {
3398 case "true": {
3399 shouldSendToDemoMode = true;
3400 break;
3401 }
3402 case "false": {
3403 shouldSendToDemoMode = false;
3404 break;
3405 }
3406 default:
3407 errPw.println(
3408 "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
3409 + " Invalid Argument");
3410 return -1;
3411 }
3412 }
3413
3414 Log.d(LOG_TAG,
3415 "handleSetShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode + ")");
3416
3417 try {
3418 boolean result = mInterface.setShouldSendDatagramToModemInDemoMode(
3419 shouldSendToDemoMode);
3420 if (VDBG) {
3421 Log.v(LOG_TAG, "handleSetShouldSendDatagramToModemInDemoMode returns: "
3422 + result);
3423 }
3424 getOutPrintWriter().println(false);
3425 } catch (RemoteException e) {
3426 Log.w(LOG_TAG, "setShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode
3427 + "), error = " + e.getMessage());
3428 errPw.println("Exception: " + e.getMessage());
3429 return -1;
3430 }
3431 return 0;
3432 }
3433
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -08003434 private int handleSetSatelliteAccessControlOverlayConfigs() {
3435 PrintWriter errPw = getErrPrintWriter();
3436 boolean reset = false;
3437 boolean isAllowed = false;
3438 String s2CellFile = null;
3439 long locationFreshDurationNanos = 0;
3440 List<String> satelliteCountryCodes = null;
3441
3442 String opt;
3443 while ((opt = getNextOption()) != null) {
3444 switch (opt) {
3445 case "-r": {
3446 reset = true;
3447 break;
3448 }
3449 case "-a": {
3450 isAllowed = true;
3451 break;
3452 }
3453 case "-f": {
3454 s2CellFile = getNextArgRequired();
3455 break;
3456 }
3457 case "-d": {
3458 locationFreshDurationNanos = Long.parseLong(getNextArgRequired());
3459 break;
3460 }
3461 case "-c": {
3462 String countryCodeStr = getNextArgRequired();
3463 satelliteCountryCodes = Arrays.asList(countryCodeStr.split(","));
3464 break;
3465 }
3466 }
3467 }
3468 Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: reset=" + reset
3469 + ", isAllowed=" + isAllowed + ", s2CellFile=" + s2CellFile
3470 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
3471 + ", satelliteCountryCodes=" + satelliteCountryCodes);
3472
3473 try {
3474 boolean result = mInterface.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
3475 s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
3476 if (VDBG) {
3477 Log.v(LOG_TAG, "setSatelliteAccessControlOverlayConfigs result =" + result);
3478 }
3479 getOutPrintWriter().println(result);
3480 } catch (RemoteException e) {
3481 Log.e(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: ex=" + e.getMessage());
3482 errPw.println("Exception: " + e.getMessage());
3483 return -1;
3484 }
3485 return 0;
3486 }
3487
3488 private int handleSetCountryCodes() {
3489 PrintWriter errPw = getErrPrintWriter();
3490 List<String> currentNetworkCountryCodes = new ArrayList<>();
3491 String locationCountryCode = null;
3492 long locationCountryCodeTimestampNanos = 0;
3493 Map<String, Long> cachedNetworkCountryCodes = new HashMap<>();
3494 boolean reset = false;
3495
3496 String opt;
3497 while ((opt = getNextOption()) != null) {
3498 switch (opt) {
3499 case "-r": {
3500 reset = true;
3501 break;
3502 }
3503 case "-n": {
3504 String countryCodeStr = getNextArgRequired();
3505 currentNetworkCountryCodes = Arrays.asList(countryCodeStr.split(","));
3506 break;
3507 }
3508 case "-c": {
3509 String cachedNetworkCountryCodeStr = getNextArgRequired();
3510 cachedNetworkCountryCodes = parseStringLongMap(cachedNetworkCountryCodeStr);
3511 break;
3512 }
3513 case "-l": {
3514 locationCountryCode = getNextArgRequired();
3515 break;
3516 }
3517 case "-t": {
3518 locationCountryCodeTimestampNanos = Long.parseLong(getNextArgRequired());
3519 break;
3520 }
3521 }
3522 }
3523 Log.d(LOG_TAG, "setCountryCodes: locationCountryCode="
3524 + locationCountryCode + ", locationCountryCodeTimestampNanos="
3525 + locationCountryCodeTimestampNanos + ", currentNetworkCountryCodes="
3526 + currentNetworkCountryCodes);
3527
3528 try {
3529 boolean result = mInterface.setCountryCodes(reset, currentNetworkCountryCodes,
3530 cachedNetworkCountryCodes, locationCountryCode,
3531 locationCountryCodeTimestampNanos);
3532 if (VDBG) {
3533 Log.v(LOG_TAG, "setCountryCodes result =" + result);
3534 }
3535 getOutPrintWriter().println(result);
3536 } catch (RemoteException e) {
3537 Log.e(LOG_TAG, "setCountryCodes: ex=" + e.getMessage());
3538 errPw.println("Exception: " + e.getMessage());
3539 return -1;
3540 }
3541 return 0;
3542 }
3543
Thomas Nguyen3d602742024-01-19 11:29:35 -08003544 private int handleSetOemEnabledSatelliteProvisionStatus() {
3545 PrintWriter errPw = getErrPrintWriter();
3546 boolean isProvisioned = false;
3547 boolean reset = true;
3548
3549 String opt;
3550 while ((opt = getNextOption()) != null) {
3551 switch (opt) {
3552 case "-p": {
3553 try {
3554 isProvisioned = Boolean.parseBoolean(getNextArgRequired());
3555 reset = false;
3556 } catch (Exception e) {
3557 errPw.println("setOemEnabledSatelliteProvisionStatus requires a boolean "
3558 + "after -p indicating provision status");
3559 return -1;
3560 }
3561 }
3562 }
3563 }
3564 Log.d(LOG_TAG, "setOemEnabledSatelliteProvisionStatus: reset=" + reset
3565 + ", isProvisioned=" + isProvisioned);
3566
3567 try {
3568 boolean result = mInterface.setOemEnabledSatelliteProvisionStatus(reset, isProvisioned);
3569 if (VDBG) {
3570 Log.v(LOG_TAG, "setOemEnabledSatelliteProvisionStatus result = " + result);
3571 }
3572 getOutPrintWriter().println(result);
3573 } catch (RemoteException e) {
3574 Log.w(LOG_TAG, "setOemEnabledSatelliteProvisionStatus: error = " + e.getMessage());
3575 errPw.println("Exception: " + e.getMessage());
3576 return -1;
3577 }
3578 return 0;
3579 }
3580
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -08003581 /**
3582 * Sample inputStr = "US,UK,CA;2,1,3"
3583 * Sample output: {[US,2], [UK,1], [CA,3]}
3584 */
3585 @NonNull private Map<String, Long> parseStringLongMap(@Nullable String inputStr) {
3586 Map<String, Long> result = new HashMap<>();
3587 if (!TextUtils.isEmpty(inputStr)) {
3588 String[] stringLongArr = inputStr.split(";");
3589 if (stringLongArr.length != 2) {
3590 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
3591 return result;
3592 }
3593
3594 String[] stringArr = stringLongArr[0].split(",");
3595 String[] longArr = stringLongArr[1].split(",");
3596 if (stringArr.length != longArr.length) {
3597 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
3598 return result;
3599 }
3600
3601 for (int i = 0; i < stringArr.length; i++) {
3602 try {
3603 result.put(stringArr[i], Long.parseLong(longArr[i]));
3604 } catch (Exception ex) {
3605 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr
3606 + ", ex=" + ex);
3607 return result;
3608 }
3609 }
3610 }
3611 return result;
3612 }
3613
arunvoddud7401012022-12-15 16:08:12 +00003614 private int handleCarrierRestrictionStatusCommand() {
3615 try {
3616 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3617 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3618 mInterface.getModemService()))) {
3619 Log.v(LOG_TAG,
3620 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3621 + " checkShellUid fails");
3622 return -1;
3623 }
3624 } catch (RemoteException ex) {
3625 ex.printStackTrace();
3626 }
3627 String callerInfo = getNextOption();
3628 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3629 if (TextUtils.isEmpty(callerInfo)) {
3630 // reset the Json content after testing
3631 allowListInfo.updateJsonForTest(null);
3632 return 0;
3633 }
3634 if (callerInfo.startsWith("--")) {
3635 callerInfo = callerInfo.replace("--", "");
3636 }
3637 String params[] = callerInfo.split(",");
3638 StringBuffer jsonStrBuffer = new StringBuffer();
3639 String tokens;
3640 for (int index = 0; index < params.length; index++) {
3641 tokens = convertToJsonString(index, params[index]);
3642 if (TextUtils.isEmpty(tokens)) {
3643 // received wrong format from CTS
3644 if (VDBG) {
3645 Log.v(LOG_TAG,
3646 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3647 }
3648 return -1;
3649 }
3650 jsonStrBuffer.append(tokens);
3651 }
3652 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3653 return result;
3654 }
3655
Benedict Wong66477622023-02-03 23:30:57 +00003656 // set-carrier-service-package-override
3657 private int setCarrierServicePackageOverride() {
3658 PrintWriter errPw = getErrPrintWriter();
3659 int subId = SubscriptionManager.getDefaultSubscriptionId();
3660
3661 String opt;
3662 while ((opt = getNextOption()) != null) {
3663 switch (opt) {
3664 case "-s":
3665 try {
3666 subId = Integer.parseInt(getNextArgRequired());
3667 } catch (NumberFormatException e) {
3668 errPw.println(
3669 "set-carrier-service-package-override requires an integer as a"
3670 + " subscription ID.");
3671 return -1;
3672 }
3673 break;
3674 }
3675 }
3676
3677 String packageName = getNextArg();
3678 if (packageName == null) {
3679 errPw.println("set-carrier-service-package-override requires a override package name.");
3680 return -1;
3681 }
3682
3683 try {
3684 mInterface.setCarrierServicePackageOverride(
3685 subId, packageName, mContext.getOpPackageName());
3686
3687 if (VDBG) {
3688 Log.v(
3689 LOG_TAG,
3690 "set-carrier-service-package-override -s " + subId + " " + packageName);
3691 }
3692 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3693 Log.w(
3694 LOG_TAG,
3695 "set-carrier-service-package-override -s "
3696 + subId
3697 + " "
3698 + packageName
3699 + ", error"
3700 + e.getMessage());
3701 errPw.println("Exception: " + e.getMessage());
3702 return -1;
3703 }
3704 return 0;
3705 }
3706
3707 // clear-carrier-service-package-override
3708 private int clearCarrierServicePackageOverride() {
3709 PrintWriter errPw = getErrPrintWriter();
Chalard Jean71706f42023-09-22 18:22:47 +09003710 int subId = SubscriptionManager.getDefaultSubscriptionId();
Benedict Wong66477622023-02-03 23:30:57 +00003711
3712 String opt;
3713 while ((opt = getNextOption()) != null) {
3714 switch (opt) {
3715 case "-s":
3716 try {
3717 subId = Integer.parseInt(getNextArgRequired());
3718 } catch (NumberFormatException e) {
3719 errPw.println(
3720 "clear-carrier-service-package-override requires an integer as a"
3721 + " subscription ID.");
3722 return -1;
3723 }
3724 break;
3725 }
3726 }
3727
3728 try {
3729 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3730
3731 if (VDBG) {
3732 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3733 }
3734 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3735 Log.w(
3736 LOG_TAG,
3737 "clear-carrier-service-package-override -s "
3738 + subId
3739 + ", error"
3740 + e.getMessage());
3741 errPw.println("Exception: " + e.getMessage());
3742 return -1;
3743 }
3744 return 0;
3745 }
arunvoddud7401012022-12-15 16:08:12 +00003746
3747 /**
3748 * Building the string that can be used to build the JsonObject which supports to stub the data
3749 * in CarrierAllowListInfo for CTS testing. sample format is like
3750 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3751 */
3752 private String convertToJsonString(int index, String param) {
3753
3754 String token[] = param.split(":");
3755 String jSonString;
3756 switch (index) {
3757 case 0:
3758 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3759 break;
3760 case 1:
3761 jSonString =
3762 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3763 break;
3764 case 2:
3765 jSonString =
3766 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3767 break;
3768 default:
3769 jSonString = null;
3770 }
3771 return jSonString;
3772 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003773}