blob: b4448401070a2690a7ca0d7160882e2f2900d1de [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Cole Faustc16d5292022-10-15 21:33:27 -070024import static java.util.Map.entry;
25
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010027import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080028import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080031import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000033import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070034import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070035import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010036import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070037import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000039import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070040import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080041import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000042import android.telephony.ims.ImsException;
43import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080044import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080045import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000046import android.util.ArrayMap;
47import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070049import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050
Brad Ebinger14d467f2021-02-12 06:18:28 +000051import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080053import com.android.internal.telephony.Phone;
54import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080055import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080056import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080057import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080058import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080059import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000060import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000061import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070062
Allen Xuee00f0e2022-03-14 21:04:49 +000063import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080065import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Arrays;
67import java.util.Collections;
Brad Ebinger24c29992019-12-05 13:03:21 -080068import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000069import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010070import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000071import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080073import java.util.UUID;
74import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070075
76/**
77 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
78 * permission checks have been done before onCommand was called. Make sure any commands processed
79 * here also contain the appropriate permissions checks.
80 */
81
Hall Liua1548bd2019-12-24 14:14:12 -080082public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
84 private static final String LOG_TAG = "TelephonyShellCommand";
85 // Don't commit with this true.
86 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070087 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070088
Hall Liuaa4211e2021-01-20 15:43:39 -080089 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070090 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080091 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080092 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080093 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070094 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000095 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000096 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010097 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080098 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String ENABLE = "enable";
100 private static final String DISABLE = "disable";
101 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000102 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000103 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
104 "set-carrier-service-package-override";
105 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
106 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000107 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800108
Hall Liu7135e502021-02-04 16:58:17 -0800109 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800110 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800111 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Brad Ebinger999d3302020-11-25 14:31:39 -0800113 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
114 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
115 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700116 // Used to disable or enable processing of conference event package data from the network.
117 // This is handy for testing scenarios where CEP data does not exist on a network which does
118 // support CEP data.
119 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700120
Hall Liud892bec2018-11-30 14:51:45 -0800121 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800122 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800123
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100124 private static final String CC_GET_VALUE = "get-value";
125 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000126 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private static final String CC_CLEAR_VALUES = "clear-values";
128
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000129 private static final String EUICC_SUBCOMMAND = "euicc";
130 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
131
Hui Wang641e81c2020-10-12 12:14:23 -0700132 private static final String GBA_SUBCOMMAND = "gba";
133 private static final String GBA_SET_SERVICE = "set-service";
134 private static final String GBA_GET_SERVICE = "get-service";
135 private static final String GBA_SET_RELEASE_TIME = "set-release";
136 private static final String GBA_GET_RELEASE_TIME = "get-release";
137
Hui Wang761a6682020-10-31 05:12:53 +0000138 private static final String SINGLE_REGISTATION_CONFIG = "src";
139 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
140 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
141 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
142 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800143 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
144 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800145 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
146 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000147
Tyler Gunn92479152021-01-20 16:30:10 -0800148 private static final String D2D_SUBCOMMAND = "d2d";
149 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800150 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700151 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800152
Nazanin014f41e2021-05-06 17:26:31 -0700153 private static final String BARRING_SUBCOMMAND = "barring";
154 private static final String BARRING_SEND_INFO = "send";
155
James.cf Linbcdf8b32021-01-14 16:44:13 +0800156 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800157 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800158 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800159 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800160 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
161 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000162 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
163 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800164 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
165 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800166 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
167 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800168
jimsun3b9ccac2021-10-26 15:01:23 +0800169 private static final String RADIO_SUBCOMMAND = "radio";
170 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
171 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
172
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800173 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
174 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
175
Jordan Liu0ccee222021-04-27 11:55:13 -0700176 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
177 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
178
Jack Nudelman644b91a2021-03-12 14:09:48 -0800179 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
180 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
181 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700182 private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
183 "set-satellite-service-package-name";
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700184 private static final String SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME =
185 "set-satellite-gateway-service-package-name";
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700186 private static final String SET_SATELLITE_LISTENING_TIMEOUT_DURATION =
187 "set-satellite-listening-timeout-duration";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800188
Grant Menke567d48f2022-08-18 20:19:10 +0000189 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
190 + "'*', '#' or '+') needs to be specified after -a in the command ";
191
192 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
193 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
194 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
195
SongFerngWang98dd5992021-05-13 17:50:00 +0800196 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
197 "get-allowed-network-types-for-users";
198 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
199 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000200 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000201 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700202 // Take advantage of existing methods that already contain permissions checks when possible.
203 private final ITelephony mInterface;
204
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100205 private SubscriptionManager mSubscriptionManager;
206 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700207 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700208 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100209
210 private enum CcType {
211 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000212 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100213 }
214
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100215 private class CcOptionParseResult {
216 public int mSubId;
217 public boolean mPersistent;
218 }
219
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100220 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
221 // keys by looking at the end of the string which usually tells the type.
222 // For instance: "xxxx_string", "xxxx_string_array", etc.
223 // The carrier config keys in this map does not follow this convention. It is therefore not
224 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700225 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
226 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
227 CcType.STRING),
228 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
229 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
230 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
231 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
232 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
233 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
234 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
235 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
236 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
237 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
238 CcType.STRING),
239 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
240 CcType.STRING_ARRAY),
241 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
242 CcType.STRING_ARRAY),
243 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
244 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
245 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
246 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
247 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
248 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
249 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
250 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100251
Brad Ebinger14d467f2021-02-12 06:18:28 +0000252 /**
253 * Map from a shorthand string to the feature tags required in registration required in order
254 * for the RCS feature to be considered "capable".
255 */
256 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
257 static {
258 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
259 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
260 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
261 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
262 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
263 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
264 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
265 FeatureTags.FEATURE_TAG_VIDEO)));
266 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
267 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
268 map.put("call_comp",
269 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
270 map.put("call_comp_mmtel",
271 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
272 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
273 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
274 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
275 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
276 // version
277 map.put("chatbot", new ArraySet<>(Arrays.asList(
278 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
279 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
280 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
281 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000282 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000283 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
284 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
285 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
286 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
287 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000288 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000289 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
290 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
291 }
292
293
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100294 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700295 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100296 mCarrierConfigManager =
297 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
298 mSubscriptionManager = (SubscriptionManager)
299 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700300 mTelephonyRegistryManager = (TelephonyRegistryManager)
301 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700302 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700303 }
304
305 @Override
306 public int onCommand(String cmd) {
307 if (cmd == null) {
308 return handleDefaultCommands(null);
309 }
310
311 switch (cmd) {
312 case IMS_SUBCOMMAND: {
313 return handleImsCommand();
314 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800315 case RCS_UCE_COMMAND:
316 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800317 case NUMBER_VERIFICATION_SUBCOMMAND:
318 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800319 case EMERGENCY_CALLBACK_MODE:
320 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800321 case EMERGENCY_NUMBER_TEST_MODE:
322 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100323 case CARRIER_CONFIG_SUBCOMMAND: {
324 return handleCcCommand();
325 }
Shuo Qianf5125122019-12-16 17:03:07 -0800326 case DATA_TEST_MODE:
327 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700328 case END_BLOCK_SUPPRESSION:
329 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000330 case EUICC_SUBCOMMAND:
331 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700332 case GBA_SUBCOMMAND:
333 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800334 case D2D_SUBCOMMAND:
335 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700336 case BARRING_SUBCOMMAND:
337 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000338 case SINGLE_REGISTATION_CONFIG:
339 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000340 case RESTART_MODEM:
341 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800342 case CALL_COMPOSER_SUBCOMMAND:
343 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000344 case UNATTENDED_REBOOT:
345 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800346 case HAS_CARRIER_PRIVILEGES_COMMAND:
347 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800348 case THERMAL_MITIGATION_COMMAND:
349 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700350 case DISABLE_PHYSICAL_SUBSCRIPTION:
351 return handleEnablePhysicalSubscription(false);
352 case ENABLE_PHYSICAL_SUBSCRIPTION:
353 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800354 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
355 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
356 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000357 case GET_IMEI:
358 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000359 case GET_SIM_SLOTS_MAPPING:
360 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800361 case RADIO_SUBCOMMAND:
362 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000363 case CARRIER_RESTRICTION_STATUS_TEST:
364 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000365 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
366 return setCarrierServicePackageOverride();
367 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
368 return clearCarrierServicePackageOverride();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700369 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
370 return handleSetSatelliteServicePackageNameCommand();
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700371 case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
372 return handleSetSatelliteGatewayServicePackageNameCommand();
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700373 case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
374 return handleSetSatelliteListeningTimeoutDuration();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700375 default: {
376 return handleDefaultCommands(cmd);
377 }
378 }
379 }
380
381 @Override
382 public void onHelp() {
383 PrintWriter pw = getOutPrintWriter();
384 pw.println("Telephony Commands:");
385 pw.println(" help");
386 pw.println(" Print this help text.");
387 pw.println(" ims");
388 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800389 pw.println(" uce");
390 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800391 pw.println(" emergency-number-test-mode");
392 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700393 pw.println(" end-block-suppression");
394 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800395 pw.println(" data");
396 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100397 pw.println(" cc");
398 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700399 pw.println(" gba");
400 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000401 pw.println(" src");
402 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000403 pw.println(" restart-modem");
404 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000405 pw.println(" unattended-reboot");
406 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800407 pw.println(" has-carrier-privileges [package]");
408 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800409 pw.println(" get-allowed-network-types-for-users");
410 pw.println(" Get the Allowed Network Types.");
411 pw.println(" set-allowed-network-types-for-users");
412 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800413 pw.println(" radio");
414 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700415 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800416 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800417 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700418 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800419 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100420 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700421 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000422 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800423 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700424 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800425 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800426 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000427 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700428 onHelpSatellite();
Tyler Gunn92479152021-01-20 16:30:10 -0800429 }
430
431 private void onHelpD2D() {
432 PrintWriter pw = getOutPrintWriter();
433 pw.println("D2D Comms Commands:");
434 pw.println(" d2d send TYPE VALUE");
435 pw.println(" Sends a D2D message of specified type and value.");
436 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
437 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
438 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
439 MESSAGE_CALL_AUDIO_CODEC));
440 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
441 + Communicator.messageToString(
442 MESSAGE_DEVICE_BATTERY_STATE));
443 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
444 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800445 pw.println(" d2d transport TYPE");
446 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
447 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700448 pw.println(" d2d set-device-support true/default");
449 pw.println(" true - forces device support to be enabled for D2D.");
450 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
451 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700452 }
453
Nazanin014f41e2021-05-06 17:26:31 -0700454 private void onHelpBarring() {
455 PrintWriter pw = getOutPrintWriter();
456 pw.println("Barring Commands:");
457 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
458 + " -t CONDITIONAL_BARRING_TIME_SECS");
459 pw.println(" Notifies of a barring info change for the specified slot id.");
460 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
461 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
462 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
463 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
464 }
465
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700466 private void onHelpIms() {
467 PrintWriter pw = getOutPrintWriter();
468 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800469 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700470 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
471 pw.println(" ImsService. Options are:");
472 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
473 pw.println(" is specified, it will choose the default voice SIM slot.");
474 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
475 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800476 pw.println(" -f: Set the feature that this override if for, if no option is");
477 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700478 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
479 pw.println(" Gets the package name of the currently defined ImsService.");
480 pw.println(" Options are:");
481 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
482 pw.println(" is specified, it will choose the default voice SIM slot.");
483 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000484 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800485 pw.println(" -f: The feature type that the query will be requested for. If none is");
486 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800487 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
488 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
489 pw.println(" configuration overrides. Options are:");
490 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
491 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700492 pw.println(" ims enable [-s SLOT_ID]");
493 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
494 pw.println(" if none is specified.");
495 pw.println(" ims disable [-s SLOT_ID]");
496 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
497 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700498 pw.println(" ims conference-event-package [enable/disable]");
499 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700500 }
501
James.cf Linbcdf8b32021-01-14 16:44:13 +0800502 private void onHelpUce() {
503 PrintWriter pw = getOutPrintWriter();
504 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800505 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
506 pw.println(" Get the EAB contacts from the EAB database.");
507 pw.println(" Options are:");
508 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
509 pw.println(" Expected output format :");
510 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800511 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
512 pw.println(" Remove the EAB contacts from the EAB database.");
513 pw.println(" Options are:");
514 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
515 pw.println(" is specified, it will choose the default voice SIM slot.");
516 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800517 pw.println(" uce get-device-enabled");
518 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
519 pw.println(" uce set-device-enabled true|false");
520 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
521 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000522 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
523 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
524 pw.println(" Options are:");
525 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
526 pw.println(" is specified, it will choose the default voice SIM slot.");
527 pw.println(" add [CAPABILITY]: add a new capability");
528 pw.println(" remove [CAPABILITY]: remove a capability");
529 pw.println(" clear: clear all capability overrides");
530 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
531 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
532 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
533 pw.println(" chatbot_sa, chatbot_role] as well as full length");
534 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
535 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
536 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
537 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800538 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
539 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800540 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
541 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800542 }
543
Hall Liud892bec2018-11-30 14:51:45 -0800544 private void onHelpNumberVerification() {
545 PrintWriter pw = getOutPrintWriter();
546 pw.println("Number verification commands");
547 pw.println(" numverify override-package PACKAGE_NAME;");
548 pw.println(" Set the authorized package for number verification.");
549 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800550 pw.println(" numverify fake-call NUMBER;");
551 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
552 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800553 }
554
Jack Nudelman644b91a2021-03-12 14:09:48 -0800555 private void onHelpThermalMitigation() {
556 PrintWriter pw = getOutPrintWriter();
557 pw.println("Thermal mitigation commands");
558 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
559 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
560 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
561 pw.println(" Remove the package from one of the authorized packages for thermal "
562 + "mitigation.");
563 }
564
Jordan Liu0ccee222021-04-27 11:55:13 -0700565 private void onHelpDisableOrEnablePhysicalSubscription() {
566 PrintWriter pw = getOutPrintWriter();
567 pw.println("Disable or enable a physical subscription");
568 pw.println(" disable-physical-subscription SUB_ID");
569 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
570 pw.println(" enable-physical-subscription SUB_ID");
571 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
572 }
573
Shuo Qianf5125122019-12-16 17:03:07 -0800574 private void onHelpDataTestMode() {
575 PrintWriter pw = getOutPrintWriter();
576 pw.println("Mobile Data Test Mode Commands:");
577 pw.println(" data enable: enable mobile data connectivity");
578 pw.println(" data disable: disable mobile data connectivity");
579 }
580
sqian9d4df8b2019-01-15 18:32:07 -0800581 private void onHelpEmergencyNumber() {
582 PrintWriter pw = getOutPrintWriter();
583 pw.println("Emergency Number Test Mode Commands:");
584 pw.println(" emergency-number-test-mode ");
585 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
586 + " the test mode");
587 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700588 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800589 pw.println(" -c: clear the emergency number list in the test mode.");
590 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700591 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800592 pw.println(" -p: get the full emergency number list in the test mode.");
593 }
594
Shuo Qian489d9282020-07-09 11:30:03 -0700595 private void onHelpEndBlockSupperssion() {
596 PrintWriter pw = getOutPrintWriter();
597 pw.println("End Block Suppression command:");
598 pw.println(" end-block-suppression: disable suppressing blocking by contact");
599 pw.println(" with emergency services.");
600 }
601
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100602 private void onHelpCc() {
603 PrintWriter pw = getOutPrintWriter();
604 pw.println("Carrier Config Commands:");
605 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
606 pw.println(" Print carrier config values.");
607 pw.println(" Options are:");
608 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
609 pw.println(" is specified, it will choose the default voice SIM slot.");
610 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
611 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100612 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100613 pw.println(" Set carrier config KEY to NEW_VALUE.");
614 pw.println(" Options are:");
615 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
616 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100617 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100618 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
619 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
620 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
621 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000622 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
623 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
624 pw.println(" provided through standard input and follow CarrierConfig XML format.");
625 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
626 pw.println(" Options are:");
627 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
628 pw.println(" is specified, it will choose the default voice SIM slot.");
629 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100630 pw.println(" cc clear-values [-s SLOT_ID]");
631 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000632 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100633 pw.println(" Options are:");
634 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
635 pw.println(" is specified, it will choose the default voice SIM slot.");
636 }
637
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000638 private void onHelpEuicc() {
639 PrintWriter pw = getOutPrintWriter();
640 pw.println("Euicc Commands:");
641 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
642 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
643 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
644 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
645 }
646
Hui Wang641e81c2020-10-12 12:14:23 -0700647 private void onHelpGba() {
648 PrintWriter pw = getOutPrintWriter();
649 pw.println("Gba Commands:");
650 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
651 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
652 pw.println(" Options are:");
653 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
654 pw.println(" is specified, it will choose the default voice SIM slot.");
655 pw.println(" gba get-service [-s SLOT_ID]");
656 pw.println(" Gets the package name of the currently defined GbaService.");
657 pw.println(" Options are:");
658 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
659 pw.println(" is specified, it will choose the default voice SIM slot.");
660 pw.println(" gba set-release [-s SLOT_ID] n");
661 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
662 pw.println(" Do not release/unbind if n is -1.");
663 pw.println(" Options are:");
664 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
665 pw.println(" is specified, it will choose the default voice SIM slot.");
666 pw.println(" gba get-release [-s SLOT_ID]");
667 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
668 pw.println(" Options are:");
669 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
670 pw.println(" is specified, it will choose the default voice SIM slot.");
671 }
672
Hui Wang761a6682020-10-31 05:12:53 +0000673 private void onHelpSrc() {
674 PrintWriter pw = getOutPrintWriter();
675 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800676 pw.println(" src set-test-enabled true|false");
677 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
678 pw.println(" The value could be true, false, or null(undefined).");
679 pw.println(" src get-test-enabled");
680 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000681 pw.println(" src set-device-enabled true|false|null");
682 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
683 pw.println(" The value could be true, false, or null(undefined).");
684 pw.println(" src get-device-enabled");
685 pw.println(" Gets the device config for RCS VoLTE single registration.");
686 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
687 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
688 pw.println(" The value could be true, false, or null(undefined).");
689 pw.println(" Options are:");
690 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
691 pw.println(" is specified, it will choose the default voice SIM slot.");
692 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
693 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
694 pw.println(" Options are:");
695 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
696 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800697 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
698 pw.println(" Sets ims feature validation result.");
699 pw.println(" The value could be true, false, or null(undefined).");
700 pw.println(" Options are:");
701 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
702 pw.println(" is specified, it will choose the default voice SIM slot.");
703 pw.println(" src get-feature-validation [-s SLOT_ID]");
704 pw.println(" Gets ims feature validation override value.");
705 pw.println(" Options are:");
706 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
707 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000708 }
709
SongFerngWang98dd5992021-05-13 17:50:00 +0800710 private void onHelpAllowedNetworkTypes() {
711 PrintWriter pw = getOutPrintWriter();
712 pw.println("Allowed Network Types Commands:");
713 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
714 pw.println(" Print allowed network types value.");
715 pw.println(" Options are:");
716 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
717 pw.println(" option is specified, it will choose the default voice SIM slot.");
718 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
719 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
720 pw.println(" Options are:");
721 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
722 pw.println(" option is specified, it will choose the default voice SIM slot.");
723 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
724 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
725 pw.println(" at TelephonyManager.java");
726 pw.println(" For example:");
727 pw.println(" NR only : 10000000000000000000");
728 pw.println(" NR|LTE : 11000001000000000000");
729 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
730 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
731 pw.println(" LTE only : 01000001000000000000");
732 }
733
jimsun3b9ccac2021-10-26 15:01:23 +0800734 private void onHelpRadio() {
735 PrintWriter pw = getOutPrintWriter();
736 pw.println("Radio Commands:");
737 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
738 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
739 pw.println(" to be the bound. Options are:");
740 pw.println(" -s: the service name that the modem service should be bound for.");
741 pw.println(" If no option is specified, it will bind to the default.");
742 pw.println(" radio get-modem-service");
743 pw.println(" Gets the service name of the currently defined modem service.");
744 pw.println(" If it is binding to default, 'default' returns.");
745 pw.println(" If it doesn't bind to any modem service for some reasons,");
746 pw.println(" the result would be 'unknown'.");
747 }
748
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700749 private void onHelpSatellite() {
750 PrintWriter pw = getOutPrintWriter();
751 pw.println("Satellite Commands:");
752 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
753 pw.println(" Sets the package name of satellite service defined in");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700754 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700755 pw.println(" -s: the satellite service package name that Telephony will bind to.");
756 pw.println(" If no option is specified, it will bind to the default.");
Thomas Nguyen1854a5a2023-04-04 09:31:47 -0700757 pw.println(" set-satellite-gateway-service-package-name [-s SERVICE_PACKAGE_NAME]");
758 pw.println(" Sets the package name of satellite gateway service defined in");
759 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
760 pw.println(" -s: the satellite gateway service package name that Telephony will bind");
761 pw.println(" to. If no option is specified, it will bind to the default.");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700762 pw.println(" set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
763 pw.println(" Sets the timeout duration in millis that satellite will stay at listening");
764 pw.println(" mode. Options are:");
765 pw.println(" -t: the timeout duration in milliseconds.");
766 pw.println(" If no option is specified, it will use the default values.");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700767 }
768
Ling Ma4fbab492022-01-25 22:36:16 +0000769 private void onHelpImei() {
770 PrintWriter pw = getOutPrintWriter();
771 pw.println("IMEI Commands:");
772 pw.println(" get-imei [-s SLOT_ID]");
773 pw.println(" Gets the device IMEI. Options are:");
774 pw.println(" -s: the slot ID to get the IMEI. If no option");
775 pw.println(" is specified, it will choose the default voice SIM slot.");
776 }
777
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700778 private int handleImsCommand() {
779 String arg = getNextArg();
780 if (arg == null) {
781 onHelpIms();
782 return 0;
783 }
784
785 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800786 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700787 return handleImsSetServiceCommand();
788 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800789 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700790 return handleImsGetServiceCommand();
791 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800792 case IMS_CLEAR_SERVICE_OVERRIDE: {
793 return handleImsClearCarrierServiceCommand();
794 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800795 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700796 return handleEnableIms();
797 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800798 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700799 return handleDisableIms();
800 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700801 case IMS_CEP: {
802 return handleCepChange();
803 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700804 }
805
806 return -1;
807 }
808
Shuo Qianf5125122019-12-16 17:03:07 -0800809 private int handleDataTestModeCommand() {
810 PrintWriter errPw = getErrPrintWriter();
811 String arg = getNextArgRequired();
812 if (arg == null) {
813 onHelpDataTestMode();
814 return 0;
815 }
816 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800817 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800818 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700819 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800820 } catch (RemoteException ex) {
821 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
822 errPw.println("Exception: " + ex.getMessage());
823 return -1;
824 }
825 break;
826 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800827 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800828 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700829 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800830 } catch (RemoteException ex) {
831 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
832 errPw.println("Exception: " + ex.getMessage());
833 return -1;
834 }
835 break;
836 }
837 default:
838 onHelpDataTestMode();
839 break;
840 }
841 return 0;
842 }
843
Shuo Qianccbaf742021-02-22 18:32:21 -0800844 private int handleEmergencyCallbackModeCommand() {
845 PrintWriter errPw = getErrPrintWriter();
846 try {
847 mInterface.startEmergencyCallbackMode();
848 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
849 } catch (RemoteException ex) {
850 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
851 errPw.println("Exception: " + ex.getMessage());
852 return -1;
853 }
854 return 0;
855 }
856
Grant Menke567d48f2022-08-18 20:19:10 +0000857 private void removeEmergencyNumberTestMode(String emergencyNumber) {
858 PrintWriter errPw = getErrPrintWriter();
859 for (int routingType : ROUTING_TYPES) {
860 try {
861 mInterface.updateEmergencyNumberListTestMode(
862 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
863 new EmergencyNumber(emergencyNumber, "", "",
864 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
865 new ArrayList<String>(),
866 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
867 routingType));
868 } catch (RemoteException ex) {
869 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
870 errPw.println("Exception: " + ex.getMessage());
871 }
872 }
873 }
874
sqian9d4df8b2019-01-15 18:32:07 -0800875 private int handleEmergencyNumberTestModeCommand() {
876 PrintWriter errPw = getErrPrintWriter();
877 String opt = getNextOption();
878 if (opt == null) {
879 onHelpEmergencyNumber();
880 return 0;
881 }
sqian9d4df8b2019-01-15 18:32:07 -0800882 switch (opt) {
883 case "-a": {
884 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000885 if (emergencyNumberCmd == null){
886 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800887 return -1;
888 }
Grant Menke567d48f2022-08-18 20:19:10 +0000889 String[] params = emergencyNumberCmd.split(":");
890 String emergencyNumber;
891 if (params[0] == null ||
892 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
893 errPw.println(INVALID_ENTRY_ERROR);
894 return -1;
895 } else {
896 emergencyNumber = params[0];
897 }
898 removeEmergencyNumberTestMode(emergencyNumber);
899 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
900 if (params.length > 1) {
901 switch (params[1].toLowerCase(Locale.ROOT)) {
902 case "emergency":
903 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
904 break;
905 case "normal":
906 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
907 break;
908 case "unknown":
909 break;
910 default:
911 errPw.println("\"" + params[1] + "\" is not a valid specification for "
912 + "emergency call routing. Please enter either \"normal\", "
913 + "\"unknown\", or \"emergency\" for call routing. "
914 + "(-a 1234:normal)");
915 return -1;
916 }
917 }
sqian9d4df8b2019-01-15 18:32:07 -0800918 try {
919 mInterface.updateEmergencyNumberListTestMode(
920 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000921 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800922 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
923 new ArrayList<String>(),
924 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000925 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800926 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000927 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800928 + ", error " + ex.getMessage());
929 errPw.println("Exception: " + ex.getMessage());
930 return -1;
931 }
932 break;
933 }
934 case "-c": {
935 try {
936 mInterface.updateEmergencyNumberListTestMode(
937 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
938 } catch (RemoteException ex) {
939 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
940 errPw.println("Exception: " + ex.getMessage());
941 return -1;
942 }
943 break;
944 }
945 case "-r": {
946 String emergencyNumberCmd = getNextArgRequired();
947 if (emergencyNumberCmd == null
948 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700949 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800950 + " to be specified after -r in the command ");
951 return -1;
952 }
Grant Menke567d48f2022-08-18 20:19:10 +0000953 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800954 break;
955 }
956 case "-p": {
957 try {
958 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
959 } catch (RemoteException ex) {
960 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
961 errPw.println("Exception: " + ex.getMessage());
962 return -1;
963 }
964 break;
965 }
966 default:
967 onHelpEmergencyNumber();
968 break;
969 }
970 return 0;
971 }
972
Hall Liud892bec2018-11-30 14:51:45 -0800973 private int handleNumberVerificationCommand() {
974 String arg = getNextArg();
975 if (arg == null) {
976 onHelpNumberVerification();
977 return 0;
978 }
979
Hall Liuca5af3a2018-12-04 16:58:23 -0800980 if (!checkShellUid()) {
981 return -1;
982 }
983
Hall Liud892bec2018-11-30 14:51:45 -0800984 switch (arg) {
985 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800986 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
987 return 0;
988 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800989 case NUMBER_VERIFICATION_FAKE_CALL: {
990 boolean val = NumberVerificationManager.getInstance()
991 .checkIncomingCall(getNextArg());
992 getOutPrintWriter().println(val ? "1" : "0");
993 return 0;
994 }
Hall Liud892bec2018-11-30 14:51:45 -0800995 }
996
997 return -1;
998 }
999
Jordan Liu0ccee222021-04-27 11:55:13 -07001000 private boolean subIsEsim(int subId) {
1001 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
1002 if (info != null) {
1003 return info.isEmbedded();
1004 }
1005 return false;
1006 }
1007
1008 private int handleEnablePhysicalSubscription(boolean enable) {
1009 PrintWriter errPw = getErrPrintWriter();
1010 int subId = 0;
1011 try {
1012 subId = Integer.parseInt(getNextArgRequired());
1013 } catch (NumberFormatException e) {
1014 errPw.println((enable ? "enable" : "disable")
1015 + "-physical-subscription requires an integer as a subId.");
1016 return -1;
1017 }
1018 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1019 // non user build.
1020 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1021 errPw.println("cc: Permission denied.");
1022 return -1;
1023 }
1024 // Verify that the subId represents a physical sub
1025 if (subIsEsim(subId)) {
1026 errPw.println("SubId " + subId + " is not for a physical subscription");
1027 return -1;
1028 }
1029 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1030 + " physical subscription with subId=" + subId);
1031 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1032 return 0;
1033 }
1034
Jack Nudelman644b91a2021-03-12 14:09:48 -08001035 private int handleThermalMitigationCommand() {
1036 String arg = getNextArg();
1037 String packageName = getNextArg();
1038 if (arg == null || packageName == null) {
1039 onHelpThermalMitigation();
1040 return 0;
1041 }
1042
1043 if (!checkShellUid()) {
1044 return -1;
1045 }
1046
1047 switch (arg) {
1048 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1049 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1050 return 0;
1051 }
1052 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1053 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1054 mContext);
1055 return 0;
1056 }
1057 default:
1058 onHelpThermalMitigation();
1059 }
1060
1061 return -1;
1062
1063 }
1064
Tyler Gunn92479152021-01-20 16:30:10 -08001065 private int handleD2dCommand() {
1066 String arg = getNextArg();
1067 if (arg == null) {
1068 onHelpD2D();
1069 return 0;
1070 }
1071
1072 switch (arg) {
1073 case D2D_SEND: {
1074 return handleD2dSendCommand();
1075 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001076 case D2D_TRANSPORT: {
1077 return handleD2dTransportCommand();
1078 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001079 case D2D_SET_DEVICE_SUPPORT: {
1080 return handleD2dDeviceSupportedCommand();
1081 }
Tyler Gunn92479152021-01-20 16:30:10 -08001082 }
1083
1084 return -1;
1085 }
1086
1087 private int handleD2dSendCommand() {
1088 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001089 int messageType = -1;
1090 int messageValue = -1;
1091
Tyler Gunn92479152021-01-20 16:30:10 -08001092 String arg = getNextArg();
1093 if (arg == null) {
1094 onHelpD2D();
1095 return 0;
1096 }
1097 try {
1098 messageType = Integer.parseInt(arg);
1099 } catch (NumberFormatException e) {
1100 errPw.println("message type must be a valid integer");
1101 return -1;
1102 }
1103
1104 arg = getNextArg();
1105 if (arg == null) {
1106 onHelpD2D();
1107 return 0;
1108 }
1109 try {
1110 messageValue = Integer.parseInt(arg);
1111 } catch (NumberFormatException e) {
1112 errPw.println("message value must be a valid integer");
1113 return -1;
1114 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001115
Tyler Gunn92479152021-01-20 16:30:10 -08001116 try {
1117 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1118 } catch (RemoteException e) {
1119 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1120 errPw.println("Exception: " + e.getMessage());
1121 return -1;
1122 }
1123
1124 return 0;
1125 }
1126
Tyler Gunnbabbda02021-02-10 11:05:02 -08001127 private int handleD2dTransportCommand() {
1128 PrintWriter errPw = getErrPrintWriter();
1129
1130 String arg = getNextArg();
1131 if (arg == null) {
1132 onHelpD2D();
1133 return 0;
1134 }
1135
1136 try {
1137 mInterface.setActiveDeviceToDeviceTransport(arg);
1138 } catch (RemoteException e) {
1139 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1140 errPw.println("Exception: " + e.getMessage());
1141 return -1;
1142 }
1143 return 0;
1144 }
Nazanin014f41e2021-05-06 17:26:31 -07001145 private int handleBarringCommand() {
1146 String arg = getNextArg();
1147 if (arg == null) {
1148 onHelpBarring();
1149 return 0;
1150 }
1151
1152 switch (arg) {
1153 case BARRING_SEND_INFO: {
1154 return handleBarringSendCommand();
1155 }
1156 }
1157 return -1;
1158 }
1159
1160 private int handleBarringSendCommand() {
1161 PrintWriter errPw = getErrPrintWriter();
1162 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001163 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001164 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1165 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1166 boolean isConditionallyBarred = false;
1167 int conditionalBarringTimeSeconds = 0;
1168
1169 String opt;
1170 while ((opt = getNextOption()) != null) {
1171 switch (opt) {
1172 case "-s": {
1173 try {
1174 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001175 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001176 } catch (NumberFormatException e) {
1177 errPw.println("barring send requires an integer as a SLOT_ID.");
1178 return -1;
1179 }
1180 break;
1181 }
1182 case "-b": {
1183 try {
1184 barringType = Integer.parseInt(getNextArgRequired());
1185 if (barringType < -1 || barringType > 2) {
1186 throw new NumberFormatException();
1187 }
1188
1189 } catch (NumberFormatException e) {
1190 errPw.println("barring send requires an integer in range [-1,2] as "
1191 + "a BARRING_TYPE.");
1192 return -1;
1193 }
1194 break;
1195 }
1196 case "-c": {
1197 try {
1198 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1199 } catch (Exception e) {
1200 errPw.println("barring send requires a boolean after -c indicating"
1201 + " conditional barring");
1202 return -1;
1203 }
1204 break;
1205 }
1206 case "-t": {
1207 try {
1208 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1209 } catch (NumberFormatException e) {
1210 errPw.println("barring send requires an integer for time of barring"
1211 + " in seconds after -t for conditional barring");
1212 return -1;
1213 }
1214 break;
1215 }
1216 }
1217 }
1218 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1219 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1220 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1221 barringServiceInfos.append(0, bsi);
1222 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1223 try {
1224 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1225 } catch (Exception e) {
1226 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1227 errPw.println("Exception: " + e.getMessage());
1228 return -1;
1229 }
1230 return 0;
1231 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001232
Tyler Gunnd4575212021-05-03 14:46:49 -07001233 private int handleD2dDeviceSupportedCommand() {
1234 PrintWriter errPw = getErrPrintWriter();
1235
1236 String arg = getNextArg();
1237 if (arg == null) {
1238 onHelpD2D();
1239 return 0;
1240 }
1241
Jack Yua533d632022-09-30 13:53:46 -07001242 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001243 try {
1244 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1245 } catch (RemoteException e) {
1246 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1247 errPw.println("Exception: " + e.getMessage());
1248 return -1;
1249 }
1250 return 0;
1251 }
1252
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001253 // ims set-ims-service
1254 private int handleImsSetServiceCommand() {
1255 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001256 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001257 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001258 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001259
1260 String opt;
1261 while ((opt = getNextOption()) != null) {
1262 switch (opt) {
1263 case "-s": {
1264 try {
1265 slotId = Integer.parseInt(getNextArgRequired());
1266 } catch (NumberFormatException e) {
1267 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1268 return -1;
1269 }
1270 break;
1271 }
1272 case "-c": {
1273 isCarrierService = true;
1274 break;
1275 }
1276 case "-d": {
1277 isCarrierService = false;
1278 break;
1279 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001280 case "-f": {
1281 String featureString = getNextArgRequired();
1282 String[] features = featureString.split(",");
1283 for (int i = 0; i < features.length; i++) {
1284 try {
1285 Integer result = Integer.parseInt(features[i]);
1286 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1287 || result >= ImsFeature.FEATURE_MAX) {
1288 errPw.println("ims set-ims-service -f " + result
1289 + " is an invalid feature.");
1290 return -1;
1291 }
1292 featuresList.add(result);
1293 } catch (NumberFormatException e) {
1294 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1295 + " as an integer.");
1296 return -1;
1297 }
1298 }
1299 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001300 }
1301 }
1302 // Mandatory param, either -c or -d
1303 if (isCarrierService == null) {
1304 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1305 return -1;
1306 }
1307
1308 String packageName = getNextArg();
1309
1310 try {
1311 if (packageName == null) {
1312 packageName = "";
1313 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001314 int[] featureArray = new int[featuresList.size()];
1315 for (int i = 0; i < featuresList.size(); i++) {
1316 featureArray[i] = featuresList.get(i);
1317 }
1318 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1319 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001320 if (VDBG) {
1321 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001322 + (isCarrierService ? "-c " : "-d ")
1323 + "-f " + featuresList + " "
1324 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001325 }
1326 getOutPrintWriter().println(result);
1327 } catch (RemoteException e) {
1328 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001329 + (isCarrierService ? "-c " : "-d ")
1330 + "-f " + featuresList + " "
1331 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001332 errPw.println("Exception: " + e.getMessage());
1333 return -1;
1334 }
1335 return 0;
1336 }
1337
Brad Ebinger999d3302020-11-25 14:31:39 -08001338 // ims clear-ims-service-override
1339 private int handleImsClearCarrierServiceCommand() {
1340 PrintWriter errPw = getErrPrintWriter();
1341 int slotId = getDefaultSlot();
1342
1343 String opt;
1344 while ((opt = getNextOption()) != null) {
1345 switch (opt) {
1346 case "-s": {
1347 try {
1348 slotId = Integer.parseInt(getNextArgRequired());
1349 } catch (NumberFormatException e) {
1350 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1351 return -1;
1352 }
1353 break;
1354 }
1355 }
1356 }
1357
1358 try {
1359 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1360 if (VDBG) {
1361 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1362 + ", result=" + result);
1363 }
1364 getOutPrintWriter().println(result);
1365 } catch (RemoteException e) {
1366 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1367 + ", error" + e.getMessage());
1368 errPw.println("Exception: " + e.getMessage());
1369 return -1;
1370 }
1371 return 0;
1372 }
1373
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001374 // ims get-ims-service
1375 private int handleImsGetServiceCommand() {
1376 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001377 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001378 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001379 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001380
1381 String opt;
1382 while ((opt = getNextOption()) != null) {
1383 switch (opt) {
1384 case "-s": {
1385 try {
1386 slotId = Integer.parseInt(getNextArgRequired());
1387 } catch (NumberFormatException e) {
1388 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1389 return -1;
1390 }
1391 break;
1392 }
1393 case "-c": {
1394 isCarrierService = true;
1395 break;
1396 }
1397 case "-d": {
1398 isCarrierService = false;
1399 break;
1400 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001401 case "-f": {
1402 try {
1403 featureType = Integer.parseInt(getNextArg());
1404 } catch (NumberFormatException e) {
1405 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1406 return -1;
1407 }
1408 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1409 || featureType >= ImsFeature.FEATURE_MAX) {
1410 errPw.println("ims get-ims-service -f invalid feature.");
1411 return -1;
1412 }
1413 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001414 }
1415 }
1416 // Mandatory param, either -c or -d
1417 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001418 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001419 return -1;
1420 }
1421
1422 String result;
1423 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001424 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001425 } catch (RemoteException e) {
1426 return -1;
1427 }
1428 if (VDBG) {
1429 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001430 + (isCarrierService ? "-c " : "-d ")
1431 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1432 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001433 }
1434 getOutPrintWriter().println(result);
1435 return 0;
1436 }
1437
1438 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001439 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001440 String opt;
1441 while ((opt = getNextOption()) != null) {
1442 switch (opt) {
1443 case "-s": {
1444 try {
1445 slotId = Integer.parseInt(getNextArgRequired());
1446 } catch (NumberFormatException e) {
1447 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1448 return -1;
1449 }
1450 break;
1451 }
1452 }
1453 }
1454 try {
1455 mInterface.enableIms(slotId);
1456 } catch (RemoteException e) {
1457 return -1;
1458 }
1459 if (VDBG) {
1460 Log.v(LOG_TAG, "ims enable -s " + slotId);
1461 }
1462 return 0;
1463 }
1464
1465 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001466 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001467 String opt;
1468 while ((opt = getNextOption()) != null) {
1469 switch (opt) {
1470 case "-s": {
1471 try {
1472 slotId = Integer.parseInt(getNextArgRequired());
1473 } catch (NumberFormatException e) {
1474 getErrPrintWriter().println(
1475 "ims disable requires an integer as a SLOT_ID.");
1476 return -1;
1477 }
1478 break;
1479 }
1480 }
1481 }
1482 try {
1483 mInterface.disableIms(slotId);
1484 } catch (RemoteException e) {
1485 return -1;
1486 }
1487 if (VDBG) {
1488 Log.v(LOG_TAG, "ims disable -s " + slotId);
1489 }
1490 return 0;
1491 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001492
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001493 private int handleCepChange() {
1494 Log.i(LOG_TAG, "handleCepChange");
1495 String opt = getNextArg();
1496 if (opt == null) {
1497 return -1;
1498 }
1499 boolean isCepEnabled = opt.equals("enable");
1500
1501 try {
1502 mInterface.setCepEnabled(isCepEnabled);
1503 } catch (RemoteException e) {
1504 return -1;
1505 }
1506 return 0;
1507 }
1508
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001509 private int getDefaultSlot() {
1510 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1511 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1512 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1513 // If there is no default, default to slot 0.
1514 slotId = DEFAULT_PHONE_ID;
1515 }
1516 return slotId;
1517 }
sqian2fff4a32018-11-05 14:18:37 -08001518
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001519 // Parse options related to Carrier Config Commands.
1520 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001521 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001522 CcOptionParseResult result = new CcOptionParseResult();
1523 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1524 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001525
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001526 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001527 while ((opt = getNextOption()) != null) {
1528 switch (opt) {
1529 case "-s": {
1530 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001531 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1532 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1533 errPw.println(tag + "No valid subscription found.");
1534 return null;
1535 }
1536
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001537 } catch (IllegalArgumentException e) {
1538 // Missing slot id
1539 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001540 return null;
1541 }
1542 break;
1543 }
1544 case "-p": {
1545 if (allowOptionPersistent) {
1546 result.mPersistent = true;
1547 } else {
1548 errPw.println(tag + "Unexpected option " + opt);
1549 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001550 }
1551 break;
1552 }
1553 default: {
1554 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001555 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001556 }
1557 }
1558 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001559 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001560 }
1561
1562 private int slotStringToSubId(String tag, String slotString) {
1563 int slotId = -1;
1564 try {
1565 slotId = Integer.parseInt(slotString);
1566 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001567 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1568 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1569 }
1570
1571 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001572 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1573 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1574 }
1575
Qiong Liuf25799b2020-09-10 10:13:46 +08001576 Phone phone = PhoneFactory.getPhone(slotId);
1577 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001578 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1579 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1580 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001581 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001582 }
1583
Hall Liud892bec2018-11-30 14:51:45 -08001584 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001585 // adb can run as root or as shell, depending on whether the device is rooted.
1586 return Binder.getCallingUid() == Process.SHELL_UID
1587 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001588 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001589
1590 private int handleCcCommand() {
1591 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1592 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001593 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001594 getErrPrintWriter().println("cc: Permission denied.");
1595 return -1;
1596 }
1597
1598 String arg = getNextArg();
1599 if (arg == null) {
1600 onHelpCc();
1601 return 0;
1602 }
1603
1604 switch (arg) {
1605 case CC_GET_VALUE: {
1606 return handleCcGetValue();
1607 }
1608 case CC_SET_VALUE: {
1609 return handleCcSetValue();
1610 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001611 case CC_SET_VALUES_FROM_XML: {
1612 return handleCcSetValuesFromXml();
1613 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001614 case CC_CLEAR_VALUES: {
1615 return handleCcClearValues();
1616 }
1617 default: {
1618 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1619 }
1620 }
1621 return -1;
1622 }
1623
1624 // cc get-value
1625 private int handleCcGetValue() {
1626 PrintWriter errPw = getErrPrintWriter();
1627 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1628 String key = null;
1629
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001630 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001631 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001632 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001633 return -1;
1634 }
1635
1636 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001637 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001638 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001639 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001640 return -1;
1641 }
1642
1643 // Get the key.
1644 key = getNextArg();
1645 if (key != null) {
1646 // A key was provided. Verify if it is a valid key
1647 if (!bundle.containsKey(key)) {
1648 errPw.println(tag + key + " is not a valid key.");
1649 return -1;
1650 }
1651
1652 // Print the carrier config value for key.
1653 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1654 } else {
1655 // No key provided. Show all values.
1656 // Iterate over a sorted list of all carrier config keys and print them.
1657 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1658 for (String k : sortedSet) {
1659 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1660 }
1661 }
1662 return 0;
1663 }
1664
1665 // cc set-value
1666 private int handleCcSetValue() {
1667 PrintWriter errPw = getErrPrintWriter();
1668 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1669
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001670 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001671 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001672 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001673 return -1;
1674 }
1675
1676 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001677 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001678 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001679 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001680 return -1;
1681 }
1682
1683 // Get the key.
1684 String key = getNextArg();
1685 if (key == null || key.equals("")) {
1686 errPw.println(tag + "KEY is missing");
1687 return -1;
1688 }
1689
1690 // Verify if the key is valid
1691 if (!originalValues.containsKey(key)) {
1692 errPw.println(tag + key + " is not a valid key.");
1693 return -1;
1694 }
1695
1696 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1697 ArrayList<String> valueList = new ArrayList<String>();
1698 while (peekNextArg() != null) {
1699 valueList.add(getNextArg());
1700 }
1701
1702 // Find the type of the carrier config value
1703 CcType type = getType(tag, key, originalValues);
1704 if (type == CcType.UNKNOWN) {
1705 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1706 return -1;
1707 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001708 if (type == CcType.PERSISTABLE_BUNDLE) {
1709 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1710 + "Use set-values-from-xml instead.");
1711 return -1;
1712 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001713
1714 // Create an override bundle containing the key and value that should be overriden.
1715 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1716 if (overrideBundle == null) {
1717 return -1;
1718 }
1719
1720 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001721 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001722
1723 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001724 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001725 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001726 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001727 return -1;
1728 }
1729
1730 // Print the original and new value.
1731 String originalValueString = ccValueToString(key, type, originalValues);
1732 String newValueString = ccValueToString(key, type, newValues);
1733 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1734 getOutPrintWriter().println("New value: \n" + newValueString);
1735
1736 return 0;
1737 }
1738
Allen Xuee00f0e2022-03-14 21:04:49 +00001739 // cc set-values-from-xml
1740 private int handleCcSetValuesFromXml() {
1741 PrintWriter errPw = getErrPrintWriter();
1742 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1743
1744 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001745 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001746 if (options == null) {
1747 return -1;
1748 }
1749
1750 // Get bundle containing all current carrier configuration values.
1751 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1752 if (originalValues == null) {
1753 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1754 return -1;
1755 }
1756
1757 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1758 if (overrideBundle == null) {
1759 return -1;
1760 }
1761
1762 // Verify all values are valid types
1763 for (String key : overrideBundle.keySet()) {
1764 CcType type = getType(tag, key, originalValues);
1765 if (type == CcType.UNKNOWN) {
1766 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1767 return -1;
1768 }
1769 }
1770
1771 // Override the value
1772 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1773
1774 // Find bundle containing all new carrier configuration values after the override.
1775 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1776 if (newValues == null) {
1777 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1778 return -1;
1779 }
1780
1781 // Print the original and new values
1782 overrideBundle.keySet().forEach(key -> {
1783 CcType type = getType(tag, key, originalValues);
1784 String originalValueString = ccValueToString(key, type, originalValues);
1785 String newValueString = ccValueToString(key, type, newValues);
1786 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1787 getOutPrintWriter().println("New value: \n" + newValueString);
1788 });
1789
1790 return 0;
1791 }
1792
1793 private PersistableBundle readPersistableBundleFromXml(String tag) {
1794 PersistableBundle subIdBundles;
1795 try {
1796 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1797 } catch (IOException | RuntimeException e) {
1798 PrintWriter errPw = getErrPrintWriter();
1799 errPw.println(tag + e);
1800 return null;
1801 }
1802
1803 return subIdBundles;
1804 }
1805
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001806 // cc clear-values
1807 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001808 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1809
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001810 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001811 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001812 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001813 return -1;
1814 }
1815
1816 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001817 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001818 getOutPrintWriter()
1819 .println("All previously set carrier config override values has been cleared");
1820 return 0;
1821 }
1822
1823 private CcType getType(String tag, String key, PersistableBundle bundle) {
1824 // Find the type by checking the type of the current value stored in the bundle.
1825 Object value = bundle.get(key);
1826
1827 if (CC_TYPE_MAP.containsKey(key)) {
1828 return CC_TYPE_MAP.get(key);
1829 } else if (value != null) {
1830 if (value instanceof Boolean) {
1831 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001832 }
1833 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001834 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001835 }
1836 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001837 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001838 }
1839 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001840 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001841 }
1842 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001843 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001844 }
1845 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001846 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001847 }
1848 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001849 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001850 }
1851 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001852 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001853 }
1854 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001855 return CcType.STRING_ARRAY;
1856 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001857 if (value instanceof PersistableBundle) {
1858 return CcType.PERSISTABLE_BUNDLE;
1859 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001860 } else {
1861 // Current value was null and can therefore not be used in order to find the type.
1862 // Check the name of the key to infer the type. This check is not needed for primitive
1863 // data types (boolean, double, int and long), since they can not be null.
1864 if (key.endsWith("double_array")) {
1865 return CcType.DOUBLE_ARRAY;
1866 }
1867 if (key.endsWith("int_array")) {
1868 return CcType.INT_ARRAY;
1869 }
1870 if (key.endsWith("long_array")) {
1871 return CcType.LONG_ARRAY;
1872 }
1873 if (key.endsWith("string")) {
1874 return CcType.STRING;
1875 }
1876 if (key.endsWith("string_array") || key.endsWith("strings")) {
1877 return CcType.STRING_ARRAY;
1878 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001879 if (key.endsWith("bundle")) {
1880 return CcType.PERSISTABLE_BUNDLE;
1881 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001882 }
1883
1884 // Not possible to infer the type by looking at the current value or the key.
1885 PrintWriter errPw = getErrPrintWriter();
1886 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1887 return CcType.UNKNOWN;
1888 }
1889
1890 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1891 String result;
1892 StringBuilder valueString = new StringBuilder();
1893 String typeString = type.toString();
1894 Object value = bundle.get(key);
1895
1896 if (value == null) {
1897 valueString.append("null");
1898 } else {
1899 switch (type) {
1900 case DOUBLE_ARRAY: {
1901 // Format the string representation of the int array as value1 value2......
1902 double[] valueArray = (double[]) value;
1903 for (int i = 0; i < valueArray.length; i++) {
1904 if (i != 0) {
1905 valueString.append(" ");
1906 }
1907 valueString.append(valueArray[i]);
1908 }
1909 break;
1910 }
1911 case INT_ARRAY: {
1912 // Format the string representation of the int array as value1 value2......
1913 int[] valueArray = (int[]) value;
1914 for (int i = 0; i < valueArray.length; i++) {
1915 if (i != 0) {
1916 valueString.append(" ");
1917 }
1918 valueString.append(valueArray[i]);
1919 }
1920 break;
1921 }
1922 case LONG_ARRAY: {
1923 // Format the string representation of the int array as value1 value2......
1924 long[] valueArray = (long[]) value;
1925 for (int i = 0; i < valueArray.length; i++) {
1926 if (i != 0) {
1927 valueString.append(" ");
1928 }
1929 valueString.append(valueArray[i]);
1930 }
1931 break;
1932 }
1933 case STRING: {
1934 valueString.append("\"" + value.toString() + "\"");
1935 break;
1936 }
1937 case STRING_ARRAY: {
1938 // Format the string representation of the string array as "value1" "value2"....
1939 String[] valueArray = (String[]) value;
1940 for (int i = 0; i < valueArray.length; i++) {
1941 if (i != 0) {
1942 valueString.append(" ");
1943 }
1944 if (valueArray[i] != null) {
1945 valueString.append("\"" + valueArray[i] + "\"");
1946 } else {
1947 valueString.append("null");
1948 }
1949 }
1950 break;
1951 }
1952 default: {
1953 valueString.append(value.toString());
1954 }
1955 }
1956 }
1957 return String.format("%-70s %-15s %s", key, typeString, valueString);
1958 }
1959
1960 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1961 ArrayList<String> valueList) {
1962 PrintWriter errPw = getErrPrintWriter();
1963 PersistableBundle bundle = new PersistableBundle();
1964
1965 // First verify that a valid number of values has been provided for the type.
1966 switch (type) {
1967 case BOOLEAN:
1968 case DOUBLE:
1969 case INT:
1970 case LONG: {
1971 if (valueList.size() != 1) {
1972 errPw.println(tag + "Expected 1 value for type " + type
1973 + ". Found: " + valueList.size());
1974 return null;
1975 }
1976 break;
1977 }
1978 case STRING: {
1979 if (valueList.size() > 1) {
1980 errPw.println(tag + "Expected 0 or 1 values for type " + type
1981 + ". Found: " + valueList.size());
1982 return null;
1983 }
1984 break;
1985 }
1986 }
1987
1988 // Parse the value according to type and add it to the Bundle.
1989 switch (type) {
1990 case BOOLEAN: {
1991 if ("true".equalsIgnoreCase(valueList.get(0))) {
1992 bundle.putBoolean(key, true);
1993 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1994 bundle.putBoolean(key, false);
1995 } else {
1996 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1997 return null;
1998 }
1999 break;
2000 }
2001 case DOUBLE: {
2002 try {
2003 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
2004 } catch (NumberFormatException nfe) {
2005 // Not a valid double
2006 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2007 return null;
2008 }
2009 break;
2010 }
2011 case DOUBLE_ARRAY: {
2012 double[] valueDoubleArray = null;
2013 if (valueList.size() > 0) {
2014 valueDoubleArray = new double[valueList.size()];
2015 for (int i = 0; i < valueList.size(); i++) {
2016 try {
2017 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2018 } catch (NumberFormatException nfe) {
2019 // Not a valid double
2020 errPw.println(
2021 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2022 return null;
2023 }
2024 }
2025 }
2026 bundle.putDoubleArray(key, valueDoubleArray);
2027 break;
2028 }
2029 case INT: {
2030 try {
2031 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2032 } catch (NumberFormatException nfe) {
2033 // Not a valid integer
2034 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2035 return null;
2036 }
2037 break;
2038 }
2039 case INT_ARRAY: {
2040 int[] valueIntArray = null;
2041 if (valueList.size() > 0) {
2042 valueIntArray = new int[valueList.size()];
2043 for (int i = 0; i < valueList.size(); i++) {
2044 try {
2045 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2046 } catch (NumberFormatException nfe) {
2047 // Not a valid integer
2048 errPw.println(tag
2049 + "Unable to parse " + valueList.get(i) + " as an integer.");
2050 return null;
2051 }
2052 }
2053 }
2054 bundle.putIntArray(key, valueIntArray);
2055 break;
2056 }
2057 case LONG: {
2058 try {
2059 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2060 } catch (NumberFormatException nfe) {
2061 // Not a valid long
2062 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2063 return null;
2064 }
2065 break;
2066 }
2067 case LONG_ARRAY: {
2068 long[] valueLongArray = null;
2069 if (valueList.size() > 0) {
2070 valueLongArray = new long[valueList.size()];
2071 for (int i = 0; i < valueList.size(); i++) {
2072 try {
2073 valueLongArray[i] = Long.parseLong(valueList.get(i));
2074 } catch (NumberFormatException nfe) {
2075 // Not a valid long
2076 errPw.println(
2077 tag + "Unable to parse " + valueList.get(i) + " as a long");
2078 return null;
2079 }
2080 }
2081 }
2082 bundle.putLongArray(key, valueLongArray);
2083 break;
2084 }
2085 case STRING: {
2086 String value = null;
2087 if (valueList.size() > 0) {
2088 value = valueList.get(0);
2089 }
2090 bundle.putString(key, value);
2091 break;
2092 }
2093 case STRING_ARRAY: {
2094 String[] valueStringArray = null;
2095 if (valueList.size() > 0) {
2096 valueStringArray = new String[valueList.size()];
2097 valueList.toArray(valueStringArray);
2098 }
2099 bundle.putStringArray(key, valueStringArray);
2100 break;
2101 }
2102 }
2103 return bundle;
2104 }
Shuo Qian489d9282020-07-09 11:30:03 -07002105
2106 private int handleEndBlockSuppressionCommand() {
2107 if (!checkShellUid()) {
2108 return -1;
2109 }
2110
2111 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2112 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2113 }
2114 return 0;
2115 }
Hui Wang641e81c2020-10-12 12:14:23 -07002116
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002117 private int handleEuiccCommand() {
2118 String arg = getNextArg();
2119 if (arg == null) {
2120 onHelpEuicc();
2121 return 0;
2122 }
2123
2124 switch (arg) {
2125 case EUICC_SET_UI_COMPONENT: {
2126 return handleEuiccServiceCommand();
2127 }
2128 }
2129 return -1;
2130 }
2131
2132 private int handleEuiccServiceCommand() {
2133 String uiComponent = getNextArg();
2134 String packageName = getNextArg();
2135 if (packageName == null || uiComponent == null) {
2136 return -1;
2137 }
2138 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2139 if (VDBG) {
2140 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2141 + packageName);
2142 }
2143 return 0;
2144 }
2145
Michele Berionne54af4632020-12-28 20:23:16 +00002146 private int handleRestartModemCommand() {
2147 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2148 // non user build.
2149 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2150 getErrPrintWriter().println("RestartModem: Permission denied.");
2151 return -1;
2152 }
2153
2154 boolean result = TelephonyManager.getDefault().rebootRadio();
2155 getOutPrintWriter().println(result);
2156
2157 return result ? 0 : -1;
2158 }
2159
Ling Ma4fbab492022-01-25 22:36:16 +00002160 private int handleGetImei() {
2161 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2162 // non user build.
2163 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2164 getErrPrintWriter().println("Device IMEI: Permission denied.");
2165 return -1;
2166 }
2167
2168 final long identity = Binder.clearCallingIdentity();
2169
2170 String imei = null;
2171 String arg = getNextArg();
2172 if (arg != null) {
2173 try {
2174 int specifiedSlotIndex = Integer.parseInt(arg);
2175 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2176 } catch (NumberFormatException exception) {
2177 PrintWriter errPw = getErrPrintWriter();
2178 errPw.println("-s requires an integer as slot index.");
2179 return -1;
2180 }
2181
2182 } else {
2183 imei = TelephonyManager.from(mContext).getImei();
2184 }
2185 getOutPrintWriter().println("Device IMEI: " + imei);
2186
2187 Binder.restoreCallingIdentity(identity);
2188 return 0;
2189 }
2190
Michele Berionne5e411512020-11-13 02:36:59 +00002191 private int handleUnattendedReboot() {
2192 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2193 // non user build.
2194 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2195 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2196 return -1;
2197 }
2198
2199 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2200 getOutPrintWriter().println("result: " + result);
2201
2202 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2203 }
2204
Aman Gupta07124872022-02-09 08:02:14 +00002205 private int handleGetSimSlotsMapping() {
2206 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2207 // non user build.
2208 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2209 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2210 return -1;
2211 }
2212 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2213 String result = telephonyManager.getSimSlotMapping().toString();
2214 getOutPrintWriter().println("simSlotsMapping: " + result);
2215
2216 return 0;
2217 }
2218
Hui Wang641e81c2020-10-12 12:14:23 -07002219 private int handleGbaCommand() {
2220 String arg = getNextArg();
2221 if (arg == null) {
2222 onHelpGba();
2223 return 0;
2224 }
2225
2226 switch (arg) {
2227 case GBA_SET_SERVICE: {
2228 return handleGbaSetServiceCommand();
2229 }
2230 case GBA_GET_SERVICE: {
2231 return handleGbaGetServiceCommand();
2232 }
2233 case GBA_SET_RELEASE_TIME: {
2234 return handleGbaSetReleaseCommand();
2235 }
2236 case GBA_GET_RELEASE_TIME: {
2237 return handleGbaGetReleaseCommand();
2238 }
2239 }
2240
2241 return -1;
2242 }
2243
2244 private int getSubId(String cmd) {
2245 int slotId = getDefaultSlot();
2246 String opt = getNextOption();
2247 if (opt != null && opt.equals("-s")) {
2248 try {
2249 slotId = Integer.parseInt(getNextArgRequired());
2250 } catch (NumberFormatException e) {
2251 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2252 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2253 }
2254 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002255 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002256 }
2257
2258 private int handleGbaSetServiceCommand() {
2259 int subId = getSubId("gba set-service");
2260 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2261 return -1;
2262 }
2263
2264 String packageName = getNextArg();
2265 try {
2266 if (packageName == null) {
2267 packageName = "";
2268 }
2269 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2270 if (VDBG) {
2271 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2272 + packageName + ", result=" + result);
2273 }
2274 getOutPrintWriter().println(result);
2275 } catch (RemoteException e) {
2276 Log.w(LOG_TAG, "gba set-service " + subId + " "
2277 + packageName + ", error" + e.getMessage());
2278 getErrPrintWriter().println("Exception: " + e.getMessage());
2279 return -1;
2280 }
2281 return 0;
2282 }
2283
2284 private int handleGbaGetServiceCommand() {
2285 String result;
2286
2287 int subId = getSubId("gba get-service");
2288 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2289 return -1;
2290 }
2291
2292 try {
2293 result = mInterface.getBoundGbaService(subId);
2294 } catch (RemoteException e) {
2295 return -1;
2296 }
2297 if (VDBG) {
2298 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2299 }
2300 getOutPrintWriter().println(result);
2301 return 0;
2302 }
2303
2304 private int handleGbaSetReleaseCommand() {
2305 //the release time value could be -1
2306 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2307 : SubscriptionManager.getDefaultSubscriptionId();
2308 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2309 return -1;
2310 }
2311
2312 String intervalStr = getNextArg();
2313 if (intervalStr == null) {
2314 return -1;
2315 }
2316
2317 try {
2318 int interval = Integer.parseInt(intervalStr);
2319 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2320 if (VDBG) {
2321 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2322 + intervalStr + ", result=" + result);
2323 }
2324 getOutPrintWriter().println(result);
2325 } catch (NumberFormatException | RemoteException e) {
2326 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2327 + intervalStr + ", error" + e.getMessage());
2328 getErrPrintWriter().println("Exception: " + e.getMessage());
2329 return -1;
2330 }
2331 return 0;
2332 }
2333
2334 private int handleGbaGetReleaseCommand() {
2335 int subId = getSubId("gba get-release");
2336 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2337 return -1;
2338 }
2339
2340 int result = 0;
2341 try {
2342 result = mInterface.getGbaReleaseTime(subId);
2343 } catch (RemoteException e) {
2344 return -1;
2345 }
2346 if (VDBG) {
2347 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2348 }
2349 getOutPrintWriter().println(result);
2350 return 0;
2351 }
Hui Wang761a6682020-10-31 05:12:53 +00002352
2353 private int handleSingleRegistrationConfigCommand() {
2354 String arg = getNextArg();
2355 if (arg == null) {
2356 onHelpSrc();
2357 return 0;
2358 }
2359
2360 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002361 case SRC_SET_TEST_ENABLED: {
2362 return handleSrcSetTestEnabledCommand();
2363 }
2364 case SRC_GET_TEST_ENABLED: {
2365 return handleSrcGetTestEnabledCommand();
2366 }
Hui Wang761a6682020-10-31 05:12:53 +00002367 case SRC_SET_DEVICE_ENABLED: {
2368 return handleSrcSetDeviceEnabledCommand();
2369 }
2370 case SRC_GET_DEVICE_ENABLED: {
2371 return handleSrcGetDeviceEnabledCommand();
2372 }
2373 case SRC_SET_CARRIER_ENABLED: {
2374 return handleSrcSetCarrierEnabledCommand();
2375 }
2376 case SRC_GET_CARRIER_ENABLED: {
2377 return handleSrcGetCarrierEnabledCommand();
2378 }
Hui Wangb647abe2021-02-26 09:33:38 -08002379 case SRC_SET_FEATURE_ENABLED: {
2380 return handleSrcSetFeatureValidationCommand();
2381 }
2382 case SRC_GET_FEATURE_ENABLED: {
2383 return handleSrcGetFeatureValidationCommand();
2384 }
Hui Wang761a6682020-10-31 05:12:53 +00002385 }
2386
2387 return -1;
2388 }
2389
James.cf Linbcdf8b32021-01-14 16:44:13 +08002390 private int handleRcsUceCommand() {
2391 String arg = getNextArg();
2392 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002393 onHelpUce();
2394 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002395 }
2396
2397 switch (arg) {
2398 case UCE_REMOVE_EAB_CONTACT:
2399 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002400 case UCE_GET_EAB_CONTACT:
2401 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002402 case UCE_GET_EAB_CAPABILITY:
2403 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002404 case UCE_GET_DEVICE_ENABLED:
2405 return handleUceGetDeviceEnabledCommand();
2406 case UCE_SET_DEVICE_ENABLED:
2407 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002408 case UCE_OVERRIDE_PUBLISH_CAPS:
2409 return handleUceOverridePublishCaps();
2410 case UCE_GET_LAST_PIDF_XML:
2411 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002412 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2413 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002414 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2415 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002416 }
2417 return -1;
2418 }
2419
2420 private int handleRemovingEabContactCommand() {
2421 int subId = getSubId("uce remove-eab-contact");
2422 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2423 return -1;
2424 }
2425
2426 String phoneNumber = getNextArgRequired();
2427 if (TextUtils.isEmpty(phoneNumber)) {
2428 return -1;
2429 }
2430 int result = 0;
2431 try {
2432 result = mInterface.removeContactFromEab(subId, phoneNumber);
2433 } catch (RemoteException e) {
2434 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2435 getErrPrintWriter().println("Exception: " + e.getMessage());
2436 return -1;
2437 }
2438
2439 if (VDBG) {
2440 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2441 }
calvinpan293ea1b2021-02-04 17:52:13 +08002442 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002443 }
2444
calvinpane4a8a1d2021-01-25 13:51:18 +08002445 private int handleGettingEabContactCommand() {
2446 String phoneNumber = getNextArgRequired();
2447 if (TextUtils.isEmpty(phoneNumber)) {
2448 return -1;
2449 }
2450 String result = "";
2451 try {
2452 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002453 } catch (RemoteException e) {
2454 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2455 getErrPrintWriter().println("Exception: " + e.getMessage());
2456 return -1;
2457 }
2458
2459 if (VDBG) {
2460 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2461 }
calvinpan293ea1b2021-02-04 17:52:13 +08002462 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002463 return 0;
2464 }
2465
Calvin Pana1434322021-07-01 19:27:01 +08002466 private int handleGettingEabCapabilityCommand() {
2467 String phoneNumber = getNextArgRequired();
2468 if (TextUtils.isEmpty(phoneNumber)) {
2469 return -1;
2470 }
2471 String result = "";
2472 try {
2473 result = mInterface.getCapabilityFromEab(phoneNumber);
2474 } catch (RemoteException e) {
2475 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2476 getErrPrintWriter().println("Exception: " + e.getMessage());
2477 return -1;
2478 }
2479
2480 if (VDBG) {
2481 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2482 }
2483 getOutPrintWriter().println(result);
2484 return 0;
2485 }
2486
James.cf Lin4b784aa2021-01-31 03:25:15 +08002487 private int handleUceGetDeviceEnabledCommand() {
2488 boolean result = false;
2489 try {
2490 result = mInterface.getDeviceUceEnabled();
2491 } catch (RemoteException e) {
2492 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2493 return -1;
2494 }
2495 if (VDBG) {
2496 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2497 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002498 getOutPrintWriter().println(result);
2499 return 0;
2500 }
2501
James.cf Lin4b784aa2021-01-31 03:25:15 +08002502 private int handleUceSetDeviceEnabledCommand() {
2503 String enabledStr = getNextArg();
2504 if (TextUtils.isEmpty(enabledStr)) {
2505 return -1;
2506 }
2507
2508 try {
2509 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2510 mInterface.setDeviceUceEnabled(isEnabled);
2511 if (VDBG) {
2512 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2513 }
2514 } catch (NumberFormatException | RemoteException e) {
2515 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2516 getErrPrintWriter().println("Exception: " + e.getMessage());
2517 return -1;
2518 }
2519 return 0;
2520 }
2521
James.cf Line8713a42021-04-29 16:04:26 +08002522 private int handleUceRemoveRequestDisallowedStatus() {
2523 int subId = getSubId("uce remove-request-disallowed-status");
2524 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2525 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2526 return -1;
2527 }
2528 boolean result;
2529 try {
2530 result = mInterface.removeUceRequestDisallowedStatus(subId);
2531 } catch (RemoteException e) {
2532 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2533 return -1;
2534 }
2535 if (VDBG) {
2536 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2537 }
2538 getOutPrintWriter().println(result);
2539 return 0;
2540 }
2541
James.cf Lin0fc71b02021-05-25 01:37:38 +08002542 private int handleUceSetCapRequestTimeout() {
2543 int subId = getSubId("uce set-capabilities-request-timeout");
2544 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2545 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2546 return -1;
2547 }
2548 long timeoutAfterMs = Long.valueOf(getNextArg());
2549 boolean result;
2550 try {
2551 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2552 } catch (RemoteException e) {
2553 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2554 return -1;
2555 }
2556 if (VDBG) {
2557 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2558 }
2559 getOutPrintWriter().println(result);
2560 return 0;
2561 }
2562
Hui Wangbaaee6a2021-02-19 20:45:36 -08002563 private int handleSrcSetTestEnabledCommand() {
2564 String enabledStr = getNextArg();
2565 if (enabledStr == null) {
2566 return -1;
2567 }
2568
2569 try {
2570 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2571 if (VDBG) {
2572 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2573 }
2574 getOutPrintWriter().println("Done");
2575 } catch (NumberFormatException | RemoteException e) {
2576 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2577 getErrPrintWriter().println("Exception: " + e.getMessage());
2578 return -1;
2579 }
2580 return 0;
2581 }
2582
2583 private int handleSrcGetTestEnabledCommand() {
2584 boolean result = false;
2585 try {
2586 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2587 } catch (RemoteException e) {
2588 return -1;
2589 }
2590 if (VDBG) {
2591 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2592 }
2593 getOutPrintWriter().println(result);
2594 return 0;
2595 }
2596
Brad Ebinger14d467f2021-02-12 06:18:28 +00002597 private int handleUceOverridePublishCaps() {
2598 int subId = getSubId("uce override-published-caps");
2599 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2600 return -1;
2601 }
2602 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2603 String operation = getNextArgRequired();
2604 String caps = getNextArg();
2605 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2606 && !"list".equals(operation)) {
2607 getErrPrintWriter().println("Invalid operation: " + operation);
2608 return -1;
2609 }
2610
2611 // add/remove requires capabilities to be specified.
2612 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2613 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2614 + "specified");
2615 return -1;
2616 }
2617
2618 ArraySet<String> capSet = new ArraySet<>();
2619 if (!TextUtils.isEmpty(caps)) {
2620 String[] capArray = caps.split(":");
2621 for (String cap : capArray) {
2622 // Allow unknown tags to be passed in as well.
2623 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2624 }
2625 }
2626
2627 RcsContactUceCapability result = null;
2628 try {
2629 switch (operation) {
2630 case "add":
2631 result = mInterface.addUceRegistrationOverrideShell(subId,
2632 new ArrayList<>(capSet));
2633 break;
2634 case "remove":
2635 result = mInterface.removeUceRegistrationOverrideShell(subId,
2636 new ArrayList<>(capSet));
2637 break;
2638 case "clear":
2639 result = mInterface.clearUceRegistrationOverrideShell(subId);
2640 break;
2641 case "list":
2642 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2643 break;
2644 }
2645 } catch (RemoteException e) {
2646 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2647 getErrPrintWriter().println("Exception: " + e.getMessage());
2648 return -1;
2649 } catch (ServiceSpecificException sse) {
2650 // Reconstruct ImsException
2651 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2652 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2653 getErrPrintWriter().println("Exception: " + imsException);
2654 return -1;
2655 }
2656 if (result == null) {
2657 getErrPrintWriter().println("Service not available");
2658 return -1;
2659 }
2660 getOutPrintWriter().println(result);
2661 return 0;
2662 }
2663
2664 private int handleUceGetPidfXml() {
2665 int subId = getSubId("uce get-last-publish-pidf");
2666 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2667 return -1;
2668 }
2669
2670 String result;
2671 try {
2672 result = mInterface.getLastUcePidfXmlShell(subId);
2673 } catch (RemoteException e) {
2674 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2675 getErrPrintWriter().println("Exception: " + e.getMessage());
2676 return -1;
2677 } catch (ServiceSpecificException sse) {
2678 // Reconstruct ImsException
2679 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2680 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2681 getErrPrintWriter().println("Exception: " + imsException);
2682 return -1;
2683 }
2684 if (result == null) {
2685 getErrPrintWriter().println("Service not available");
2686 return -1;
2687 }
2688 getOutPrintWriter().println(result);
2689 return 0;
2690 }
2691
Hui Wang761a6682020-10-31 05:12:53 +00002692 private int handleSrcSetDeviceEnabledCommand() {
2693 String enabledStr = getNextArg();
2694 if (enabledStr == null) {
2695 return -1;
2696 }
2697
2698 try {
2699 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2700 if (VDBG) {
2701 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2702 }
2703 getOutPrintWriter().println("Done");
2704 } catch (NumberFormatException | RemoteException e) {
2705 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2706 getErrPrintWriter().println("Exception: " + e.getMessage());
2707 return -1;
2708 }
2709 return 0;
2710 }
2711
2712 private int handleSrcGetDeviceEnabledCommand() {
2713 boolean result = false;
2714 try {
2715 result = mInterface.getDeviceSingleRegistrationEnabled();
2716 } catch (RemoteException e) {
2717 return -1;
2718 }
2719 if (VDBG) {
2720 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2721 }
2722 getOutPrintWriter().println(result);
2723 return 0;
2724 }
2725
2726 private int handleSrcSetCarrierEnabledCommand() {
2727 //the release time value could be -1
2728 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2729 : SubscriptionManager.getDefaultSubscriptionId();
2730 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2731 return -1;
2732 }
2733
2734 String enabledStr = getNextArg();
2735 if (enabledStr == null) {
2736 return -1;
2737 }
2738
2739 try {
2740 boolean result =
2741 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2742 if (VDBG) {
2743 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2744 + enabledStr + ", result=" + result);
2745 }
2746 getOutPrintWriter().println(result);
2747 } catch (NumberFormatException | RemoteException e) {
2748 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2749 + enabledStr + ", error" + e.getMessage());
2750 getErrPrintWriter().println("Exception: " + e.getMessage());
2751 return -1;
2752 }
2753 return 0;
2754 }
2755
2756 private int handleSrcGetCarrierEnabledCommand() {
2757 int subId = getSubId("src get-carrier-enabled");
2758 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2759 return -1;
2760 }
2761
2762 boolean result = false;
2763 try {
2764 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2765 } catch (RemoteException e) {
2766 return -1;
2767 }
2768 if (VDBG) {
2769 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2770 }
2771 getOutPrintWriter().println(result);
2772 return 0;
2773 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002774
Hui Wangb647abe2021-02-26 09:33:38 -08002775 private int handleSrcSetFeatureValidationCommand() {
2776 //the release time value could be -1
2777 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2778 : SubscriptionManager.getDefaultSubscriptionId();
2779 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2780 return -1;
2781 }
2782
2783 String enabledStr = getNextArg();
2784 if (enabledStr == null) {
2785 return -1;
2786 }
2787
2788 try {
2789 boolean result =
2790 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2791 if (VDBG) {
2792 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2793 + enabledStr + ", result=" + result);
2794 }
2795 getOutPrintWriter().println(result);
2796 } catch (NumberFormatException | RemoteException e) {
2797 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2798 + enabledStr + ", error" + e.getMessage());
2799 getErrPrintWriter().println("Exception: " + e.getMessage());
2800 return -1;
2801 }
2802 return 0;
2803 }
2804
2805 private int handleSrcGetFeatureValidationCommand() {
2806 int subId = getSubId("src get-feature-validation");
2807 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2808 return -1;
2809 }
2810
2811 Boolean result = false;
2812 try {
2813 result = mInterface.getImsFeatureValidationOverride(subId);
2814 } catch (RemoteException e) {
2815 return -1;
2816 }
2817 if (VDBG) {
2818 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2819 }
2820 getOutPrintWriter().println(result);
2821 return 0;
2822 }
2823
2824
Hall Liuaa4211e2021-01-20 15:43:39 -08002825 private void onHelpCallComposer() {
2826 PrintWriter pw = getOutPrintWriter();
2827 pw.println("Call composer commands");
2828 pw.println(" callcomposer test-mode enable|disable|query");
2829 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2830 pw.println(" upload/download from carrier servers is disabled, and operations are");
2831 pw.println(" performed using emulated local files instead.");
2832 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2833 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2834 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002835 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2836 pw.println(" Enables or disables the user setting for call composer, as set by");
2837 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002838 }
2839
2840 private int handleCallComposerCommand() {
2841 String arg = getNextArg();
2842 if (arg == null) {
2843 onHelpCallComposer();
2844 return 0;
2845 }
2846
2847 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2848 "MODIFY_PHONE_STATE required for call composer shell cmds");
2849 switch (arg) {
2850 case CALL_COMPOSER_TEST_MODE: {
2851 String enabledStr = getNextArg();
2852 if (ENABLE.equals(enabledStr)) {
2853 CallComposerPictureManager.sTestMode = true;
2854 } else if (DISABLE.equals(enabledStr)) {
2855 CallComposerPictureManager.sTestMode = false;
2856 } else if (QUERY.equals(enabledStr)) {
2857 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2858 } else {
2859 onHelpCallComposer();
2860 return 1;
2861 }
2862 break;
2863 }
2864 case CALL_COMPOSER_SIMULATE_CALL: {
2865 int subscriptionId = Integer.valueOf(getNextArg());
2866 String uuidString = getNextArg();
2867 UUID uuid = UUID.fromString(uuidString);
2868 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2869 Binder.withCleanCallingIdentity(() -> {
2870 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2871 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2872 });
2873 try {
2874 Uri uri = storageUriFuture.get();
2875 getOutPrintWriter().println(String.valueOf(uri));
2876 } catch (Exception e) {
2877 throw new RuntimeException(e);
2878 }
2879 break;
2880 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002881 case CALL_COMPOSER_USER_SETTING: {
2882 try {
2883 int subscriptionId = Integer.valueOf(getNextArg());
2884 String enabledStr = getNextArg();
2885 if (ENABLE.equals(enabledStr)) {
2886 mInterface.setCallComposerStatus(subscriptionId,
2887 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2888 } else if (DISABLE.equals(enabledStr)) {
2889 mInterface.setCallComposerStatus(subscriptionId,
2890 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2891 } else if (QUERY.equals(enabledStr)) {
2892 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2893 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2894 } else {
2895 onHelpCallComposer();
2896 return 1;
2897 }
2898 } catch (RemoteException e) {
2899 e.printStackTrace(getOutPrintWriter());
2900 return 1;
2901 }
2902 break;
2903 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002904 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002905 return 0;
2906 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002907
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002908 private int handleHasCarrierPrivilegesCommand() {
2909 String packageName = getNextArgRequired();
2910
2911 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002912 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002913 try {
2914 hasCarrierPrivileges =
2915 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2916 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2917 } catch (RemoteException e) {
2918 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2919 getErrPrintWriter().println("Exception: " + e.getMessage());
2920 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002921 } finally {
2922 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002923 }
2924
2925 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002926 return 0;
2927 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002928
2929 private int handleAllowedNetworkTypesCommand(String command) {
2930 if (!checkShellUid()) {
2931 return -1;
2932 }
2933
2934 PrintWriter errPw = getErrPrintWriter();
2935 String tag = command + ": ";
2936 String opt;
2937 int subId = -1;
2938 Log.v(LOG_TAG, command + " start");
2939
2940 while ((opt = getNextOption()) != null) {
2941 if (opt.equals("-s")) {
2942 try {
2943 subId = slotStringToSubId(tag, getNextArgRequired());
2944 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2945 errPw.println(tag + "No valid subscription found.");
2946 return -1;
2947 }
2948 } catch (IllegalArgumentException e) {
2949 // Missing slot id
2950 errPw.println(tag + "SLOT_ID expected after -s.");
2951 return -1;
2952 }
2953 } else {
2954 errPw.println(tag + "Unknown option " + opt);
2955 return -1;
2956 }
2957 }
2958
2959 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2960 return handleGetAllowedNetworkTypesCommand(subId);
2961 }
2962 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2963 return handleSetAllowedNetworkTypesCommand(subId);
2964 }
2965 return -1;
2966 }
2967
2968 private int handleGetAllowedNetworkTypesCommand(int subId) {
2969 PrintWriter errPw = getErrPrintWriter();
2970
2971 long result = -1;
2972 try {
2973 if (mInterface != null) {
2974 result = mInterface.getAllowedNetworkTypesForReason(subId,
2975 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2976 } else {
2977 throw new IllegalStateException("telephony service is null.");
2978 }
2979 } catch (RemoteException e) {
2980 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2981 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2982 return -1;
2983 }
2984
2985 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2986 return 0;
2987 }
2988
2989 private int handleSetAllowedNetworkTypesCommand(int subId) {
2990 PrintWriter errPw = getErrPrintWriter();
2991
2992 String bitmaskString = getNextArg();
2993 if (TextUtils.isEmpty(bitmaskString)) {
2994 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2995 return -1;
2996 }
2997 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2998 if (allowedNetworkTypes < 0) {
2999 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
3000 return -1;
3001 }
3002 boolean result = false;
3003 try {
3004 if (mInterface != null) {
3005 result = mInterface.setAllowedNetworkTypesForReason(subId,
3006 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
3007 } else {
3008 throw new IllegalStateException("telephony service is null.");
3009 }
3010 } catch (RemoteException e) {
3011 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
3012 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
3013 return -1;
3014 }
3015
3016 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
3017 if (result) {
3018 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3019 }
3020 getOutPrintWriter().println(resultMessage);
3021 return 0;
3022 }
3023
3024 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3025 if (TextUtils.isEmpty(bitmaskString)) {
3026 return -1;
3027 }
3028 if (VDBG) {
3029 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3030 + ", length: " + bitmaskString.length());
3031 }
3032 try {
3033 return Long.parseLong(bitmaskString, 2);
3034 } catch (NumberFormatException e) {
3035 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3036 return -1;
3037 }
3038 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003039
jimsun3b9ccac2021-10-26 15:01:23 +08003040 private int handleRadioSetModemServiceCommand() {
3041 PrintWriter errPw = getErrPrintWriter();
3042 String serviceName = null;
3043
3044 String opt;
3045 while ((opt = getNextOption()) != null) {
3046 switch (opt) {
3047 case "-s": {
3048 serviceName = getNextArgRequired();
3049 break;
3050 }
3051 }
3052 }
3053
3054 try {
3055 boolean result = mInterface.setModemService(serviceName);
3056 if (VDBG) {
3057 Log.v(LOG_TAG,
3058 "RadioSetModemService " + serviceName + ", result = " + result);
3059 }
3060 getOutPrintWriter().println(result);
3061 } catch (RemoteException e) {
3062 Log.w(LOG_TAG,
3063 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3064 errPw.println("Exception: " + e.getMessage());
3065 return -1;
3066 }
3067 return 0;
3068 }
3069
3070 private int handleRadioGetModemServiceCommand() {
3071 PrintWriter errPw = getErrPrintWriter();
3072 String result;
3073
3074 try {
3075 result = mInterface.getModemService();
3076 getOutPrintWriter().println(result);
3077 } catch (RemoteException e) {
3078 errPw.println("Exception: " + e.getMessage());
3079 return -1;
3080 }
3081 if (VDBG) {
3082 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3083 }
3084 return 0;
3085 }
3086
3087 private int handleRadioCommand() {
3088 String arg = getNextArg();
3089 if (arg == null) {
3090 onHelpRadio();
3091 return 0;
3092 }
3093
3094 switch (arg) {
3095 case RADIO_SET_MODEM_SERVICE:
3096 return handleRadioSetModemServiceCommand();
3097
3098 case RADIO_GET_MODEM_SERVICE:
3099 return handleRadioGetModemServiceCommand();
3100 }
3101
3102 return -1;
3103 }
arunvoddud7401012022-12-15 16:08:12 +00003104
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003105 private int handleSetSatelliteServicePackageNameCommand() {
3106 PrintWriter errPw = getErrPrintWriter();
3107 String serviceName = null;
3108
3109 String opt;
3110 while ((opt = getNextOption()) != null) {
3111 switch (opt) {
3112 case "-s": {
3113 serviceName = getNextArgRequired();
3114 break;
3115 }
3116 }
3117 }
3118 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3119 + serviceName);
3120
3121 try {
3122 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3123 if (VDBG) {
3124 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3125 + ", result = " + result);
3126 }
3127 getOutPrintWriter().println(result);
3128 } catch (RemoteException e) {
3129 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3130 + ", error = " + e.getMessage());
3131 errPw.println("Exception: " + e.getMessage());
3132 return -1;
3133 }
3134 return 0;
3135 }
3136
Thomas Nguyen1854a5a2023-04-04 09:31:47 -07003137 private int handleSetSatelliteGatewayServicePackageNameCommand() {
3138 PrintWriter errPw = getErrPrintWriter();
3139 String serviceName = null;
3140
3141 String opt;
3142 while ((opt = getNextOption()) != null) {
3143 switch (opt) {
3144 case "-s": {
3145 serviceName = getNextArgRequired();
3146 break;
3147 }
3148 }
3149 }
3150 Log.d(LOG_TAG, "handleSetSatelliteGatewayServicePackageNameCommand: serviceName="
3151 + serviceName);
3152
3153 try {
3154 boolean result = mInterface.setSatelliteGatewayServicePackageName(serviceName);
3155 if (VDBG) {
3156 Log.v(LOG_TAG, "setSatelliteGatewayServicePackageName " + serviceName
3157 + ", result = " + result);
3158 }
3159 getOutPrintWriter().println(result);
3160 } catch (RemoteException e) {
3161 Log.w(LOG_TAG, "setSatelliteGatewayServicePackageName: " + serviceName
3162 + ", error = " + e.getMessage());
3163 errPw.println("Exception: " + e.getMessage());
3164 return -1;
3165 }
3166 return 0;
3167 }
3168
Thomas Nguyenf9a533c2023-04-06 20:48:41 -07003169 private int handleSetSatelliteListeningTimeoutDuration() {
3170 PrintWriter errPw = getErrPrintWriter();
3171 long timeoutMillis = 0;
3172
3173 String opt;
3174 while ((opt = getNextOption()) != null) {
3175 switch (opt) {
3176 case "-t": {
3177 timeoutMillis = Long.parseLong(getNextArgRequired());
3178 break;
3179 }
3180 }
3181 }
3182 Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
3183 + timeoutMillis);
3184
3185 try {
3186 boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
3187 if (VDBG) {
3188 Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
3189 + ", result = " + result);
3190 }
3191 getOutPrintWriter().println(result);
3192 } catch (RemoteException e) {
3193 Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
3194 + ", error = " + e.getMessage());
3195 errPw.println("Exception: " + e.getMessage());
3196 return -1;
3197 }
3198 return 0;
3199 }
3200
arunvoddud7401012022-12-15 16:08:12 +00003201 private int handleCarrierRestrictionStatusCommand() {
3202 try {
3203 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3204 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3205 mInterface.getModemService()))) {
3206 Log.v(LOG_TAG,
3207 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3208 + " checkShellUid fails");
3209 return -1;
3210 }
3211 } catch (RemoteException ex) {
3212 ex.printStackTrace();
3213 }
3214 String callerInfo = getNextOption();
3215 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3216 if (TextUtils.isEmpty(callerInfo)) {
3217 // reset the Json content after testing
3218 allowListInfo.updateJsonForTest(null);
3219 return 0;
3220 }
3221 if (callerInfo.startsWith("--")) {
3222 callerInfo = callerInfo.replace("--", "");
3223 }
3224 String params[] = callerInfo.split(",");
3225 StringBuffer jsonStrBuffer = new StringBuffer();
3226 String tokens;
3227 for (int index = 0; index < params.length; index++) {
3228 tokens = convertToJsonString(index, params[index]);
3229 if (TextUtils.isEmpty(tokens)) {
3230 // received wrong format from CTS
3231 if (VDBG) {
3232 Log.v(LOG_TAG,
3233 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3234 }
3235 return -1;
3236 }
3237 jsonStrBuffer.append(tokens);
3238 }
3239 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3240 return result;
3241 }
3242
Benedict Wong66477622023-02-03 23:30:57 +00003243 // set-carrier-service-package-override
3244 private int setCarrierServicePackageOverride() {
3245 PrintWriter errPw = getErrPrintWriter();
3246 int subId = SubscriptionManager.getDefaultSubscriptionId();
3247
3248 String opt;
3249 while ((opt = getNextOption()) != null) {
3250 switch (opt) {
3251 case "-s":
3252 try {
3253 subId = Integer.parseInt(getNextArgRequired());
3254 } catch (NumberFormatException e) {
3255 errPw.println(
3256 "set-carrier-service-package-override requires an integer as a"
3257 + " subscription ID.");
3258 return -1;
3259 }
3260 break;
3261 }
3262 }
3263
3264 String packageName = getNextArg();
3265 if (packageName == null) {
3266 errPw.println("set-carrier-service-package-override requires a override package name.");
3267 return -1;
3268 }
3269
3270 try {
3271 mInterface.setCarrierServicePackageOverride(
3272 subId, packageName, mContext.getOpPackageName());
3273
3274 if (VDBG) {
3275 Log.v(
3276 LOG_TAG,
3277 "set-carrier-service-package-override -s " + subId + " " + packageName);
3278 }
3279 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3280 Log.w(
3281 LOG_TAG,
3282 "set-carrier-service-package-override -s "
3283 + subId
3284 + " "
3285 + packageName
3286 + ", error"
3287 + e.getMessage());
3288 errPw.println("Exception: " + e.getMessage());
3289 return -1;
3290 }
3291 return 0;
3292 }
3293
3294 // clear-carrier-service-package-override
3295 private int clearCarrierServicePackageOverride() {
3296 PrintWriter errPw = getErrPrintWriter();
3297 int subId = getDefaultSlot();
3298
3299 String opt;
3300 while ((opt = getNextOption()) != null) {
3301 switch (opt) {
3302 case "-s":
3303 try {
3304 subId = Integer.parseInt(getNextArgRequired());
3305 } catch (NumberFormatException e) {
3306 errPw.println(
3307 "clear-carrier-service-package-override requires an integer as a"
3308 + " subscription ID.");
3309 return -1;
3310 }
3311 break;
3312 }
3313 }
3314
3315 try {
3316 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3317
3318 if (VDBG) {
3319 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3320 }
3321 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3322 Log.w(
3323 LOG_TAG,
3324 "clear-carrier-service-package-override -s "
3325 + subId
3326 + ", error"
3327 + e.getMessage());
3328 errPw.println("Exception: " + e.getMessage());
3329 return -1;
3330 }
3331 return 0;
3332 }
arunvoddud7401012022-12-15 16:08:12 +00003333
3334 /**
3335 * Building the string that can be used to build the JsonObject which supports to stub the data
3336 * in CarrierAllowListInfo for CTS testing. sample format is like
3337 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3338 */
3339 private String convertToJsonString(int index, String param) {
3340
3341 String token[] = param.split(":");
3342 String jSonString;
3343 switch (index) {
3344 case 0:
3345 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3346 break;
3347 case 1:
3348 jSonString =
3349 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3350 break;
3351 case 2:
3352 jSonString =
3353 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3354 break;
3355 default:
3356 jSonString = null;
3357 }
3358 return jSonString;
3359 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003360}