blob: 80b7cf6411e063d917dfa4c52a3af4798a53aa60 [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";
Hakjun Choibc6ce992023-11-07 16:04:33 +0000200 private static final String SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE =
201 "set-should-send-datagram-to-modem-in-demo-mode";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800202
Grant Menke567d48f2022-08-18 20:19:10 +0000203 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
204 + "'*', '#' or '+') needs to be specified after -a in the command ";
205
206 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
207 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
208 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
209
SongFerngWang98dd5992021-05-13 17:50:00 +0800210 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
211 "get-allowed-network-types-for-users";
212 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
213 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000214 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000215 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700216 // Take advantage of existing methods that already contain permissions checks when possible.
217 private final ITelephony mInterface;
218
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100219 private SubscriptionManager mSubscriptionManager;
220 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700221 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700222 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100223
224 private enum CcType {
225 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000226 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100227 }
228
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100229 private class CcOptionParseResult {
230 public int mSubId;
231 public boolean mPersistent;
232 }
233
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100234 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
235 // keys by looking at the end of the string which usually tells the type.
236 // For instance: "xxxx_string", "xxxx_string_array", etc.
237 // The carrier config keys in this map does not follow this convention. It is therefore not
238 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700239 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
240 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
241 CcType.STRING),
242 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
243 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
244 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
245 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
246 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
247 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
248 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
249 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
250 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
251 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
252 CcType.STRING),
253 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
254 CcType.STRING_ARRAY),
255 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
256 CcType.STRING_ARRAY),
257 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
258 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
259 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
260 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
261 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
262 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
263 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
264 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100265
Brad Ebinger14d467f2021-02-12 06:18:28 +0000266 /**
267 * Map from a shorthand string to the feature tags required in registration required in order
268 * for the RCS feature to be considered "capable".
269 */
270 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
271 static {
272 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
273 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
274 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
275 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
276 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
277 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
278 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
279 FeatureTags.FEATURE_TAG_VIDEO)));
280 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
281 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
282 map.put("call_comp",
283 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
284 map.put("call_comp_mmtel",
285 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
286 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
287 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
288 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
289 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
290 // version
291 map.put("chatbot", new ArraySet<>(Arrays.asList(
292 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
293 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
294 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
295 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000296 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000297 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
298 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
299 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
300 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
301 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000302 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000303 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
304 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
305 }
306
307
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100308 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700309 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100310 mCarrierConfigManager =
311 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
312 mSubscriptionManager = (SubscriptionManager)
313 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700314 mTelephonyRegistryManager = (TelephonyRegistryManager)
315 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700316 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700317 }
318
319 @Override
320 public int onCommand(String cmd) {
321 if (cmd == null) {
322 return handleDefaultCommands(null);
323 }
324
325 switch (cmd) {
326 case IMS_SUBCOMMAND: {
327 return handleImsCommand();
328 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800329 case RCS_UCE_COMMAND:
330 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800331 case NUMBER_VERIFICATION_SUBCOMMAND:
332 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800333 case EMERGENCY_CALLBACK_MODE:
334 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800335 case EMERGENCY_NUMBER_TEST_MODE:
336 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100337 case CARRIER_CONFIG_SUBCOMMAND: {
338 return handleCcCommand();
339 }
Shuo Qianf5125122019-12-16 17:03:07 -0800340 case DATA_TEST_MODE:
341 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700342 case END_BLOCK_SUPPRESSION:
343 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000344 case EUICC_SUBCOMMAND:
345 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700346 case GBA_SUBCOMMAND:
347 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800348 case D2D_SUBCOMMAND:
349 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700350 case BARRING_SUBCOMMAND:
351 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000352 case SINGLE_REGISTATION_CONFIG:
353 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000354 case RESTART_MODEM:
355 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800356 case CALL_COMPOSER_SUBCOMMAND:
357 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000358 case UNATTENDED_REBOOT:
359 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800360 case HAS_CARRIER_PRIVILEGES_COMMAND:
361 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800362 case THERMAL_MITIGATION_COMMAND:
363 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700364 case DISABLE_PHYSICAL_SUBSCRIPTION:
365 return handleEnablePhysicalSubscription(false);
366 case ENABLE_PHYSICAL_SUBSCRIPTION:
367 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800368 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
369 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
370 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000371 case GET_IMEI:
372 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000373 case GET_SIM_SLOTS_MAPPING:
374 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800375 case RADIO_SUBCOMMAND:
376 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000377 case CARRIER_RESTRICTION_STATUS_TEST:
378 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000379 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
380 return setCarrierServicePackageOverride();
381 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
382 return clearCarrierServicePackageOverride();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700383 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
384 return handleSetSatelliteServicePackageNameCommand();
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700385 case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
386 return handleSetSatelliteGatewayServicePackageNameCommand();
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700387 case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
388 return handleSetSatelliteListeningTimeoutDuration();
Thomas Nguyen87dce732023-04-20 18:27:16 -0700389 case SET_SATELLITE_POINTING_UI_CLASS_NAME:
390 return handleSetSatellitePointingUiClassNameCommand();
Hakjun Choiae365972023-04-25 11:00:31 +0000391 case SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION:
392 return handleSettSatelliteDeviceAlignedTimeoutDuration();
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700393 case SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE:
394 return handleSetEmergencyCallToSatelliteHandoverType();
Hakjun Choibc6ce992023-11-07 16:04:33 +0000395 case SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE:
396 return handleSetShouldSendDatagramToModemInDemoMode();
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800397 case SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS:
398 return handleSetSatelliteAccessControlOverlayConfigs();
399 case SET_COUNTRY_CODES:
400 return handleSetCountryCodes();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700401 default: {
402 return handleDefaultCommands(cmd);
403 }
404 }
405 }
406
407 @Override
408 public void onHelp() {
409 PrintWriter pw = getOutPrintWriter();
410 pw.println("Telephony Commands:");
411 pw.println(" help");
412 pw.println(" Print this help text.");
413 pw.println(" ims");
414 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800415 pw.println(" uce");
416 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800417 pw.println(" emergency-number-test-mode");
418 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700419 pw.println(" end-block-suppression");
420 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800421 pw.println(" data");
422 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100423 pw.println(" cc");
424 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700425 pw.println(" gba");
426 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000427 pw.println(" src");
428 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000429 pw.println(" restart-modem");
430 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000431 pw.println(" unattended-reboot");
432 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800433 pw.println(" has-carrier-privileges [package]");
434 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800435 pw.println(" get-allowed-network-types-for-users");
436 pw.println(" Get the Allowed Network Types.");
437 pw.println(" set-allowed-network-types-for-users");
438 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800439 pw.println(" radio");
440 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700441 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800442 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800443 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700444 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800445 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100446 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700447 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000448 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800449 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700450 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800451 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800452 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000453 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700454 onHelpSatellite();
Tyler Gunn92479152021-01-20 16:30:10 -0800455 }
456
457 private void onHelpD2D() {
458 PrintWriter pw = getOutPrintWriter();
459 pw.println("D2D Comms Commands:");
460 pw.println(" d2d send TYPE VALUE");
461 pw.println(" Sends a D2D message of specified type and value.");
462 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
463 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
464 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
465 MESSAGE_CALL_AUDIO_CODEC));
466 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
467 + Communicator.messageToString(
468 MESSAGE_DEVICE_BATTERY_STATE));
469 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
470 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800471 pw.println(" d2d transport TYPE");
472 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
473 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700474 pw.println(" d2d set-device-support true/default");
475 pw.println(" true - forces device support to be enabled for D2D.");
476 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
477 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700478 }
479
Nazanin014f41e2021-05-06 17:26:31 -0700480 private void onHelpBarring() {
481 PrintWriter pw = getOutPrintWriter();
482 pw.println("Barring Commands:");
483 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
484 + " -t CONDITIONAL_BARRING_TIME_SECS");
485 pw.println(" Notifies of a barring info change for the specified slot id.");
486 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
487 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
488 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
489 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
490 }
491
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700492 private void onHelpIms() {
493 PrintWriter pw = getOutPrintWriter();
494 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800495 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700496 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
497 pw.println(" ImsService. Options are:");
498 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
499 pw.println(" is specified, it will choose the default voice SIM slot.");
500 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
501 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800502 pw.println(" -f: Set the feature that this override if for, if no option is");
503 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700504 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
505 pw.println(" Gets the package name of the currently defined ImsService.");
506 pw.println(" Options are:");
507 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
508 pw.println(" is specified, it will choose the default voice SIM slot.");
509 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000510 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800511 pw.println(" -f: The feature type that the query will be requested for. If none is");
512 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800513 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
514 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
515 pw.println(" configuration overrides. Options are:");
516 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
517 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700518 pw.println(" ims enable [-s SLOT_ID]");
519 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
520 pw.println(" if none is specified.");
521 pw.println(" ims disable [-s SLOT_ID]");
522 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
523 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700524 pw.println(" ims conference-event-package [enable/disable]");
525 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700526 }
527
James.cf Linbcdf8b32021-01-14 16:44:13 +0800528 private void onHelpUce() {
529 PrintWriter pw = getOutPrintWriter();
530 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800531 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
532 pw.println(" Get the EAB contacts from the EAB database.");
533 pw.println(" Options are:");
534 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
535 pw.println(" Expected output format :");
536 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800537 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
538 pw.println(" Remove the EAB contacts from the EAB database.");
539 pw.println(" Options are:");
540 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
541 pw.println(" is specified, it will choose the default voice SIM slot.");
542 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800543 pw.println(" uce get-device-enabled");
544 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
545 pw.println(" uce set-device-enabled true|false");
546 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
547 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000548 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
549 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
550 pw.println(" Options are:");
551 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
552 pw.println(" is specified, it will choose the default voice SIM slot.");
553 pw.println(" add [CAPABILITY]: add a new capability");
554 pw.println(" remove [CAPABILITY]: remove a capability");
555 pw.println(" clear: clear all capability overrides");
556 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
557 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
558 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
559 pw.println(" chatbot_sa, chatbot_role] as well as full length");
560 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
561 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
562 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
563 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800564 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
565 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800566 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
567 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800568 }
569
Hall Liud892bec2018-11-30 14:51:45 -0800570 private void onHelpNumberVerification() {
571 PrintWriter pw = getOutPrintWriter();
572 pw.println("Number verification commands");
573 pw.println(" numverify override-package PACKAGE_NAME;");
574 pw.println(" Set the authorized package for number verification.");
575 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800576 pw.println(" numverify fake-call NUMBER;");
577 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
578 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800579 }
580
Jack Nudelman644b91a2021-03-12 14:09:48 -0800581 private void onHelpThermalMitigation() {
582 PrintWriter pw = getOutPrintWriter();
583 pw.println("Thermal mitigation commands");
584 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
585 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
586 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
587 pw.println(" Remove the package from one of the authorized packages for thermal "
588 + "mitigation.");
589 }
590
Jordan Liu0ccee222021-04-27 11:55:13 -0700591 private void onHelpDisableOrEnablePhysicalSubscription() {
592 PrintWriter pw = getOutPrintWriter();
593 pw.println("Disable or enable a physical subscription");
594 pw.println(" disable-physical-subscription SUB_ID");
595 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
596 pw.println(" enable-physical-subscription SUB_ID");
597 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
598 }
599
Shuo Qianf5125122019-12-16 17:03:07 -0800600 private void onHelpDataTestMode() {
601 PrintWriter pw = getOutPrintWriter();
602 pw.println("Mobile Data Test Mode Commands:");
603 pw.println(" data enable: enable mobile data connectivity");
604 pw.println(" data disable: disable mobile data connectivity");
605 }
606
sqian9d4df8b2019-01-15 18:32:07 -0800607 private void onHelpEmergencyNumber() {
608 PrintWriter pw = getOutPrintWriter();
609 pw.println("Emergency Number Test Mode Commands:");
610 pw.println(" emergency-number-test-mode ");
611 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
612 + " the test mode");
613 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700614 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800615 pw.println(" -c: clear the emergency number list in the test mode.");
616 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700617 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800618 pw.println(" -p: get the full emergency number list in the test mode.");
619 }
620
Shuo Qian489d9282020-07-09 11:30:03 -0700621 private void onHelpEndBlockSupperssion() {
622 PrintWriter pw = getOutPrintWriter();
623 pw.println("End Block Suppression command:");
624 pw.println(" end-block-suppression: disable suppressing blocking by contact");
625 pw.println(" with emergency services.");
626 }
627
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100628 private void onHelpCc() {
629 PrintWriter pw = getOutPrintWriter();
630 pw.println("Carrier Config Commands:");
631 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
632 pw.println(" Print carrier config values.");
633 pw.println(" Options are:");
634 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
635 pw.println(" is specified, it will choose the default voice SIM slot.");
636 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
637 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100638 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100639 pw.println(" Set carrier config KEY to NEW_VALUE.");
640 pw.println(" Options are:");
641 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
642 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100643 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100644 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
645 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
646 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
647 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000648 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
649 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
650 pw.println(" provided through standard input and follow CarrierConfig XML format.");
651 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
652 pw.println(" Options are:");
653 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
654 pw.println(" is specified, it will choose the default voice SIM slot.");
655 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100656 pw.println(" cc clear-values [-s SLOT_ID]");
657 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000658 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100659 pw.println(" Options are:");
660 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
661 pw.println(" is specified, it will choose the default voice SIM slot.");
662 }
663
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000664 private void onHelpEuicc() {
665 PrintWriter pw = getOutPrintWriter();
666 pw.println("Euicc Commands:");
667 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
668 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
669 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
670 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
671 }
672
Hui Wang641e81c2020-10-12 12:14:23 -0700673 private void onHelpGba() {
674 PrintWriter pw = getOutPrintWriter();
675 pw.println("Gba Commands:");
676 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
677 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
678 pw.println(" Options are:");
679 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
680 pw.println(" is specified, it will choose the default voice SIM slot.");
681 pw.println(" gba get-service [-s SLOT_ID]");
682 pw.println(" Gets the package name of the currently defined GbaService.");
683 pw.println(" Options are:");
684 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
685 pw.println(" is specified, it will choose the default voice SIM slot.");
686 pw.println(" gba set-release [-s SLOT_ID] n");
687 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
688 pw.println(" Do not release/unbind if n is -1.");
689 pw.println(" Options are:");
690 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
691 pw.println(" is specified, it will choose the default voice SIM slot.");
692 pw.println(" gba get-release [-s SLOT_ID]");
693 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
694 pw.println(" Options are:");
695 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
696 pw.println(" is specified, it will choose the default voice SIM slot.");
697 }
698
Hui Wang761a6682020-10-31 05:12:53 +0000699 private void onHelpSrc() {
700 PrintWriter pw = getOutPrintWriter();
701 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800702 pw.println(" src set-test-enabled true|false");
703 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
704 pw.println(" The value could be true, false, or null(undefined).");
705 pw.println(" src get-test-enabled");
706 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000707 pw.println(" src set-device-enabled true|false|null");
708 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
709 pw.println(" The value could be true, false, or null(undefined).");
710 pw.println(" src get-device-enabled");
711 pw.println(" Gets the device config for RCS VoLTE single registration.");
712 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
713 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
714 pw.println(" The value could be true, false, or null(undefined).");
715 pw.println(" Options are:");
716 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
717 pw.println(" is specified, it will choose the default voice SIM slot.");
718 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
719 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
720 pw.println(" Options are:");
721 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
722 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800723 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
724 pw.println(" Sets ims feature validation result.");
725 pw.println(" The value could be true, false, or null(undefined).");
726 pw.println(" Options are:");
727 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
728 pw.println(" is specified, it will choose the default voice SIM slot.");
729 pw.println(" src get-feature-validation [-s SLOT_ID]");
730 pw.println(" Gets ims feature validation override value.");
731 pw.println(" Options are:");
732 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
733 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000734 }
735
SongFerngWang98dd5992021-05-13 17:50:00 +0800736 private void onHelpAllowedNetworkTypes() {
737 PrintWriter pw = getOutPrintWriter();
738 pw.println("Allowed Network Types Commands:");
739 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
740 pw.println(" Print allowed network types value.");
741 pw.println(" Options are:");
742 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
743 pw.println(" option is specified, it will choose the default voice SIM slot.");
744 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
745 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
746 pw.println(" Options are:");
747 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
748 pw.println(" option is specified, it will choose the default voice SIM slot.");
749 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
750 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
751 pw.println(" at TelephonyManager.java");
752 pw.println(" For example:");
753 pw.println(" NR only : 10000000000000000000");
754 pw.println(" NR|LTE : 11000001000000000000");
755 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
756 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
757 pw.println(" LTE only : 01000001000000000000");
758 }
759
jimsun3b9ccac2021-10-26 15:01:23 +0800760 private void onHelpRadio() {
761 PrintWriter pw = getOutPrintWriter();
762 pw.println("Radio Commands:");
763 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
764 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
765 pw.println(" to be the bound. Options are:");
766 pw.println(" -s: the service name that the modem service should be bound for.");
767 pw.println(" If no option is specified, it will bind to the default.");
768 pw.println(" radio get-modem-service");
769 pw.println(" Gets the service name of the currently defined modem service.");
770 pw.println(" If it is binding to default, 'default' returns.");
771 pw.println(" If it doesn't bind to any modem service for some reasons,");
772 pw.println(" the result would be 'unknown'.");
773 }
774
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700775 private void onHelpSatellite() {
776 PrintWriter pw = getOutPrintWriter();
777 pw.println("Satellite Commands:");
778 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
779 pw.println(" Sets the package name of satellite service defined in");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700780 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700781 pw.println(" -s: the satellite service package name that Telephony will bind to.");
782 pw.println(" If no option is specified, it will bind to the default.");
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700783 pw.println(" set-satellite-gateway-service-package-name [-s SERVICE_PACKAGE_NAME]");
784 pw.println(" Sets the package name of satellite gateway service defined in");
785 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
786 pw.println(" -s: the satellite gateway service package name that Telephony will bind");
787 pw.println(" to. If no option is specified, it will bind to the default.");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700788 pw.println(" set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
789 pw.println(" Sets the timeout duration in millis that satellite will stay at listening");
790 pw.println(" mode. Options are:");
791 pw.println(" -t: the timeout duration in milliseconds.");
792 pw.println(" If no option is specified, it will use the default values.");
Thomas Nguyen87dce732023-04-20 18:27:16 -0700793 pw.println(" set-satellite-pointing-ui-class-name [-p PACKAGE_NAME -c CLASS_NAME]");
794 pw.println(" Sets the package and class name of satellite pointing UI app defined in");
795 pw.println(" PACKAGE_NAME and CLASS_NAME to be launched. Options are:");
796 pw.println(" -p: the satellite pointing UI app package name that Telephony will");
797 pw.println(" launch. If no option is specified, it will launch the default.");
798 pw.println(" -c: the satellite pointing UI app class name that Telephony will");
799 pw.println(" launch.");
Thomas Nguyen11a051f2023-10-25 10:14:55 -0700800 pw.println(" set-emergency-call-to-satellite-handover-type [-t HANDOVER_TYPE ");
801 pw.println(" -d DELAY_SECONDS] Override connectivity status in monitoring emergency ");
802 pw.println(" call and sending EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer.");
803 pw.println(" Options are:");
804 pw.println(" -t: the emergency call to satellite handover type.");
805 pw.println(" If no option is specified, override is disabled.");
806 pw.println(" -d: the delay in seconds in sending EVENT_DISPLAY_EMERGENCY_MESSAGE.");
807 pw.println(" If no option is specified, there is no delay in sending the event.");
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -0800808 pw.println(" set-satellite-access-control-overlay-configs [-r -a -f SATELLITE_S2_FILE ");
809 pw.println(" -d LOCATION_FRESH_DURATION_NANOS -c COUNTRY_CODES] Override the overlay");
810 pw.println(" configs of satellite access controller.");
811 pw.println(" Options are:");
812 pw.println(" -r: clear the overriding. Absent means enable overriding.");
813 pw.println(" -a: the country codes is an allowed list. Absent means disallowed.");
814 pw.println(" -f: the satellite s2 file.");
815 pw.println(" -d: the location fresh duration nanos.");
816 pw.println(" -c: the list of satellite country codes separated by comma.");
817 pw.println(" set-country-codes [-r -n CURRENT_NETWORK_COUNTRY_CODES -c");
818 pw.println(" CACHED_NETWORK_COUNTRY_CODES -l LOCATION_COUNTRY_CODE -t");
819 pw.println(" LOCATION_COUNTRY_CODE_TIMESTAMP] ");
820 pw.println(" Override the cached location country code and its update timestamp. ");
821 pw.println(" Options are:");
822 pw.println(" -r: clear the overriding. Absent means enable overriding.");
823 pw.println(" -n: the current network country code ISOs.");
824 pw.println(" -c: the cached network country code ISOs.");
825 pw.println(" -l: the location country code ISO.");
826 pw.println(" -t: the update timestamp nanos of the location country code.");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700827 }
828
Ling Ma4fbab492022-01-25 22:36:16 +0000829 private void onHelpImei() {
830 PrintWriter pw = getOutPrintWriter();
831 pw.println("IMEI Commands:");
832 pw.println(" get-imei [-s SLOT_ID]");
833 pw.println(" Gets the device IMEI. Options are:");
834 pw.println(" -s: the slot ID to get the IMEI. If no option");
835 pw.println(" is specified, it will choose the default voice SIM slot.");
836 }
837
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700838 private int handleImsCommand() {
839 String arg = getNextArg();
840 if (arg == null) {
841 onHelpIms();
842 return 0;
843 }
844
845 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800846 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700847 return handleImsSetServiceCommand();
848 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800849 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700850 return handleImsGetServiceCommand();
851 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800852 case IMS_CLEAR_SERVICE_OVERRIDE: {
853 return handleImsClearCarrierServiceCommand();
854 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800855 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700856 return handleEnableIms();
857 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800858 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700859 return handleDisableIms();
860 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700861 case IMS_CEP: {
862 return handleCepChange();
863 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700864 }
865
866 return -1;
867 }
868
Shuo Qianf5125122019-12-16 17:03:07 -0800869 private int handleDataTestModeCommand() {
870 PrintWriter errPw = getErrPrintWriter();
871 String arg = getNextArgRequired();
872 if (arg == null) {
873 onHelpDataTestMode();
874 return 0;
875 }
876 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800877 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800878 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700879 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800880 } catch (RemoteException ex) {
881 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
882 errPw.println("Exception: " + ex.getMessage());
883 return -1;
884 }
885 break;
886 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800887 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800888 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700889 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800890 } catch (RemoteException ex) {
891 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
892 errPw.println("Exception: " + ex.getMessage());
893 return -1;
894 }
895 break;
896 }
897 default:
898 onHelpDataTestMode();
899 break;
900 }
901 return 0;
902 }
903
Shuo Qianccbaf742021-02-22 18:32:21 -0800904 private int handleEmergencyCallbackModeCommand() {
905 PrintWriter errPw = getErrPrintWriter();
906 try {
907 mInterface.startEmergencyCallbackMode();
908 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
909 } catch (RemoteException ex) {
910 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
911 errPw.println("Exception: " + ex.getMessage());
912 return -1;
913 }
914 return 0;
915 }
916
Grant Menke567d48f2022-08-18 20:19:10 +0000917 private void removeEmergencyNumberTestMode(String emergencyNumber) {
918 PrintWriter errPw = getErrPrintWriter();
919 for (int routingType : ROUTING_TYPES) {
920 try {
921 mInterface.updateEmergencyNumberListTestMode(
922 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
923 new EmergencyNumber(emergencyNumber, "", "",
924 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
925 new ArrayList<String>(),
926 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
927 routingType));
928 } catch (RemoteException ex) {
929 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
930 errPw.println("Exception: " + ex.getMessage());
931 }
932 }
933 }
934
sqian9d4df8b2019-01-15 18:32:07 -0800935 private int handleEmergencyNumberTestModeCommand() {
936 PrintWriter errPw = getErrPrintWriter();
937 String opt = getNextOption();
938 if (opt == null) {
939 onHelpEmergencyNumber();
940 return 0;
941 }
sqian9d4df8b2019-01-15 18:32:07 -0800942 switch (opt) {
943 case "-a": {
944 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000945 if (emergencyNumberCmd == null){
946 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800947 return -1;
948 }
Grant Menke567d48f2022-08-18 20:19:10 +0000949 String[] params = emergencyNumberCmd.split(":");
950 String emergencyNumber;
951 if (params[0] == null ||
952 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
953 errPw.println(INVALID_ENTRY_ERROR);
954 return -1;
955 } else {
956 emergencyNumber = params[0];
957 }
958 removeEmergencyNumberTestMode(emergencyNumber);
959 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
960 if (params.length > 1) {
961 switch (params[1].toLowerCase(Locale.ROOT)) {
962 case "emergency":
963 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
964 break;
965 case "normal":
966 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
967 break;
968 case "unknown":
969 break;
970 default:
971 errPw.println("\"" + params[1] + "\" is not a valid specification for "
972 + "emergency call routing. Please enter either \"normal\", "
973 + "\"unknown\", or \"emergency\" for call routing. "
974 + "(-a 1234:normal)");
975 return -1;
976 }
977 }
sqian9d4df8b2019-01-15 18:32:07 -0800978 try {
979 mInterface.updateEmergencyNumberListTestMode(
980 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000981 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800982 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
983 new ArrayList<String>(),
984 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000985 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800986 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000987 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800988 + ", error " + ex.getMessage());
989 errPw.println("Exception: " + ex.getMessage());
990 return -1;
991 }
992 break;
993 }
994 case "-c": {
995 try {
996 mInterface.updateEmergencyNumberListTestMode(
997 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
998 } catch (RemoteException ex) {
999 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
1000 errPw.println("Exception: " + ex.getMessage());
1001 return -1;
1002 }
1003 break;
1004 }
1005 case "-r": {
1006 String emergencyNumberCmd = getNextArgRequired();
1007 if (emergencyNumberCmd == null
1008 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -07001009 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -08001010 + " to be specified after -r in the command ");
1011 return -1;
1012 }
Grant Menke567d48f2022-08-18 20:19:10 +00001013 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -08001014 break;
1015 }
1016 case "-p": {
1017 try {
1018 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
1019 } catch (RemoteException ex) {
1020 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
1021 errPw.println("Exception: " + ex.getMessage());
1022 return -1;
1023 }
1024 break;
1025 }
1026 default:
1027 onHelpEmergencyNumber();
1028 break;
1029 }
1030 return 0;
1031 }
1032
Hall Liud892bec2018-11-30 14:51:45 -08001033 private int handleNumberVerificationCommand() {
1034 String arg = getNextArg();
1035 if (arg == null) {
1036 onHelpNumberVerification();
1037 return 0;
1038 }
1039
Hall Liuca5af3a2018-12-04 16:58:23 -08001040 if (!checkShellUid()) {
1041 return -1;
1042 }
1043
Hall Liud892bec2018-11-30 14:51:45 -08001044 switch (arg) {
1045 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -08001046 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
1047 return 0;
1048 }
Hall Liuca5af3a2018-12-04 16:58:23 -08001049 case NUMBER_VERIFICATION_FAKE_CALL: {
1050 boolean val = NumberVerificationManager.getInstance()
1051 .checkIncomingCall(getNextArg());
1052 getOutPrintWriter().println(val ? "1" : "0");
1053 return 0;
1054 }
Hall Liud892bec2018-11-30 14:51:45 -08001055 }
1056
1057 return -1;
1058 }
1059
Jordan Liu0ccee222021-04-27 11:55:13 -07001060 private boolean subIsEsim(int subId) {
1061 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
1062 if (info != null) {
1063 return info.isEmbedded();
1064 }
1065 return false;
1066 }
1067
1068 private int handleEnablePhysicalSubscription(boolean enable) {
1069 PrintWriter errPw = getErrPrintWriter();
1070 int subId = 0;
1071 try {
1072 subId = Integer.parseInt(getNextArgRequired());
1073 } catch (NumberFormatException e) {
1074 errPw.println((enable ? "enable" : "disable")
1075 + "-physical-subscription requires an integer as a subId.");
1076 return -1;
1077 }
1078 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1079 // non user build.
1080 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1081 errPw.println("cc: Permission denied.");
1082 return -1;
1083 }
1084 // Verify that the subId represents a physical sub
1085 if (subIsEsim(subId)) {
1086 errPw.println("SubId " + subId + " is not for a physical subscription");
1087 return -1;
1088 }
1089 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1090 + " physical subscription with subId=" + subId);
1091 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1092 return 0;
1093 }
1094
Jack Nudelman644b91a2021-03-12 14:09:48 -08001095 private int handleThermalMitigationCommand() {
1096 String arg = getNextArg();
1097 String packageName = getNextArg();
1098 if (arg == null || packageName == null) {
1099 onHelpThermalMitigation();
1100 return 0;
1101 }
1102
1103 if (!checkShellUid()) {
1104 return -1;
1105 }
1106
1107 switch (arg) {
1108 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1109 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1110 return 0;
1111 }
1112 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1113 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1114 mContext);
1115 return 0;
1116 }
1117 default:
1118 onHelpThermalMitigation();
1119 }
1120
1121 return -1;
1122
1123 }
1124
Tyler Gunn92479152021-01-20 16:30:10 -08001125 private int handleD2dCommand() {
1126 String arg = getNextArg();
1127 if (arg == null) {
1128 onHelpD2D();
1129 return 0;
1130 }
1131
1132 switch (arg) {
1133 case D2D_SEND: {
1134 return handleD2dSendCommand();
1135 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001136 case D2D_TRANSPORT: {
1137 return handleD2dTransportCommand();
1138 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001139 case D2D_SET_DEVICE_SUPPORT: {
1140 return handleD2dDeviceSupportedCommand();
1141 }
Tyler Gunn92479152021-01-20 16:30:10 -08001142 }
1143
1144 return -1;
1145 }
1146
1147 private int handleD2dSendCommand() {
1148 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001149 int messageType = -1;
1150 int messageValue = -1;
1151
Tyler Gunn92479152021-01-20 16:30:10 -08001152 String arg = getNextArg();
1153 if (arg == null) {
1154 onHelpD2D();
1155 return 0;
1156 }
1157 try {
1158 messageType = Integer.parseInt(arg);
1159 } catch (NumberFormatException e) {
1160 errPw.println("message type must be a valid integer");
1161 return -1;
1162 }
1163
1164 arg = getNextArg();
1165 if (arg == null) {
1166 onHelpD2D();
1167 return 0;
1168 }
1169 try {
1170 messageValue = Integer.parseInt(arg);
1171 } catch (NumberFormatException e) {
1172 errPw.println("message value must be a valid integer");
1173 return -1;
1174 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001175
Tyler Gunn92479152021-01-20 16:30:10 -08001176 try {
1177 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1178 } catch (RemoteException e) {
1179 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1180 errPw.println("Exception: " + e.getMessage());
1181 return -1;
1182 }
1183
1184 return 0;
1185 }
1186
Tyler Gunnbabbda02021-02-10 11:05:02 -08001187 private int handleD2dTransportCommand() {
1188 PrintWriter errPw = getErrPrintWriter();
1189
1190 String arg = getNextArg();
1191 if (arg == null) {
1192 onHelpD2D();
1193 return 0;
1194 }
1195
1196 try {
1197 mInterface.setActiveDeviceToDeviceTransport(arg);
1198 } catch (RemoteException e) {
1199 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1200 errPw.println("Exception: " + e.getMessage());
1201 return -1;
1202 }
1203 return 0;
1204 }
Nazanin014f41e2021-05-06 17:26:31 -07001205 private int handleBarringCommand() {
1206 String arg = getNextArg();
1207 if (arg == null) {
1208 onHelpBarring();
1209 return 0;
1210 }
1211
1212 switch (arg) {
1213 case BARRING_SEND_INFO: {
1214 return handleBarringSendCommand();
1215 }
1216 }
1217 return -1;
1218 }
1219
1220 private int handleBarringSendCommand() {
1221 PrintWriter errPw = getErrPrintWriter();
1222 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001223 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001224 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1225 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1226 boolean isConditionallyBarred = false;
1227 int conditionalBarringTimeSeconds = 0;
1228
1229 String opt;
1230 while ((opt = getNextOption()) != null) {
1231 switch (opt) {
1232 case "-s": {
1233 try {
1234 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001235 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001236 } catch (NumberFormatException e) {
1237 errPw.println("barring send requires an integer as a SLOT_ID.");
1238 return -1;
1239 }
1240 break;
1241 }
1242 case "-b": {
1243 try {
1244 barringType = Integer.parseInt(getNextArgRequired());
1245 if (barringType < -1 || barringType > 2) {
1246 throw new NumberFormatException();
1247 }
1248
1249 } catch (NumberFormatException e) {
1250 errPw.println("barring send requires an integer in range [-1,2] as "
1251 + "a BARRING_TYPE.");
1252 return -1;
1253 }
1254 break;
1255 }
1256 case "-c": {
1257 try {
1258 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1259 } catch (Exception e) {
1260 errPw.println("barring send requires a boolean after -c indicating"
1261 + " conditional barring");
1262 return -1;
1263 }
1264 break;
1265 }
1266 case "-t": {
1267 try {
1268 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1269 } catch (NumberFormatException e) {
1270 errPw.println("barring send requires an integer for time of barring"
1271 + " in seconds after -t for conditional barring");
1272 return -1;
1273 }
1274 break;
1275 }
1276 }
1277 }
1278 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1279 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1280 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1281 barringServiceInfos.append(0, bsi);
1282 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1283 try {
1284 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1285 } catch (Exception e) {
1286 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1287 errPw.println("Exception: " + e.getMessage());
1288 return -1;
1289 }
1290 return 0;
1291 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001292
Tyler Gunnd4575212021-05-03 14:46:49 -07001293 private int handleD2dDeviceSupportedCommand() {
1294 PrintWriter errPw = getErrPrintWriter();
1295
1296 String arg = getNextArg();
1297 if (arg == null) {
1298 onHelpD2D();
1299 return 0;
1300 }
1301
Jack Yua533d632022-09-30 13:53:46 -07001302 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001303 try {
1304 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1305 } catch (RemoteException e) {
1306 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1307 errPw.println("Exception: " + e.getMessage());
1308 return -1;
1309 }
1310 return 0;
1311 }
1312
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001313 // ims set-ims-service
1314 private int handleImsSetServiceCommand() {
1315 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001316 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001317 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001318 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001319
1320 String opt;
1321 while ((opt = getNextOption()) != null) {
1322 switch (opt) {
1323 case "-s": {
1324 try {
1325 slotId = Integer.parseInt(getNextArgRequired());
1326 } catch (NumberFormatException e) {
1327 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1328 return -1;
1329 }
1330 break;
1331 }
1332 case "-c": {
1333 isCarrierService = true;
1334 break;
1335 }
1336 case "-d": {
1337 isCarrierService = false;
1338 break;
1339 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001340 case "-f": {
1341 String featureString = getNextArgRequired();
1342 String[] features = featureString.split(",");
1343 for (int i = 0; i < features.length; i++) {
1344 try {
1345 Integer result = Integer.parseInt(features[i]);
1346 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1347 || result >= ImsFeature.FEATURE_MAX) {
1348 errPw.println("ims set-ims-service -f " + result
1349 + " is an invalid feature.");
1350 return -1;
1351 }
1352 featuresList.add(result);
1353 } catch (NumberFormatException e) {
1354 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1355 + " as an integer.");
1356 return -1;
1357 }
1358 }
1359 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001360 }
1361 }
1362 // Mandatory param, either -c or -d
1363 if (isCarrierService == null) {
1364 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1365 return -1;
1366 }
1367
1368 String packageName = getNextArg();
1369
1370 try {
1371 if (packageName == null) {
1372 packageName = "";
1373 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001374 int[] featureArray = new int[featuresList.size()];
1375 for (int i = 0; i < featuresList.size(); i++) {
1376 featureArray[i] = featuresList.get(i);
1377 }
1378 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1379 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001380 if (VDBG) {
1381 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001382 + (isCarrierService ? "-c " : "-d ")
1383 + "-f " + featuresList + " "
1384 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001385 }
1386 getOutPrintWriter().println(result);
1387 } catch (RemoteException e) {
1388 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001389 + (isCarrierService ? "-c " : "-d ")
1390 + "-f " + featuresList + " "
1391 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001392 errPw.println("Exception: " + e.getMessage());
1393 return -1;
1394 }
1395 return 0;
1396 }
1397
Brad Ebinger999d3302020-11-25 14:31:39 -08001398 // ims clear-ims-service-override
1399 private int handleImsClearCarrierServiceCommand() {
1400 PrintWriter errPw = getErrPrintWriter();
1401 int slotId = getDefaultSlot();
1402
1403 String opt;
1404 while ((opt = getNextOption()) != null) {
1405 switch (opt) {
1406 case "-s": {
1407 try {
1408 slotId = Integer.parseInt(getNextArgRequired());
1409 } catch (NumberFormatException e) {
1410 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1411 return -1;
1412 }
1413 break;
1414 }
1415 }
1416 }
1417
1418 try {
1419 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1420 if (VDBG) {
1421 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1422 + ", result=" + result);
1423 }
1424 getOutPrintWriter().println(result);
1425 } catch (RemoteException e) {
1426 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1427 + ", error" + e.getMessage());
1428 errPw.println("Exception: " + e.getMessage());
1429 return -1;
1430 }
1431 return 0;
1432 }
1433
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001434 // ims get-ims-service
1435 private int handleImsGetServiceCommand() {
1436 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001437 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001438 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001439 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001440
1441 String opt;
1442 while ((opt = getNextOption()) != null) {
1443 switch (opt) {
1444 case "-s": {
1445 try {
1446 slotId = Integer.parseInt(getNextArgRequired());
1447 } catch (NumberFormatException e) {
1448 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1449 return -1;
1450 }
1451 break;
1452 }
1453 case "-c": {
1454 isCarrierService = true;
1455 break;
1456 }
1457 case "-d": {
1458 isCarrierService = false;
1459 break;
1460 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001461 case "-f": {
1462 try {
1463 featureType = Integer.parseInt(getNextArg());
1464 } catch (NumberFormatException e) {
1465 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1466 return -1;
1467 }
1468 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1469 || featureType >= ImsFeature.FEATURE_MAX) {
1470 errPw.println("ims get-ims-service -f invalid feature.");
1471 return -1;
1472 }
1473 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001474 }
1475 }
1476 // Mandatory param, either -c or -d
1477 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001478 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001479 return -1;
1480 }
1481
1482 String result;
1483 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001484 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001485 } catch (RemoteException e) {
1486 return -1;
1487 }
1488 if (VDBG) {
1489 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001490 + (isCarrierService ? "-c " : "-d ")
1491 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1492 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001493 }
1494 getOutPrintWriter().println(result);
1495 return 0;
1496 }
1497
1498 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001499 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001500 String opt;
1501 while ((opt = getNextOption()) != null) {
1502 switch (opt) {
1503 case "-s": {
1504 try {
1505 slotId = Integer.parseInt(getNextArgRequired());
1506 } catch (NumberFormatException e) {
1507 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1508 return -1;
1509 }
1510 break;
1511 }
1512 }
1513 }
1514 try {
1515 mInterface.enableIms(slotId);
1516 } catch (RemoteException e) {
1517 return -1;
1518 }
1519 if (VDBG) {
1520 Log.v(LOG_TAG, "ims enable -s " + slotId);
1521 }
1522 return 0;
1523 }
1524
1525 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001526 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001527 String opt;
1528 while ((opt = getNextOption()) != null) {
1529 switch (opt) {
1530 case "-s": {
1531 try {
1532 slotId = Integer.parseInt(getNextArgRequired());
1533 } catch (NumberFormatException e) {
1534 getErrPrintWriter().println(
1535 "ims disable requires an integer as a SLOT_ID.");
1536 return -1;
1537 }
1538 break;
1539 }
1540 }
1541 }
1542 try {
1543 mInterface.disableIms(slotId);
1544 } catch (RemoteException e) {
1545 return -1;
1546 }
1547 if (VDBG) {
1548 Log.v(LOG_TAG, "ims disable -s " + slotId);
1549 }
1550 return 0;
1551 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001552
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001553 private int handleCepChange() {
1554 Log.i(LOG_TAG, "handleCepChange");
1555 String opt = getNextArg();
1556 if (opt == null) {
1557 return -1;
1558 }
1559 boolean isCepEnabled = opt.equals("enable");
1560
1561 try {
1562 mInterface.setCepEnabled(isCepEnabled);
1563 } catch (RemoteException e) {
1564 return -1;
1565 }
1566 return 0;
1567 }
1568
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001569 private int getDefaultSlot() {
1570 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1571 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1572 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1573 // If there is no default, default to slot 0.
1574 slotId = DEFAULT_PHONE_ID;
1575 }
1576 return slotId;
1577 }
sqian2fff4a32018-11-05 14:18:37 -08001578
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001579 // Parse options related to Carrier Config Commands.
1580 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001581 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001582 CcOptionParseResult result = new CcOptionParseResult();
1583 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1584 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001585
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001586 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001587 while ((opt = getNextOption()) != null) {
1588 switch (opt) {
1589 case "-s": {
1590 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001591 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1592 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1593 errPw.println(tag + "No valid subscription found.");
1594 return null;
1595 }
1596
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001597 } catch (IllegalArgumentException e) {
1598 // Missing slot id
1599 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001600 return null;
1601 }
1602 break;
1603 }
1604 case "-p": {
1605 if (allowOptionPersistent) {
1606 result.mPersistent = true;
1607 } else {
1608 errPw.println(tag + "Unexpected option " + opt);
1609 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001610 }
1611 break;
1612 }
1613 default: {
1614 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001615 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001616 }
1617 }
1618 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001619 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001620 }
1621
1622 private int slotStringToSubId(String tag, String slotString) {
1623 int slotId = -1;
1624 try {
1625 slotId = Integer.parseInt(slotString);
1626 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001627 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1628 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1629 }
1630
1631 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001632 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1633 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1634 }
1635
Qiong Liuf25799b2020-09-10 10:13:46 +08001636 Phone phone = PhoneFactory.getPhone(slotId);
1637 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001638 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1639 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1640 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001641 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001642 }
1643
Hall Liud892bec2018-11-30 14:51:45 -08001644 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001645 // adb can run as root or as shell, depending on whether the device is rooted.
1646 return Binder.getCallingUid() == Process.SHELL_UID
1647 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001648 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001649
1650 private int handleCcCommand() {
1651 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1652 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001653 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001654 getErrPrintWriter().println("cc: Permission denied.");
1655 return -1;
1656 }
1657
1658 String arg = getNextArg();
1659 if (arg == null) {
1660 onHelpCc();
1661 return 0;
1662 }
1663
1664 switch (arg) {
1665 case CC_GET_VALUE: {
1666 return handleCcGetValue();
1667 }
1668 case CC_SET_VALUE: {
1669 return handleCcSetValue();
1670 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001671 case CC_SET_VALUES_FROM_XML: {
1672 return handleCcSetValuesFromXml();
1673 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001674 case CC_CLEAR_VALUES: {
1675 return handleCcClearValues();
1676 }
1677 default: {
1678 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1679 }
1680 }
1681 return -1;
1682 }
1683
1684 // cc get-value
1685 private int handleCcGetValue() {
1686 PrintWriter errPw = getErrPrintWriter();
1687 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1688 String key = null;
1689
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001690 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001691 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001692 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001693 return -1;
1694 }
1695
1696 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001697 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001698 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001699 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001700 return -1;
1701 }
1702
1703 // Get the key.
1704 key = getNextArg();
1705 if (key != null) {
1706 // A key was provided. Verify if it is a valid key
1707 if (!bundle.containsKey(key)) {
1708 errPw.println(tag + key + " is not a valid key.");
1709 return -1;
1710 }
1711
1712 // Print the carrier config value for key.
1713 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1714 } else {
1715 // No key provided. Show all values.
1716 // Iterate over a sorted list of all carrier config keys and print them.
1717 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1718 for (String k : sortedSet) {
1719 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1720 }
1721 }
1722 return 0;
1723 }
1724
1725 // cc set-value
1726 private int handleCcSetValue() {
1727 PrintWriter errPw = getErrPrintWriter();
1728 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1729
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001730 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001731 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001732 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001733 return -1;
1734 }
1735
1736 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001737 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001738 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001739 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001740 return -1;
1741 }
1742
1743 // Get the key.
1744 String key = getNextArg();
1745 if (key == null || key.equals("")) {
1746 errPw.println(tag + "KEY is missing");
1747 return -1;
1748 }
1749
1750 // Verify if the key is valid
1751 if (!originalValues.containsKey(key)) {
1752 errPw.println(tag + key + " is not a valid key.");
1753 return -1;
1754 }
1755
1756 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1757 ArrayList<String> valueList = new ArrayList<String>();
1758 while (peekNextArg() != null) {
1759 valueList.add(getNextArg());
1760 }
1761
1762 // Find the type of the carrier config value
1763 CcType type = getType(tag, key, originalValues);
1764 if (type == CcType.UNKNOWN) {
1765 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1766 return -1;
1767 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001768 if (type == CcType.PERSISTABLE_BUNDLE) {
1769 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1770 + "Use set-values-from-xml instead.");
1771 return -1;
1772 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001773
1774 // Create an override bundle containing the key and value that should be overriden.
1775 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1776 if (overrideBundle == null) {
1777 return -1;
1778 }
1779
1780 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001781 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001782
1783 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001784 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001785 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001786 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001787 return -1;
1788 }
1789
1790 // Print the original and new value.
1791 String originalValueString = ccValueToString(key, type, originalValues);
1792 String newValueString = ccValueToString(key, type, newValues);
1793 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1794 getOutPrintWriter().println("New value: \n" + newValueString);
1795
1796 return 0;
1797 }
1798
Allen Xuee00f0e2022-03-14 21:04:49 +00001799 // cc set-values-from-xml
1800 private int handleCcSetValuesFromXml() {
1801 PrintWriter errPw = getErrPrintWriter();
1802 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1803
1804 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001805 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001806 if (options == null) {
1807 return -1;
1808 }
1809
1810 // Get bundle containing all current carrier configuration values.
1811 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1812 if (originalValues == null) {
1813 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1814 return -1;
1815 }
1816
1817 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1818 if (overrideBundle == null) {
1819 return -1;
1820 }
1821
1822 // Verify all values are valid types
1823 for (String key : overrideBundle.keySet()) {
1824 CcType type = getType(tag, key, originalValues);
1825 if (type == CcType.UNKNOWN) {
1826 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1827 return -1;
1828 }
1829 }
1830
1831 // Override the value
1832 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1833
1834 // Find bundle containing all new carrier configuration values after the override.
1835 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1836 if (newValues == null) {
1837 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1838 return -1;
1839 }
1840
1841 // Print the original and new values
1842 overrideBundle.keySet().forEach(key -> {
1843 CcType type = getType(tag, key, originalValues);
1844 String originalValueString = ccValueToString(key, type, originalValues);
1845 String newValueString = ccValueToString(key, type, newValues);
1846 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1847 getOutPrintWriter().println("New value: \n" + newValueString);
1848 });
1849
1850 return 0;
1851 }
1852
1853 private PersistableBundle readPersistableBundleFromXml(String tag) {
1854 PersistableBundle subIdBundles;
1855 try {
1856 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1857 } catch (IOException | RuntimeException e) {
1858 PrintWriter errPw = getErrPrintWriter();
1859 errPw.println(tag + e);
1860 return null;
1861 }
1862
1863 return subIdBundles;
1864 }
1865
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001866 // cc clear-values
1867 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001868 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1869
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001870 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001871 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001872 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001873 return -1;
1874 }
1875
1876 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001877 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001878 getOutPrintWriter()
1879 .println("All previously set carrier config override values has been cleared");
1880 return 0;
1881 }
1882
1883 private CcType getType(String tag, String key, PersistableBundle bundle) {
1884 // Find the type by checking the type of the current value stored in the bundle.
1885 Object value = bundle.get(key);
1886
1887 if (CC_TYPE_MAP.containsKey(key)) {
1888 return CC_TYPE_MAP.get(key);
1889 } else if (value != null) {
1890 if (value instanceof Boolean) {
1891 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001892 }
1893 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001894 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001895 }
1896 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001897 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001898 }
1899 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001900 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001901 }
1902 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001903 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001904 }
1905 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001906 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001907 }
1908 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001909 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001910 }
1911 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001912 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001913 }
1914 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001915 return CcType.STRING_ARRAY;
1916 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001917 if (value instanceof PersistableBundle) {
1918 return CcType.PERSISTABLE_BUNDLE;
1919 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001920 } else {
1921 // Current value was null and can therefore not be used in order to find the type.
1922 // Check the name of the key to infer the type. This check is not needed for primitive
1923 // data types (boolean, double, int and long), since they can not be null.
1924 if (key.endsWith("double_array")) {
1925 return CcType.DOUBLE_ARRAY;
1926 }
1927 if (key.endsWith("int_array")) {
1928 return CcType.INT_ARRAY;
1929 }
1930 if (key.endsWith("long_array")) {
1931 return CcType.LONG_ARRAY;
1932 }
1933 if (key.endsWith("string")) {
1934 return CcType.STRING;
1935 }
1936 if (key.endsWith("string_array") || key.endsWith("strings")) {
1937 return CcType.STRING_ARRAY;
1938 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001939 if (key.endsWith("bundle")) {
1940 return CcType.PERSISTABLE_BUNDLE;
1941 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001942 }
1943
1944 // Not possible to infer the type by looking at the current value or the key.
1945 PrintWriter errPw = getErrPrintWriter();
1946 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1947 return CcType.UNKNOWN;
1948 }
1949
1950 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1951 String result;
1952 StringBuilder valueString = new StringBuilder();
1953 String typeString = type.toString();
1954 Object value = bundle.get(key);
1955
1956 if (value == null) {
1957 valueString.append("null");
1958 } else {
1959 switch (type) {
1960 case DOUBLE_ARRAY: {
1961 // Format the string representation of the int array as value1 value2......
1962 double[] valueArray = (double[]) value;
1963 for (int i = 0; i < valueArray.length; i++) {
1964 if (i != 0) {
1965 valueString.append(" ");
1966 }
1967 valueString.append(valueArray[i]);
1968 }
1969 break;
1970 }
1971 case INT_ARRAY: {
1972 // Format the string representation of the int array as value1 value2......
1973 int[] valueArray = (int[]) value;
1974 for (int i = 0; i < valueArray.length; i++) {
1975 if (i != 0) {
1976 valueString.append(" ");
1977 }
1978 valueString.append(valueArray[i]);
1979 }
1980 break;
1981 }
1982 case LONG_ARRAY: {
1983 // Format the string representation of the int array as value1 value2......
1984 long[] valueArray = (long[]) value;
1985 for (int i = 0; i < valueArray.length; i++) {
1986 if (i != 0) {
1987 valueString.append(" ");
1988 }
1989 valueString.append(valueArray[i]);
1990 }
1991 break;
1992 }
1993 case STRING: {
1994 valueString.append("\"" + value.toString() + "\"");
1995 break;
1996 }
1997 case STRING_ARRAY: {
1998 // Format the string representation of the string array as "value1" "value2"....
1999 String[] valueArray = (String[]) value;
2000 for (int i = 0; i < valueArray.length; i++) {
2001 if (i != 0) {
2002 valueString.append(" ");
2003 }
2004 if (valueArray[i] != null) {
2005 valueString.append("\"" + valueArray[i] + "\"");
2006 } else {
2007 valueString.append("null");
2008 }
2009 }
2010 break;
2011 }
2012 default: {
2013 valueString.append(value.toString());
2014 }
2015 }
2016 }
2017 return String.format("%-70s %-15s %s", key, typeString, valueString);
2018 }
2019
2020 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
2021 ArrayList<String> valueList) {
2022 PrintWriter errPw = getErrPrintWriter();
2023 PersistableBundle bundle = new PersistableBundle();
2024
2025 // First verify that a valid number of values has been provided for the type.
2026 switch (type) {
2027 case BOOLEAN:
2028 case DOUBLE:
2029 case INT:
2030 case LONG: {
2031 if (valueList.size() != 1) {
2032 errPw.println(tag + "Expected 1 value for type " + type
2033 + ". Found: " + valueList.size());
2034 return null;
2035 }
2036 break;
2037 }
2038 case STRING: {
2039 if (valueList.size() > 1) {
2040 errPw.println(tag + "Expected 0 or 1 values for type " + type
2041 + ". Found: " + valueList.size());
2042 return null;
2043 }
2044 break;
2045 }
2046 }
2047
2048 // Parse the value according to type and add it to the Bundle.
2049 switch (type) {
2050 case BOOLEAN: {
2051 if ("true".equalsIgnoreCase(valueList.get(0))) {
2052 bundle.putBoolean(key, true);
2053 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
2054 bundle.putBoolean(key, false);
2055 } else {
2056 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2057 return null;
2058 }
2059 break;
2060 }
2061 case DOUBLE: {
2062 try {
2063 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
2064 } catch (NumberFormatException nfe) {
2065 // Not a valid double
2066 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2067 return null;
2068 }
2069 break;
2070 }
2071 case DOUBLE_ARRAY: {
2072 double[] valueDoubleArray = null;
2073 if (valueList.size() > 0) {
2074 valueDoubleArray = new double[valueList.size()];
2075 for (int i = 0; i < valueList.size(); i++) {
2076 try {
2077 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2078 } catch (NumberFormatException nfe) {
2079 // Not a valid double
2080 errPw.println(
2081 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2082 return null;
2083 }
2084 }
2085 }
2086 bundle.putDoubleArray(key, valueDoubleArray);
2087 break;
2088 }
2089 case INT: {
2090 try {
2091 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2092 } catch (NumberFormatException nfe) {
2093 // Not a valid integer
2094 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2095 return null;
2096 }
2097 break;
2098 }
2099 case INT_ARRAY: {
2100 int[] valueIntArray = null;
2101 if (valueList.size() > 0) {
2102 valueIntArray = new int[valueList.size()];
2103 for (int i = 0; i < valueList.size(); i++) {
2104 try {
2105 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2106 } catch (NumberFormatException nfe) {
2107 // Not a valid integer
2108 errPw.println(tag
2109 + "Unable to parse " + valueList.get(i) + " as an integer.");
2110 return null;
2111 }
2112 }
2113 }
2114 bundle.putIntArray(key, valueIntArray);
2115 break;
2116 }
2117 case LONG: {
2118 try {
2119 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2120 } catch (NumberFormatException nfe) {
2121 // Not a valid long
2122 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2123 return null;
2124 }
2125 break;
2126 }
2127 case LONG_ARRAY: {
2128 long[] valueLongArray = null;
2129 if (valueList.size() > 0) {
2130 valueLongArray = new long[valueList.size()];
2131 for (int i = 0; i < valueList.size(); i++) {
2132 try {
2133 valueLongArray[i] = Long.parseLong(valueList.get(i));
2134 } catch (NumberFormatException nfe) {
2135 // Not a valid long
2136 errPw.println(
2137 tag + "Unable to parse " + valueList.get(i) + " as a long");
2138 return null;
2139 }
2140 }
2141 }
2142 bundle.putLongArray(key, valueLongArray);
2143 break;
2144 }
2145 case STRING: {
2146 String value = null;
2147 if (valueList.size() > 0) {
2148 value = valueList.get(0);
2149 }
2150 bundle.putString(key, value);
2151 break;
2152 }
2153 case STRING_ARRAY: {
2154 String[] valueStringArray = null;
2155 if (valueList.size() > 0) {
2156 valueStringArray = new String[valueList.size()];
2157 valueList.toArray(valueStringArray);
2158 }
2159 bundle.putStringArray(key, valueStringArray);
2160 break;
2161 }
2162 }
2163 return bundle;
2164 }
Shuo Qian489d9282020-07-09 11:30:03 -07002165
2166 private int handleEndBlockSuppressionCommand() {
2167 if (!checkShellUid()) {
2168 return -1;
2169 }
2170
2171 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2172 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2173 }
2174 return 0;
2175 }
Hui Wang641e81c2020-10-12 12:14:23 -07002176
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002177 private int handleEuiccCommand() {
2178 String arg = getNextArg();
2179 if (arg == null) {
2180 onHelpEuicc();
2181 return 0;
2182 }
2183
2184 switch (arg) {
2185 case EUICC_SET_UI_COMPONENT: {
2186 return handleEuiccServiceCommand();
2187 }
2188 }
2189 return -1;
2190 }
2191
2192 private int handleEuiccServiceCommand() {
2193 String uiComponent = getNextArg();
2194 String packageName = getNextArg();
2195 if (packageName == null || uiComponent == null) {
2196 return -1;
2197 }
2198 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2199 if (VDBG) {
2200 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2201 + packageName);
2202 }
2203 return 0;
2204 }
2205
Michele Berionne54af4632020-12-28 20:23:16 +00002206 private int handleRestartModemCommand() {
2207 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2208 // non user build.
2209 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2210 getErrPrintWriter().println("RestartModem: Permission denied.");
2211 return -1;
2212 }
2213
2214 boolean result = TelephonyManager.getDefault().rebootRadio();
2215 getOutPrintWriter().println(result);
2216
2217 return result ? 0 : -1;
2218 }
2219
Ling Ma4fbab492022-01-25 22:36:16 +00002220 private int handleGetImei() {
2221 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2222 // non user build.
2223 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2224 getErrPrintWriter().println("Device IMEI: Permission denied.");
2225 return -1;
2226 }
2227
2228 final long identity = Binder.clearCallingIdentity();
2229
2230 String imei = null;
2231 String arg = getNextArg();
2232 if (arg != null) {
2233 try {
2234 int specifiedSlotIndex = Integer.parseInt(arg);
2235 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2236 } catch (NumberFormatException exception) {
2237 PrintWriter errPw = getErrPrintWriter();
2238 errPw.println("-s requires an integer as slot index.");
2239 return -1;
2240 }
2241
2242 } else {
2243 imei = TelephonyManager.from(mContext).getImei();
2244 }
2245 getOutPrintWriter().println("Device IMEI: " + imei);
2246
2247 Binder.restoreCallingIdentity(identity);
2248 return 0;
2249 }
2250
Michele Berionne5e411512020-11-13 02:36:59 +00002251 private int handleUnattendedReboot() {
2252 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2253 // non user build.
2254 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2255 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2256 return -1;
2257 }
2258
2259 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2260 getOutPrintWriter().println("result: " + result);
2261
2262 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2263 }
2264
Aman Gupta07124872022-02-09 08:02:14 +00002265 private int handleGetSimSlotsMapping() {
2266 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2267 // non user build.
2268 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2269 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2270 return -1;
2271 }
2272 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2273 String result = telephonyManager.getSimSlotMapping().toString();
2274 getOutPrintWriter().println("simSlotsMapping: " + result);
2275
2276 return 0;
2277 }
2278
Hui Wang641e81c2020-10-12 12:14:23 -07002279 private int handleGbaCommand() {
2280 String arg = getNextArg();
2281 if (arg == null) {
2282 onHelpGba();
2283 return 0;
2284 }
2285
2286 switch (arg) {
2287 case GBA_SET_SERVICE: {
2288 return handleGbaSetServiceCommand();
2289 }
2290 case GBA_GET_SERVICE: {
2291 return handleGbaGetServiceCommand();
2292 }
2293 case GBA_SET_RELEASE_TIME: {
2294 return handleGbaSetReleaseCommand();
2295 }
2296 case GBA_GET_RELEASE_TIME: {
2297 return handleGbaGetReleaseCommand();
2298 }
2299 }
2300
2301 return -1;
2302 }
2303
2304 private int getSubId(String cmd) {
2305 int slotId = getDefaultSlot();
2306 String opt = getNextOption();
2307 if (opt != null && opt.equals("-s")) {
2308 try {
2309 slotId = Integer.parseInt(getNextArgRequired());
2310 } catch (NumberFormatException e) {
2311 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2312 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2313 }
2314 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002315 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002316 }
2317
2318 private int handleGbaSetServiceCommand() {
2319 int subId = getSubId("gba set-service");
2320 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2321 return -1;
2322 }
2323
2324 String packageName = getNextArg();
2325 try {
2326 if (packageName == null) {
2327 packageName = "";
2328 }
2329 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2330 if (VDBG) {
2331 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2332 + packageName + ", result=" + result);
2333 }
2334 getOutPrintWriter().println(result);
2335 } catch (RemoteException e) {
2336 Log.w(LOG_TAG, "gba set-service " + subId + " "
2337 + packageName + ", error" + e.getMessage());
2338 getErrPrintWriter().println("Exception: " + e.getMessage());
2339 return -1;
2340 }
2341 return 0;
2342 }
2343
2344 private int handleGbaGetServiceCommand() {
2345 String result;
2346
2347 int subId = getSubId("gba get-service");
2348 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2349 return -1;
2350 }
2351
2352 try {
2353 result = mInterface.getBoundGbaService(subId);
2354 } catch (RemoteException e) {
2355 return -1;
2356 }
2357 if (VDBG) {
2358 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2359 }
2360 getOutPrintWriter().println(result);
2361 return 0;
2362 }
2363
2364 private int handleGbaSetReleaseCommand() {
2365 //the release time value could be -1
2366 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2367 : SubscriptionManager.getDefaultSubscriptionId();
2368 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2369 return -1;
2370 }
2371
2372 String intervalStr = getNextArg();
2373 if (intervalStr == null) {
2374 return -1;
2375 }
2376
2377 try {
2378 int interval = Integer.parseInt(intervalStr);
2379 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2380 if (VDBG) {
2381 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2382 + intervalStr + ", result=" + result);
2383 }
2384 getOutPrintWriter().println(result);
2385 } catch (NumberFormatException | RemoteException e) {
2386 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2387 + intervalStr + ", error" + e.getMessage());
2388 getErrPrintWriter().println("Exception: " + e.getMessage());
2389 return -1;
2390 }
2391 return 0;
2392 }
2393
2394 private int handleGbaGetReleaseCommand() {
2395 int subId = getSubId("gba get-release");
2396 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2397 return -1;
2398 }
2399
2400 int result = 0;
2401 try {
2402 result = mInterface.getGbaReleaseTime(subId);
2403 } catch (RemoteException e) {
2404 return -1;
2405 }
2406 if (VDBG) {
2407 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2408 }
2409 getOutPrintWriter().println(result);
2410 return 0;
2411 }
Hui Wang761a6682020-10-31 05:12:53 +00002412
2413 private int handleSingleRegistrationConfigCommand() {
2414 String arg = getNextArg();
2415 if (arg == null) {
2416 onHelpSrc();
2417 return 0;
2418 }
2419
2420 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002421 case SRC_SET_TEST_ENABLED: {
2422 return handleSrcSetTestEnabledCommand();
2423 }
2424 case SRC_GET_TEST_ENABLED: {
2425 return handleSrcGetTestEnabledCommand();
2426 }
Hui Wang761a6682020-10-31 05:12:53 +00002427 case SRC_SET_DEVICE_ENABLED: {
2428 return handleSrcSetDeviceEnabledCommand();
2429 }
2430 case SRC_GET_DEVICE_ENABLED: {
2431 return handleSrcGetDeviceEnabledCommand();
2432 }
2433 case SRC_SET_CARRIER_ENABLED: {
2434 return handleSrcSetCarrierEnabledCommand();
2435 }
2436 case SRC_GET_CARRIER_ENABLED: {
2437 return handleSrcGetCarrierEnabledCommand();
2438 }
Hui Wangb647abe2021-02-26 09:33:38 -08002439 case SRC_SET_FEATURE_ENABLED: {
2440 return handleSrcSetFeatureValidationCommand();
2441 }
2442 case SRC_GET_FEATURE_ENABLED: {
2443 return handleSrcGetFeatureValidationCommand();
2444 }
Hui Wang761a6682020-10-31 05:12:53 +00002445 }
2446
2447 return -1;
2448 }
2449
James.cf Linbcdf8b32021-01-14 16:44:13 +08002450 private int handleRcsUceCommand() {
2451 String arg = getNextArg();
2452 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002453 onHelpUce();
2454 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002455 }
2456
2457 switch (arg) {
2458 case UCE_REMOVE_EAB_CONTACT:
2459 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002460 case UCE_GET_EAB_CONTACT:
2461 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002462 case UCE_GET_EAB_CAPABILITY:
2463 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002464 case UCE_GET_DEVICE_ENABLED:
2465 return handleUceGetDeviceEnabledCommand();
2466 case UCE_SET_DEVICE_ENABLED:
2467 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002468 case UCE_OVERRIDE_PUBLISH_CAPS:
2469 return handleUceOverridePublishCaps();
2470 case UCE_GET_LAST_PIDF_XML:
2471 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002472 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2473 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002474 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2475 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002476 }
2477 return -1;
2478 }
2479
2480 private int handleRemovingEabContactCommand() {
2481 int subId = getSubId("uce remove-eab-contact");
2482 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2483 return -1;
2484 }
2485
2486 String phoneNumber = getNextArgRequired();
2487 if (TextUtils.isEmpty(phoneNumber)) {
2488 return -1;
2489 }
2490 int result = 0;
2491 try {
2492 result = mInterface.removeContactFromEab(subId, phoneNumber);
2493 } catch (RemoteException e) {
2494 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2495 getErrPrintWriter().println("Exception: " + e.getMessage());
2496 return -1;
2497 }
2498
2499 if (VDBG) {
2500 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2501 }
calvinpan293ea1b2021-02-04 17:52:13 +08002502 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002503 }
2504
calvinpane4a8a1d2021-01-25 13:51:18 +08002505 private int handleGettingEabContactCommand() {
2506 String phoneNumber = getNextArgRequired();
2507 if (TextUtils.isEmpty(phoneNumber)) {
2508 return -1;
2509 }
2510 String result = "";
2511 try {
2512 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002513 } catch (RemoteException e) {
2514 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2515 getErrPrintWriter().println("Exception: " + e.getMessage());
2516 return -1;
2517 }
2518
2519 if (VDBG) {
2520 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2521 }
calvinpan293ea1b2021-02-04 17:52:13 +08002522 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002523 return 0;
2524 }
2525
Calvin Pana1434322021-07-01 19:27:01 +08002526 private int handleGettingEabCapabilityCommand() {
2527 String phoneNumber = getNextArgRequired();
2528 if (TextUtils.isEmpty(phoneNumber)) {
2529 return -1;
2530 }
2531 String result = "";
2532 try {
2533 result = mInterface.getCapabilityFromEab(phoneNumber);
2534 } catch (RemoteException e) {
2535 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2536 getErrPrintWriter().println("Exception: " + e.getMessage());
2537 return -1;
2538 }
2539
2540 if (VDBG) {
2541 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2542 }
2543 getOutPrintWriter().println(result);
2544 return 0;
2545 }
2546
James.cf Lin4b784aa2021-01-31 03:25:15 +08002547 private int handleUceGetDeviceEnabledCommand() {
2548 boolean result = false;
2549 try {
2550 result = mInterface.getDeviceUceEnabled();
2551 } catch (RemoteException e) {
2552 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2553 return -1;
2554 }
2555 if (VDBG) {
2556 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2557 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002558 getOutPrintWriter().println(result);
2559 return 0;
2560 }
2561
James.cf Lin4b784aa2021-01-31 03:25:15 +08002562 private int handleUceSetDeviceEnabledCommand() {
2563 String enabledStr = getNextArg();
2564 if (TextUtils.isEmpty(enabledStr)) {
2565 return -1;
2566 }
2567
2568 try {
2569 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2570 mInterface.setDeviceUceEnabled(isEnabled);
2571 if (VDBG) {
2572 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2573 }
2574 } catch (NumberFormatException | RemoteException e) {
2575 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2576 getErrPrintWriter().println("Exception: " + e.getMessage());
2577 return -1;
2578 }
2579 return 0;
2580 }
2581
James.cf Line8713a42021-04-29 16:04:26 +08002582 private int handleUceRemoveRequestDisallowedStatus() {
2583 int subId = getSubId("uce remove-request-disallowed-status");
2584 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2585 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2586 return -1;
2587 }
2588 boolean result;
2589 try {
2590 result = mInterface.removeUceRequestDisallowedStatus(subId);
2591 } catch (RemoteException e) {
2592 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2593 return -1;
2594 }
2595 if (VDBG) {
2596 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2597 }
2598 getOutPrintWriter().println(result);
2599 return 0;
2600 }
2601
James.cf Lin0fc71b02021-05-25 01:37:38 +08002602 private int handleUceSetCapRequestTimeout() {
2603 int subId = getSubId("uce set-capabilities-request-timeout");
2604 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2605 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2606 return -1;
2607 }
2608 long timeoutAfterMs = Long.valueOf(getNextArg());
2609 boolean result;
2610 try {
2611 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2612 } catch (RemoteException e) {
2613 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2614 return -1;
2615 }
2616 if (VDBG) {
2617 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2618 }
2619 getOutPrintWriter().println(result);
2620 return 0;
2621 }
2622
Hui Wangbaaee6a2021-02-19 20:45:36 -08002623 private int handleSrcSetTestEnabledCommand() {
2624 String enabledStr = getNextArg();
2625 if (enabledStr == null) {
2626 return -1;
2627 }
2628
2629 try {
2630 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2631 if (VDBG) {
2632 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2633 }
2634 getOutPrintWriter().println("Done");
2635 } catch (NumberFormatException | RemoteException e) {
2636 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2637 getErrPrintWriter().println("Exception: " + e.getMessage());
2638 return -1;
2639 }
2640 return 0;
2641 }
2642
2643 private int handleSrcGetTestEnabledCommand() {
2644 boolean result = false;
2645 try {
2646 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2647 } catch (RemoteException e) {
2648 return -1;
2649 }
2650 if (VDBG) {
2651 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2652 }
2653 getOutPrintWriter().println(result);
2654 return 0;
2655 }
2656
Brad Ebinger14d467f2021-02-12 06:18:28 +00002657 private int handleUceOverridePublishCaps() {
2658 int subId = getSubId("uce override-published-caps");
2659 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2660 return -1;
2661 }
2662 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2663 String operation = getNextArgRequired();
2664 String caps = getNextArg();
2665 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2666 && !"list".equals(operation)) {
2667 getErrPrintWriter().println("Invalid operation: " + operation);
2668 return -1;
2669 }
2670
2671 // add/remove requires capabilities to be specified.
2672 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2673 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2674 + "specified");
2675 return -1;
2676 }
2677
2678 ArraySet<String> capSet = new ArraySet<>();
2679 if (!TextUtils.isEmpty(caps)) {
2680 String[] capArray = caps.split(":");
2681 for (String cap : capArray) {
2682 // Allow unknown tags to be passed in as well.
2683 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2684 }
2685 }
2686
2687 RcsContactUceCapability result = null;
2688 try {
2689 switch (operation) {
2690 case "add":
2691 result = mInterface.addUceRegistrationOverrideShell(subId,
2692 new ArrayList<>(capSet));
2693 break;
2694 case "remove":
2695 result = mInterface.removeUceRegistrationOverrideShell(subId,
2696 new ArrayList<>(capSet));
2697 break;
2698 case "clear":
2699 result = mInterface.clearUceRegistrationOverrideShell(subId);
2700 break;
2701 case "list":
2702 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2703 break;
2704 }
2705 } catch (RemoteException e) {
2706 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2707 getErrPrintWriter().println("Exception: " + e.getMessage());
2708 return -1;
2709 } catch (ServiceSpecificException sse) {
2710 // Reconstruct ImsException
2711 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2712 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2713 getErrPrintWriter().println("Exception: " + imsException);
2714 return -1;
2715 }
2716 if (result == null) {
2717 getErrPrintWriter().println("Service not available");
2718 return -1;
2719 }
2720 getOutPrintWriter().println(result);
2721 return 0;
2722 }
2723
2724 private int handleUceGetPidfXml() {
2725 int subId = getSubId("uce get-last-publish-pidf");
2726 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2727 return -1;
2728 }
2729
2730 String result;
2731 try {
2732 result = mInterface.getLastUcePidfXmlShell(subId);
2733 } catch (RemoteException e) {
2734 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2735 getErrPrintWriter().println("Exception: " + e.getMessage());
2736 return -1;
2737 } catch (ServiceSpecificException sse) {
2738 // Reconstruct ImsException
2739 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2740 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2741 getErrPrintWriter().println("Exception: " + imsException);
2742 return -1;
2743 }
2744 if (result == null) {
2745 getErrPrintWriter().println("Service not available");
2746 return -1;
2747 }
2748 getOutPrintWriter().println(result);
2749 return 0;
2750 }
2751
Hui Wang761a6682020-10-31 05:12:53 +00002752 private int handleSrcSetDeviceEnabledCommand() {
2753 String enabledStr = getNextArg();
2754 if (enabledStr == null) {
2755 return -1;
2756 }
2757
2758 try {
2759 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2760 if (VDBG) {
2761 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2762 }
2763 getOutPrintWriter().println("Done");
2764 } catch (NumberFormatException | RemoteException e) {
2765 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2766 getErrPrintWriter().println("Exception: " + e.getMessage());
2767 return -1;
2768 }
2769 return 0;
2770 }
2771
2772 private int handleSrcGetDeviceEnabledCommand() {
2773 boolean result = false;
2774 try {
2775 result = mInterface.getDeviceSingleRegistrationEnabled();
2776 } catch (RemoteException e) {
2777 return -1;
2778 }
2779 if (VDBG) {
2780 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2781 }
2782 getOutPrintWriter().println(result);
2783 return 0;
2784 }
2785
2786 private int handleSrcSetCarrierEnabledCommand() {
2787 //the release time value could be -1
2788 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2789 : SubscriptionManager.getDefaultSubscriptionId();
2790 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2791 return -1;
2792 }
2793
2794 String enabledStr = getNextArg();
2795 if (enabledStr == null) {
2796 return -1;
2797 }
2798
2799 try {
2800 boolean result =
2801 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2802 if (VDBG) {
2803 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2804 + enabledStr + ", result=" + result);
2805 }
2806 getOutPrintWriter().println(result);
2807 } catch (NumberFormatException | RemoteException e) {
2808 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2809 + enabledStr + ", error" + e.getMessage());
2810 getErrPrintWriter().println("Exception: " + e.getMessage());
2811 return -1;
2812 }
2813 return 0;
2814 }
2815
2816 private int handleSrcGetCarrierEnabledCommand() {
2817 int subId = getSubId("src get-carrier-enabled");
2818 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2819 return -1;
2820 }
2821
2822 boolean result = false;
2823 try {
2824 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2825 } catch (RemoteException e) {
2826 return -1;
2827 }
2828 if (VDBG) {
2829 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2830 }
2831 getOutPrintWriter().println(result);
2832 return 0;
2833 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002834
Hui Wangb647abe2021-02-26 09:33:38 -08002835 private int handleSrcSetFeatureValidationCommand() {
2836 //the release time value could be -1
2837 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2838 : SubscriptionManager.getDefaultSubscriptionId();
2839 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2840 return -1;
2841 }
2842
2843 String enabledStr = getNextArg();
2844 if (enabledStr == null) {
2845 return -1;
2846 }
2847
2848 try {
2849 boolean result =
2850 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2851 if (VDBG) {
2852 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2853 + enabledStr + ", result=" + result);
2854 }
2855 getOutPrintWriter().println(result);
2856 } catch (NumberFormatException | RemoteException e) {
2857 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2858 + enabledStr + ", error" + e.getMessage());
2859 getErrPrintWriter().println("Exception: " + e.getMessage());
2860 return -1;
2861 }
2862 return 0;
2863 }
2864
2865 private int handleSrcGetFeatureValidationCommand() {
2866 int subId = getSubId("src get-feature-validation");
2867 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2868 return -1;
2869 }
2870
2871 Boolean result = false;
2872 try {
2873 result = mInterface.getImsFeatureValidationOverride(subId);
2874 } catch (RemoteException e) {
2875 return -1;
2876 }
2877 if (VDBG) {
2878 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2879 }
2880 getOutPrintWriter().println(result);
2881 return 0;
2882 }
2883
2884
Hall Liuaa4211e2021-01-20 15:43:39 -08002885 private void onHelpCallComposer() {
2886 PrintWriter pw = getOutPrintWriter();
2887 pw.println("Call composer commands");
2888 pw.println(" callcomposer test-mode enable|disable|query");
2889 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2890 pw.println(" upload/download from carrier servers is disabled, and operations are");
2891 pw.println(" performed using emulated local files instead.");
2892 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2893 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2894 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002895 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2896 pw.println(" Enables or disables the user setting for call composer, as set by");
2897 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002898 }
2899
2900 private int handleCallComposerCommand() {
2901 String arg = getNextArg();
2902 if (arg == null) {
2903 onHelpCallComposer();
2904 return 0;
2905 }
2906
2907 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2908 "MODIFY_PHONE_STATE required for call composer shell cmds");
2909 switch (arg) {
2910 case CALL_COMPOSER_TEST_MODE: {
2911 String enabledStr = getNextArg();
2912 if (ENABLE.equals(enabledStr)) {
2913 CallComposerPictureManager.sTestMode = true;
2914 } else if (DISABLE.equals(enabledStr)) {
2915 CallComposerPictureManager.sTestMode = false;
2916 } else if (QUERY.equals(enabledStr)) {
2917 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2918 } else {
2919 onHelpCallComposer();
2920 return 1;
2921 }
2922 break;
2923 }
2924 case CALL_COMPOSER_SIMULATE_CALL: {
2925 int subscriptionId = Integer.valueOf(getNextArg());
2926 String uuidString = getNextArg();
2927 UUID uuid = UUID.fromString(uuidString);
2928 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2929 Binder.withCleanCallingIdentity(() -> {
2930 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2931 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2932 });
2933 try {
2934 Uri uri = storageUriFuture.get();
2935 getOutPrintWriter().println(String.valueOf(uri));
2936 } catch (Exception e) {
2937 throw new RuntimeException(e);
2938 }
2939 break;
2940 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002941 case CALL_COMPOSER_USER_SETTING: {
2942 try {
2943 int subscriptionId = Integer.valueOf(getNextArg());
2944 String enabledStr = getNextArg();
2945 if (ENABLE.equals(enabledStr)) {
2946 mInterface.setCallComposerStatus(subscriptionId,
2947 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2948 } else if (DISABLE.equals(enabledStr)) {
2949 mInterface.setCallComposerStatus(subscriptionId,
2950 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2951 } else if (QUERY.equals(enabledStr)) {
2952 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2953 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2954 } else {
2955 onHelpCallComposer();
2956 return 1;
2957 }
2958 } catch (RemoteException e) {
2959 e.printStackTrace(getOutPrintWriter());
2960 return 1;
2961 }
2962 break;
2963 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002964 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002965 return 0;
2966 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002967
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002968 private int handleHasCarrierPrivilegesCommand() {
2969 String packageName = getNextArgRequired();
2970
2971 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002972 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002973 try {
2974 hasCarrierPrivileges =
2975 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2976 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2977 } catch (RemoteException e) {
2978 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2979 getErrPrintWriter().println("Exception: " + e.getMessage());
2980 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002981 } finally {
2982 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002983 }
2984
2985 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002986 return 0;
2987 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002988
2989 private int handleAllowedNetworkTypesCommand(String command) {
2990 if (!checkShellUid()) {
2991 return -1;
2992 }
2993
2994 PrintWriter errPw = getErrPrintWriter();
2995 String tag = command + ": ";
2996 String opt;
2997 int subId = -1;
2998 Log.v(LOG_TAG, command + " start");
2999
3000 while ((opt = getNextOption()) != null) {
3001 if (opt.equals("-s")) {
3002 try {
3003 subId = slotStringToSubId(tag, getNextArgRequired());
3004 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3005 errPw.println(tag + "No valid subscription found.");
3006 return -1;
3007 }
3008 } catch (IllegalArgumentException e) {
3009 // Missing slot id
3010 errPw.println(tag + "SLOT_ID expected after -s.");
3011 return -1;
3012 }
3013 } else {
3014 errPw.println(tag + "Unknown option " + opt);
3015 return -1;
3016 }
3017 }
3018
3019 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
3020 return handleGetAllowedNetworkTypesCommand(subId);
3021 }
3022 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
3023 return handleSetAllowedNetworkTypesCommand(subId);
3024 }
3025 return -1;
3026 }
3027
3028 private int handleGetAllowedNetworkTypesCommand(int subId) {
3029 PrintWriter errPw = getErrPrintWriter();
3030
3031 long result = -1;
3032 try {
3033 if (mInterface != null) {
3034 result = mInterface.getAllowedNetworkTypesForReason(subId,
3035 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
3036 } else {
3037 throw new IllegalStateException("telephony service is null.");
3038 }
3039 } catch (RemoteException e) {
3040 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
3041 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
3042 return -1;
3043 }
3044
3045 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
3046 return 0;
3047 }
3048
3049 private int handleSetAllowedNetworkTypesCommand(int subId) {
3050 PrintWriter errPw = getErrPrintWriter();
3051
3052 String bitmaskString = getNextArg();
3053 if (TextUtils.isEmpty(bitmaskString)) {
3054 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
3055 return -1;
3056 }
3057 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
3058 if (allowedNetworkTypes < 0) {
3059 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
3060 return -1;
3061 }
3062 boolean result = false;
3063 try {
3064 if (mInterface != null) {
3065 result = mInterface.setAllowedNetworkTypesForReason(subId,
3066 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
3067 } else {
3068 throw new IllegalStateException("telephony service is null.");
3069 }
3070 } catch (RemoteException e) {
3071 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
3072 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
3073 return -1;
3074 }
3075
3076 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
3077 if (result) {
3078 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3079 }
3080 getOutPrintWriter().println(resultMessage);
3081 return 0;
3082 }
3083
3084 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3085 if (TextUtils.isEmpty(bitmaskString)) {
3086 return -1;
3087 }
3088 if (VDBG) {
3089 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3090 + ", length: " + bitmaskString.length());
3091 }
3092 try {
3093 return Long.parseLong(bitmaskString, 2);
3094 } catch (NumberFormatException e) {
3095 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3096 return -1;
3097 }
3098 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003099
jimsun3b9ccac2021-10-26 15:01:23 +08003100 private int handleRadioSetModemServiceCommand() {
3101 PrintWriter errPw = getErrPrintWriter();
3102 String serviceName = null;
3103
3104 String opt;
3105 while ((opt = getNextOption()) != null) {
3106 switch (opt) {
3107 case "-s": {
3108 serviceName = getNextArgRequired();
3109 break;
3110 }
3111 }
3112 }
3113
3114 try {
3115 boolean result = mInterface.setModemService(serviceName);
3116 if (VDBG) {
3117 Log.v(LOG_TAG,
3118 "RadioSetModemService " + serviceName + ", result = " + result);
3119 }
3120 getOutPrintWriter().println(result);
3121 } catch (RemoteException e) {
3122 Log.w(LOG_TAG,
3123 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3124 errPw.println("Exception: " + e.getMessage());
3125 return -1;
3126 }
3127 return 0;
3128 }
3129
3130 private int handleRadioGetModemServiceCommand() {
3131 PrintWriter errPw = getErrPrintWriter();
3132 String result;
3133
3134 try {
3135 result = mInterface.getModemService();
3136 getOutPrintWriter().println(result);
3137 } catch (RemoteException e) {
3138 errPw.println("Exception: " + e.getMessage());
3139 return -1;
3140 }
3141 if (VDBG) {
3142 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3143 }
3144 return 0;
3145 }
3146
3147 private int handleRadioCommand() {
3148 String arg = getNextArg();
3149 if (arg == null) {
3150 onHelpRadio();
3151 return 0;
3152 }
3153
3154 switch (arg) {
3155 case RADIO_SET_MODEM_SERVICE:
3156 return handleRadioSetModemServiceCommand();
3157
3158 case RADIO_GET_MODEM_SERVICE:
3159 return handleRadioGetModemServiceCommand();
3160 }
3161
3162 return -1;
3163 }
arunvoddud7401012022-12-15 16:08:12 +00003164
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003165 private int handleSetSatelliteServicePackageNameCommand() {
3166 PrintWriter errPw = getErrPrintWriter();
3167 String serviceName = null;
3168
3169 String opt;
3170 while ((opt = getNextOption()) != null) {
3171 switch (opt) {
3172 case "-s": {
3173 serviceName = getNextArgRequired();
3174 break;
3175 }
3176 }
3177 }
3178 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3179 + serviceName);
3180
3181 try {
3182 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3183 if (VDBG) {
3184 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3185 + ", result = " + result);
3186 }
3187 getOutPrintWriter().println(result);
3188 } catch (RemoteException e) {
3189 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3190 + ", error = " + e.getMessage());
3191 errPw.println("Exception: " + e.getMessage());
3192 return -1;
3193 }
3194 return 0;
3195 }
3196
Thomas Nguyen1854a5a2023-04-04 09:31:47 -07003197 private int handleSetSatelliteGatewayServicePackageNameCommand() {
3198 PrintWriter errPw = getErrPrintWriter();
3199 String serviceName = null;
3200
3201 String opt;
3202 while ((opt = getNextOption()) != null) {
3203 switch (opt) {
3204 case "-s": {
3205 serviceName = getNextArgRequired();
3206 break;
3207 }
3208 }
3209 }
3210 Log.d(LOG_TAG, "handleSetSatelliteGatewayServicePackageNameCommand: serviceName="
3211 + serviceName);
3212
3213 try {
3214 boolean result = mInterface.setSatelliteGatewayServicePackageName(serviceName);
3215 if (VDBG) {
3216 Log.v(LOG_TAG, "setSatelliteGatewayServicePackageName " + serviceName
3217 + ", result = " + result);
3218 }
3219 getOutPrintWriter().println(result);
3220 } catch (RemoteException e) {
3221 Log.w(LOG_TAG, "setSatelliteGatewayServicePackageName: " + serviceName
3222 + ", error = " + e.getMessage());
3223 errPw.println("Exception: " + e.getMessage());
3224 return -1;
3225 }
3226 return 0;
3227 }
3228
Thomas Nguyen87dce732023-04-20 18:27:16 -07003229 private int handleSetSatellitePointingUiClassNameCommand() {
3230 PrintWriter errPw = getErrPrintWriter();
3231 String packageName = null;
3232 String className = null;
3233
3234 String opt;
3235 while ((opt = getNextOption()) != null) {
3236 switch (opt) {
3237 case "-p": {
3238 packageName = getNextArgRequired();
3239 break;
3240 }
3241 case "-c": {
3242 className = getNextArgRequired();
3243 break;
3244 }
3245 }
3246 }
3247 Log.d(LOG_TAG, "handleSetSatellitePointingUiClassNameCommand: packageName="
3248 + packageName + ", className=" + className);
3249
3250 try {
3251 boolean result = mInterface.setSatellitePointingUiClassName(packageName, className);
3252 if (VDBG) {
3253 Log.v(LOG_TAG, "setSatellitePointingUiClassName result =" + result);
3254 }
3255 getOutPrintWriter().println(result);
3256 } catch (RemoteException e) {
3257 Log.e(LOG_TAG, "setSatellitePointingUiClassName: " + packageName
3258 + ", error = " + e.getMessage());
3259 errPw.println("Exception: " + e.getMessage());
3260 return -1;
3261 }
3262 return 0;
3263 }
3264
Thomas Nguyen11a051f2023-10-25 10:14:55 -07003265 private int handleSetEmergencyCallToSatelliteHandoverType() {
3266 PrintWriter errPw = getErrPrintWriter();
3267 int handoverType = -1;
3268 int delaySeconds = 0;
3269
3270 String opt;
3271 while ((opt = getNextOption()) != null) {
3272 switch (opt) {
3273 case "-t": {
3274 try {
3275 handoverType = Integer.parseInt(getNextArgRequired());
3276 } catch (NumberFormatException e) {
3277 errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
3278 + " for handoverType");
3279 return -1;
3280 }
3281 break;
3282 }
3283 case "-d": {
3284 try {
3285 delaySeconds = Integer.parseInt(getNextArgRequired());
3286 } catch (NumberFormatException e) {
3287 errPw.println("SetEmergencyCallToSatelliteHandoverType: require an integer"
3288 + " for delaySeconds");
3289 return -1;
3290 }
3291 break;
3292 }
3293 }
3294 }
3295 Log.d(LOG_TAG, "handleSetEmergencyCallToSatelliteHandoverType: handoverType="
3296 + handoverType + ", delaySeconds=" + delaySeconds);
3297
3298 try {
3299 boolean result =
3300 mInterface.setEmergencyCallToSatelliteHandoverType(handoverType, delaySeconds);
3301 if (VDBG) {
3302 Log.v(LOG_TAG, "setEmergencyCallToSatelliteHandoverType result =" + result);
3303 }
3304 getOutPrintWriter().println(result);
3305 } catch (RemoteException e) {
3306 Log.e(LOG_TAG, "setEmergencyCallToSatelliteHandoverType: " + handoverType
3307 + ", error = " + e.getMessage());
3308 errPw.println("Exception: " + e.getMessage());
3309 return -1;
3310 }
3311 return 0;
3312 }
3313
Thomas Nguyenf9a533c2023-04-06 20:48:41 -07003314 private int handleSetSatelliteListeningTimeoutDuration() {
3315 PrintWriter errPw = getErrPrintWriter();
3316 long timeoutMillis = 0;
3317
3318 String opt;
3319 while ((opt = getNextOption()) != null) {
3320 switch (opt) {
3321 case "-t": {
3322 timeoutMillis = Long.parseLong(getNextArgRequired());
3323 break;
3324 }
3325 }
3326 }
3327 Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
3328 + timeoutMillis);
3329
3330 try {
3331 boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
3332 if (VDBG) {
3333 Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
3334 + ", result = " + result);
3335 }
3336 getOutPrintWriter().println(result);
3337 } catch (RemoteException e) {
3338 Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
3339 + ", error = " + e.getMessage());
3340 errPw.println("Exception: " + e.getMessage());
3341 return -1;
3342 }
3343 return 0;
3344 }
3345
Hakjun Choiae365972023-04-25 11:00:31 +00003346 private int handleSettSatelliteDeviceAlignedTimeoutDuration() {
3347 PrintWriter errPw = getErrPrintWriter();
3348 long timeoutMillis = 0;
3349
3350 String opt;
3351 while ((opt = getNextOption()) != null) {
3352 switch (opt) {
3353 case "-t": {
3354 timeoutMillis = Long.parseLong(getNextArgRequired());
3355 break;
3356 }
3357 }
3358 }
3359 Log.d(LOG_TAG, "handleSettSatelliteDeviceAlignedTimeoutDuration: timeoutMillis="
3360 + timeoutMillis);
3361
3362 try {
3363 boolean result = mInterface.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis);
3364 if (VDBG) {
3365 Log.v(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration " + timeoutMillis
3366 + ", result = " + result);
3367 }
3368 getOutPrintWriter().println(result);
3369 } catch (RemoteException e) {
3370 Log.w(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration: " + timeoutMillis
3371 + ", error = " + e.getMessage());
3372 errPw.println("Exception: " + e.getMessage());
3373 return -1;
3374 }
3375 return 0;
3376 }
3377
Hakjun Choibc6ce992023-11-07 16:04:33 +00003378 private int handleSetShouldSendDatagramToModemInDemoMode() {
3379 PrintWriter errPw = getErrPrintWriter();
3380 String opt;
3381 boolean shouldSendToDemoMode;
3382
3383 if ((opt = getNextArg()) == null) {
3384 errPw.println(
3385 "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
3386 + " Invalid Argument");
3387 return -1;
3388 } else {
3389 switch (opt) {
3390 case "true": {
3391 shouldSendToDemoMode = true;
3392 break;
3393 }
3394 case "false": {
3395 shouldSendToDemoMode = false;
3396 break;
3397 }
3398 default:
3399 errPw.println(
3400 "adb shell cmd phone set-should-send-datagram-to-modem-in-demo-mode :"
3401 + " Invalid Argument");
3402 return -1;
3403 }
3404 }
3405
3406 Log.d(LOG_TAG,
3407 "handleSetShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode + ")");
3408
3409 try {
3410 boolean result = mInterface.setShouldSendDatagramToModemInDemoMode(
3411 shouldSendToDemoMode);
3412 if (VDBG) {
3413 Log.v(LOG_TAG, "handleSetShouldSendDatagramToModemInDemoMode returns: "
3414 + result);
3415 }
3416 getOutPrintWriter().println(false);
3417 } catch (RemoteException e) {
3418 Log.w(LOG_TAG, "setShouldSendDatagramToModemInDemoMode(" + shouldSendToDemoMode
3419 + "), error = " + e.getMessage());
3420 errPw.println("Exception: " + e.getMessage());
3421 return -1;
3422 }
3423 return 0;
3424 }
3425
Thomas Nguyen4f9c89e2023-12-18 10:51:57 -08003426 private int handleSetSatelliteAccessControlOverlayConfigs() {
3427 PrintWriter errPw = getErrPrintWriter();
3428 boolean reset = false;
3429 boolean isAllowed = false;
3430 String s2CellFile = null;
3431 long locationFreshDurationNanos = 0;
3432 List<String> satelliteCountryCodes = null;
3433
3434 String opt;
3435 while ((opt = getNextOption()) != null) {
3436 switch (opt) {
3437 case "-r": {
3438 reset = true;
3439 break;
3440 }
3441 case "-a": {
3442 isAllowed = true;
3443 break;
3444 }
3445 case "-f": {
3446 s2CellFile = getNextArgRequired();
3447 break;
3448 }
3449 case "-d": {
3450 locationFreshDurationNanos = Long.parseLong(getNextArgRequired());
3451 break;
3452 }
3453 case "-c": {
3454 String countryCodeStr = getNextArgRequired();
3455 satelliteCountryCodes = Arrays.asList(countryCodeStr.split(","));
3456 break;
3457 }
3458 }
3459 }
3460 Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: reset=" + reset
3461 + ", isAllowed=" + isAllowed + ", s2CellFile=" + s2CellFile
3462 + ", locationFreshDurationNanos=" + locationFreshDurationNanos
3463 + ", satelliteCountryCodes=" + satelliteCountryCodes);
3464
3465 try {
3466 boolean result = mInterface.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
3467 s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
3468 if (VDBG) {
3469 Log.v(LOG_TAG, "setSatelliteAccessControlOverlayConfigs result =" + result);
3470 }
3471 getOutPrintWriter().println(result);
3472 } catch (RemoteException e) {
3473 Log.e(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: ex=" + e.getMessage());
3474 errPw.println("Exception: " + e.getMessage());
3475 return -1;
3476 }
3477 return 0;
3478 }
3479
3480 private int handleSetCountryCodes() {
3481 PrintWriter errPw = getErrPrintWriter();
3482 List<String> currentNetworkCountryCodes = new ArrayList<>();
3483 String locationCountryCode = null;
3484 long locationCountryCodeTimestampNanos = 0;
3485 Map<String, Long> cachedNetworkCountryCodes = new HashMap<>();
3486 boolean reset = false;
3487
3488 String opt;
3489 while ((opt = getNextOption()) != null) {
3490 switch (opt) {
3491 case "-r": {
3492 reset = true;
3493 break;
3494 }
3495 case "-n": {
3496 String countryCodeStr = getNextArgRequired();
3497 currentNetworkCountryCodes = Arrays.asList(countryCodeStr.split(","));
3498 break;
3499 }
3500 case "-c": {
3501 String cachedNetworkCountryCodeStr = getNextArgRequired();
3502 cachedNetworkCountryCodes = parseStringLongMap(cachedNetworkCountryCodeStr);
3503 break;
3504 }
3505 case "-l": {
3506 locationCountryCode = getNextArgRequired();
3507 break;
3508 }
3509 case "-t": {
3510 locationCountryCodeTimestampNanos = Long.parseLong(getNextArgRequired());
3511 break;
3512 }
3513 }
3514 }
3515 Log.d(LOG_TAG, "setCountryCodes: locationCountryCode="
3516 + locationCountryCode + ", locationCountryCodeTimestampNanos="
3517 + locationCountryCodeTimestampNanos + ", currentNetworkCountryCodes="
3518 + currentNetworkCountryCodes);
3519
3520 try {
3521 boolean result = mInterface.setCountryCodes(reset, currentNetworkCountryCodes,
3522 cachedNetworkCountryCodes, locationCountryCode,
3523 locationCountryCodeTimestampNanos);
3524 if (VDBG) {
3525 Log.v(LOG_TAG, "setCountryCodes result =" + result);
3526 }
3527 getOutPrintWriter().println(result);
3528 } catch (RemoteException e) {
3529 Log.e(LOG_TAG, "setCountryCodes: ex=" + e.getMessage());
3530 errPw.println("Exception: " + e.getMessage());
3531 return -1;
3532 }
3533 return 0;
3534 }
3535
3536 /**
3537 * Sample inputStr = "US,UK,CA;2,1,3"
3538 * Sample output: {[US,2], [UK,1], [CA,3]}
3539 */
3540 @NonNull private Map<String, Long> parseStringLongMap(@Nullable String inputStr) {
3541 Map<String, Long> result = new HashMap<>();
3542 if (!TextUtils.isEmpty(inputStr)) {
3543 String[] stringLongArr = inputStr.split(";");
3544 if (stringLongArr.length != 2) {
3545 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
3546 return result;
3547 }
3548
3549 String[] stringArr = stringLongArr[0].split(",");
3550 String[] longArr = stringLongArr[1].split(",");
3551 if (stringArr.length != longArr.length) {
3552 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
3553 return result;
3554 }
3555
3556 for (int i = 0; i < stringArr.length; i++) {
3557 try {
3558 result.put(stringArr[i], Long.parseLong(longArr[i]));
3559 } catch (Exception ex) {
3560 Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr
3561 + ", ex=" + ex);
3562 return result;
3563 }
3564 }
3565 }
3566 return result;
3567 }
3568
arunvoddud7401012022-12-15 16:08:12 +00003569 private int handleCarrierRestrictionStatusCommand() {
3570 try {
3571 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3572 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3573 mInterface.getModemService()))) {
3574 Log.v(LOG_TAG,
3575 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3576 + " checkShellUid fails");
3577 return -1;
3578 }
3579 } catch (RemoteException ex) {
3580 ex.printStackTrace();
3581 }
3582 String callerInfo = getNextOption();
3583 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3584 if (TextUtils.isEmpty(callerInfo)) {
3585 // reset the Json content after testing
3586 allowListInfo.updateJsonForTest(null);
3587 return 0;
3588 }
3589 if (callerInfo.startsWith("--")) {
3590 callerInfo = callerInfo.replace("--", "");
3591 }
3592 String params[] = callerInfo.split(",");
3593 StringBuffer jsonStrBuffer = new StringBuffer();
3594 String tokens;
3595 for (int index = 0; index < params.length; index++) {
3596 tokens = convertToJsonString(index, params[index]);
3597 if (TextUtils.isEmpty(tokens)) {
3598 // received wrong format from CTS
3599 if (VDBG) {
3600 Log.v(LOG_TAG,
3601 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3602 }
3603 return -1;
3604 }
3605 jsonStrBuffer.append(tokens);
3606 }
3607 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3608 return result;
3609 }
3610
Benedict Wong66477622023-02-03 23:30:57 +00003611 // set-carrier-service-package-override
3612 private int setCarrierServicePackageOverride() {
3613 PrintWriter errPw = getErrPrintWriter();
3614 int subId = SubscriptionManager.getDefaultSubscriptionId();
3615
3616 String opt;
3617 while ((opt = getNextOption()) != null) {
3618 switch (opt) {
3619 case "-s":
3620 try {
3621 subId = Integer.parseInt(getNextArgRequired());
3622 } catch (NumberFormatException e) {
3623 errPw.println(
3624 "set-carrier-service-package-override requires an integer as a"
3625 + " subscription ID.");
3626 return -1;
3627 }
3628 break;
3629 }
3630 }
3631
3632 String packageName = getNextArg();
3633 if (packageName == null) {
3634 errPw.println("set-carrier-service-package-override requires a override package name.");
3635 return -1;
3636 }
3637
3638 try {
3639 mInterface.setCarrierServicePackageOverride(
3640 subId, packageName, mContext.getOpPackageName());
3641
3642 if (VDBG) {
3643 Log.v(
3644 LOG_TAG,
3645 "set-carrier-service-package-override -s " + subId + " " + packageName);
3646 }
3647 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3648 Log.w(
3649 LOG_TAG,
3650 "set-carrier-service-package-override -s "
3651 + subId
3652 + " "
3653 + packageName
3654 + ", error"
3655 + e.getMessage());
3656 errPw.println("Exception: " + e.getMessage());
3657 return -1;
3658 }
3659 return 0;
3660 }
3661
3662 // clear-carrier-service-package-override
3663 private int clearCarrierServicePackageOverride() {
3664 PrintWriter errPw = getErrPrintWriter();
Chalard Jean71706f42023-09-22 18:22:47 +09003665 int subId = SubscriptionManager.getDefaultSubscriptionId();
Benedict Wong66477622023-02-03 23:30:57 +00003666
3667 String opt;
3668 while ((opt = getNextOption()) != null) {
3669 switch (opt) {
3670 case "-s":
3671 try {
3672 subId = Integer.parseInt(getNextArgRequired());
3673 } catch (NumberFormatException e) {
3674 errPw.println(
3675 "clear-carrier-service-package-override requires an integer as a"
3676 + " subscription ID.");
3677 return -1;
3678 }
3679 break;
3680 }
3681 }
3682
3683 try {
3684 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3685
3686 if (VDBG) {
3687 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3688 }
3689 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3690 Log.w(
3691 LOG_TAG,
3692 "clear-carrier-service-package-override -s "
3693 + subId
3694 + ", error"
3695 + e.getMessage());
3696 errPw.println("Exception: " + e.getMessage());
3697 return -1;
3698 }
3699 return 0;
3700 }
arunvoddud7401012022-12-15 16:08:12 +00003701
3702 /**
3703 * Building the string that can be used to build the JsonObject which supports to stub the data
3704 * in CarrierAllowListInfo for CTS testing. sample format is like
3705 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3706 */
3707 private String convertToJsonString(int index, String param) {
3708
3709 String token[] = param.split(":");
3710 String jSonString;
3711 switch (index) {
3712 case 0:
3713 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3714 break;
3715 case 1:
3716 jSonString =
3717 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3718 break;
3719 case 2:
3720 jSonString =
3721 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3722 break;
3723 default:
3724 jSonString = null;
3725 }
3726 return jSonString;
3727 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003728}