blob: 1858fe29f8e1e008e9012f88e894613a8cec4ad3 [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";
103 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800104
Hall Liu7135e502021-02-04 16:58:17 -0800105 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800106 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800107 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800108
Brad Ebinger999d3302020-11-25 14:31:39 -0800109 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
110 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
111 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700112 // Used to disable or enable processing of conference event package data from the network.
113 // This is handy for testing scenarios where CEP data does not exist on a network which does
114 // support CEP data.
115 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700116
Hall Liud892bec2018-11-30 14:51:45 -0800117 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800118 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800119
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100120 private static final String CC_GET_VALUE = "get-value";
121 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000122 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100123 private static final String CC_CLEAR_VALUES = "clear-values";
124
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000125 private static final String EUICC_SUBCOMMAND = "euicc";
126 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
127
Hui Wang641e81c2020-10-12 12:14:23 -0700128 private static final String GBA_SUBCOMMAND = "gba";
129 private static final String GBA_SET_SERVICE = "set-service";
130 private static final String GBA_GET_SERVICE = "get-service";
131 private static final String GBA_SET_RELEASE_TIME = "set-release";
132 private static final String GBA_GET_RELEASE_TIME = "get-release";
133
Hui Wang761a6682020-10-31 05:12:53 +0000134 private static final String SINGLE_REGISTATION_CONFIG = "src";
135 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
136 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
137 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
138 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800139 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
140 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800141 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
142 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000143
Tyler Gunn92479152021-01-20 16:30:10 -0800144 private static final String D2D_SUBCOMMAND = "d2d";
145 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800146 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700147 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800148
Nazanin014f41e2021-05-06 17:26:31 -0700149 private static final String BARRING_SUBCOMMAND = "barring";
150 private static final String BARRING_SEND_INFO = "send";
151
James.cf Linbcdf8b32021-01-14 16:44:13 +0800152 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800153 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800154 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800155 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800156 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
157 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000158 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
159 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800160 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
161 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800162 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
163 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800164
jimsun3b9ccac2021-10-26 15:01:23 +0800165 private static final String RADIO_SUBCOMMAND = "radio";
166 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
167 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
168
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800169 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
170 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
171
Jordan Liu0ccee222021-04-27 11:55:13 -0700172 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
173 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
174
Jack Nudelman644b91a2021-03-12 14:09:48 -0800175 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
176 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
177 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
178
Grant Menke567d48f2022-08-18 20:19:10 +0000179 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
180 + "'*', '#' or '+') needs to be specified after -a in the command ";
181
182 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
183 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
184 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
185
SongFerngWang98dd5992021-05-13 17:50:00 +0800186 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
187 "get-allowed-network-types-for-users";
188 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
189 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000190 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000191 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700192 // Take advantage of existing methods that already contain permissions checks when possible.
193 private final ITelephony mInterface;
194
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100195 private SubscriptionManager mSubscriptionManager;
196 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700197 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700198 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100199
200 private enum CcType {
201 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000202 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100203 }
204
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100205 private class CcOptionParseResult {
206 public int mSubId;
207 public boolean mPersistent;
208 }
209
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100210 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
211 // keys by looking at the end of the string which usually tells the type.
212 // For instance: "xxxx_string", "xxxx_string_array", etc.
213 // The carrier config keys in this map does not follow this convention. It is therefore not
214 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700215 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
216 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
217 CcType.STRING),
218 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
219 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
220 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
221 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
222 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
223 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
224 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
225 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
226 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
227 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
228 CcType.STRING),
229 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
230 CcType.STRING_ARRAY),
231 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
232 CcType.STRING_ARRAY),
233 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
234 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
235 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
236 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
237 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
238 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
239 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
240 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100241
Brad Ebinger14d467f2021-02-12 06:18:28 +0000242 /**
243 * Map from a shorthand string to the feature tags required in registration required in order
244 * for the RCS feature to be considered "capable".
245 */
246 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
247 static {
248 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
249 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
250 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
251 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
252 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
253 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
254 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
255 FeatureTags.FEATURE_TAG_VIDEO)));
256 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
257 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
258 map.put("call_comp",
259 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
260 map.put("call_comp_mmtel",
261 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
262 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
263 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
264 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
265 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
266 // version
267 map.put("chatbot", new ArraySet<>(Arrays.asList(
268 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
269 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
270 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
271 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000272 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000273 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
274 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
275 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
276 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
277 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000278 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000279 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
280 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
281 }
282
283
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100284 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700285 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100286 mCarrierConfigManager =
287 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
288 mSubscriptionManager = (SubscriptionManager)
289 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700290 mTelephonyRegistryManager = (TelephonyRegistryManager)
291 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700292 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700293 }
294
295 @Override
296 public int onCommand(String cmd) {
297 if (cmd == null) {
298 return handleDefaultCommands(null);
299 }
300
301 switch (cmd) {
302 case IMS_SUBCOMMAND: {
303 return handleImsCommand();
304 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800305 case RCS_UCE_COMMAND:
306 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800307 case NUMBER_VERIFICATION_SUBCOMMAND:
308 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800309 case EMERGENCY_CALLBACK_MODE:
310 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800311 case EMERGENCY_NUMBER_TEST_MODE:
312 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100313 case CARRIER_CONFIG_SUBCOMMAND: {
314 return handleCcCommand();
315 }
Shuo Qianf5125122019-12-16 17:03:07 -0800316 case DATA_TEST_MODE:
317 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700318 case END_BLOCK_SUPPRESSION:
319 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000320 case EUICC_SUBCOMMAND:
321 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700322 case GBA_SUBCOMMAND:
323 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800324 case D2D_SUBCOMMAND:
325 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700326 case BARRING_SUBCOMMAND:
327 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000328 case SINGLE_REGISTATION_CONFIG:
329 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000330 case RESTART_MODEM:
331 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800332 case CALL_COMPOSER_SUBCOMMAND:
333 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000334 case UNATTENDED_REBOOT:
335 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800336 case HAS_CARRIER_PRIVILEGES_COMMAND:
337 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800338 case THERMAL_MITIGATION_COMMAND:
339 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700340 case DISABLE_PHYSICAL_SUBSCRIPTION:
341 return handleEnablePhysicalSubscription(false);
342 case ENABLE_PHYSICAL_SUBSCRIPTION:
343 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800344 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
345 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
346 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000347 case GET_IMEI:
348 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000349 case GET_SIM_SLOTS_MAPPING:
350 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800351 case RADIO_SUBCOMMAND:
352 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000353 case CARRIER_RESTRICTION_STATUS_TEST:
354 return handleCarrierRestrictionStatusCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700355 default: {
356 return handleDefaultCommands(cmd);
357 }
358 }
359 }
360
361 @Override
362 public void onHelp() {
363 PrintWriter pw = getOutPrintWriter();
364 pw.println("Telephony Commands:");
365 pw.println(" help");
366 pw.println(" Print this help text.");
367 pw.println(" ims");
368 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800369 pw.println(" uce");
370 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800371 pw.println(" emergency-number-test-mode");
372 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700373 pw.println(" end-block-suppression");
374 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800375 pw.println(" data");
376 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100377 pw.println(" cc");
378 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700379 pw.println(" gba");
380 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000381 pw.println(" src");
382 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000383 pw.println(" restart-modem");
384 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000385 pw.println(" unattended-reboot");
386 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800387 pw.println(" has-carrier-privileges [package]");
388 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800389 pw.println(" get-allowed-network-types-for-users");
390 pw.println(" Get the Allowed Network Types.");
391 pw.println(" set-allowed-network-types-for-users");
392 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800393 pw.println(" radio");
394 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700395 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800396 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800397 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700398 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800399 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100400 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700401 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000402 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800403 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700404 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800405 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800406 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000407 onHelpImei();
Tyler Gunn92479152021-01-20 16:30:10 -0800408 }
409
410 private void onHelpD2D() {
411 PrintWriter pw = getOutPrintWriter();
412 pw.println("D2D Comms Commands:");
413 pw.println(" d2d send TYPE VALUE");
414 pw.println(" Sends a D2D message of specified type and value.");
415 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
416 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
417 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
418 MESSAGE_CALL_AUDIO_CODEC));
419 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
420 + Communicator.messageToString(
421 MESSAGE_DEVICE_BATTERY_STATE));
422 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
423 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800424 pw.println(" d2d transport TYPE");
425 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
426 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700427 pw.println(" d2d set-device-support true/default");
428 pw.println(" true - forces device support to be enabled for D2D.");
429 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
430 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700431 }
432
Nazanin014f41e2021-05-06 17:26:31 -0700433 private void onHelpBarring() {
434 PrintWriter pw = getOutPrintWriter();
435 pw.println("Barring Commands:");
436 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
437 + " -t CONDITIONAL_BARRING_TIME_SECS");
438 pw.println(" Notifies of a barring info change for the specified slot id.");
439 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
440 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
441 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
442 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
443 }
444
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700445 private void onHelpIms() {
446 PrintWriter pw = getOutPrintWriter();
447 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800448 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700449 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
450 pw.println(" ImsService. Options are:");
451 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
452 pw.println(" is specified, it will choose the default voice SIM slot.");
453 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
454 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800455 pw.println(" -f: Set the feature that this override if for, if no option is");
456 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700457 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
458 pw.println(" Gets the package name of the currently defined ImsService.");
459 pw.println(" Options are:");
460 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
461 pw.println(" is specified, it will choose the default voice SIM slot.");
462 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000463 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800464 pw.println(" -f: The feature type that the query will be requested for. If none is");
465 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800466 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
467 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
468 pw.println(" configuration overrides. Options are:");
469 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
470 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700471 pw.println(" ims enable [-s SLOT_ID]");
472 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
473 pw.println(" if none is specified.");
474 pw.println(" ims disable [-s SLOT_ID]");
475 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
476 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700477 pw.println(" ims conference-event-package [enable/disable]");
478 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700479 }
480
James.cf Linbcdf8b32021-01-14 16:44:13 +0800481 private void onHelpUce() {
482 PrintWriter pw = getOutPrintWriter();
483 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800484 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
485 pw.println(" Get the EAB contacts from the EAB database.");
486 pw.println(" Options are:");
487 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
488 pw.println(" Expected output format :");
489 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800490 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
491 pw.println(" Remove the EAB contacts from the EAB database.");
492 pw.println(" Options are:");
493 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
494 pw.println(" is specified, it will choose the default voice SIM slot.");
495 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800496 pw.println(" uce get-device-enabled");
497 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
498 pw.println(" uce set-device-enabled true|false");
499 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
500 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000501 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
502 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
503 pw.println(" Options are:");
504 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
505 pw.println(" is specified, it will choose the default voice SIM slot.");
506 pw.println(" add [CAPABILITY]: add a new capability");
507 pw.println(" remove [CAPABILITY]: remove a capability");
508 pw.println(" clear: clear all capability overrides");
509 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
510 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
511 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
512 pw.println(" chatbot_sa, chatbot_role] as well as full length");
513 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
514 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
515 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
516 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800517 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
518 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800519 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
520 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800521 }
522
Hall Liud892bec2018-11-30 14:51:45 -0800523 private void onHelpNumberVerification() {
524 PrintWriter pw = getOutPrintWriter();
525 pw.println("Number verification commands");
526 pw.println(" numverify override-package PACKAGE_NAME;");
527 pw.println(" Set the authorized package for number verification.");
528 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800529 pw.println(" numverify fake-call NUMBER;");
530 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
531 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800532 }
533
Jack Nudelman644b91a2021-03-12 14:09:48 -0800534 private void onHelpThermalMitigation() {
535 PrintWriter pw = getOutPrintWriter();
536 pw.println("Thermal mitigation commands");
537 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
538 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
539 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
540 pw.println(" Remove the package from one of the authorized packages for thermal "
541 + "mitigation.");
542 }
543
Jordan Liu0ccee222021-04-27 11:55:13 -0700544 private void onHelpDisableOrEnablePhysicalSubscription() {
545 PrintWriter pw = getOutPrintWriter();
546 pw.println("Disable or enable a physical subscription");
547 pw.println(" disable-physical-subscription SUB_ID");
548 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
549 pw.println(" enable-physical-subscription SUB_ID");
550 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
551 }
552
Shuo Qianf5125122019-12-16 17:03:07 -0800553 private void onHelpDataTestMode() {
554 PrintWriter pw = getOutPrintWriter();
555 pw.println("Mobile Data Test Mode Commands:");
556 pw.println(" data enable: enable mobile data connectivity");
557 pw.println(" data disable: disable mobile data connectivity");
558 }
559
sqian9d4df8b2019-01-15 18:32:07 -0800560 private void onHelpEmergencyNumber() {
561 PrintWriter pw = getOutPrintWriter();
562 pw.println("Emergency Number Test Mode Commands:");
563 pw.println(" emergency-number-test-mode ");
564 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
565 + " the test mode");
566 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700567 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800568 pw.println(" -c: clear the emergency number list in the test mode.");
569 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700570 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800571 pw.println(" -p: get the full emergency number list in the test mode.");
572 }
573
Shuo Qian489d9282020-07-09 11:30:03 -0700574 private void onHelpEndBlockSupperssion() {
575 PrintWriter pw = getOutPrintWriter();
576 pw.println("End Block Suppression command:");
577 pw.println(" end-block-suppression: disable suppressing blocking by contact");
578 pw.println(" with emergency services.");
579 }
580
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100581 private void onHelpCc() {
582 PrintWriter pw = getOutPrintWriter();
583 pw.println("Carrier Config Commands:");
584 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
585 pw.println(" Print carrier config values.");
586 pw.println(" Options are:");
587 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
588 pw.println(" is specified, it will choose the default voice SIM slot.");
589 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
590 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100591 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100592 pw.println(" Set carrier config KEY to NEW_VALUE.");
593 pw.println(" Options are:");
594 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
595 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100596 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100597 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
598 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
599 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
600 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000601 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
602 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
603 pw.println(" provided through standard input and follow CarrierConfig XML format.");
604 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
605 pw.println(" Options are:");
606 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
607 pw.println(" is specified, it will choose the default voice SIM slot.");
608 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100609 pw.println(" cc clear-values [-s SLOT_ID]");
610 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000611 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100612 pw.println(" Options are:");
613 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
614 pw.println(" is specified, it will choose the default voice SIM slot.");
615 }
616
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000617 private void onHelpEuicc() {
618 PrintWriter pw = getOutPrintWriter();
619 pw.println("Euicc Commands:");
620 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
621 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
622 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
623 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
624 }
625
Hui Wang641e81c2020-10-12 12:14:23 -0700626 private void onHelpGba() {
627 PrintWriter pw = getOutPrintWriter();
628 pw.println("Gba Commands:");
629 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
630 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
631 pw.println(" Options are:");
632 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
633 pw.println(" is specified, it will choose the default voice SIM slot.");
634 pw.println(" gba get-service [-s SLOT_ID]");
635 pw.println(" Gets the package name of the currently defined GbaService.");
636 pw.println(" Options are:");
637 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
638 pw.println(" is specified, it will choose the default voice SIM slot.");
639 pw.println(" gba set-release [-s SLOT_ID] n");
640 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
641 pw.println(" Do not release/unbind if n is -1.");
642 pw.println(" Options are:");
643 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
644 pw.println(" is specified, it will choose the default voice SIM slot.");
645 pw.println(" gba get-release [-s SLOT_ID]");
646 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
647 pw.println(" Options are:");
648 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
649 pw.println(" is specified, it will choose the default voice SIM slot.");
650 }
651
Hui Wang761a6682020-10-31 05:12:53 +0000652 private void onHelpSrc() {
653 PrintWriter pw = getOutPrintWriter();
654 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800655 pw.println(" src set-test-enabled true|false");
656 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
657 pw.println(" The value could be true, false, or null(undefined).");
658 pw.println(" src get-test-enabled");
659 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000660 pw.println(" src set-device-enabled true|false|null");
661 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
662 pw.println(" The value could be true, false, or null(undefined).");
663 pw.println(" src get-device-enabled");
664 pw.println(" Gets the device config for RCS VoLTE single registration.");
665 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
666 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
667 pw.println(" The value could be true, false, or null(undefined).");
668 pw.println(" Options are:");
669 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
670 pw.println(" is specified, it will choose the default voice SIM slot.");
671 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
672 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
673 pw.println(" Options are:");
674 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
675 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800676 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
677 pw.println(" Sets ims feature validation result.");
678 pw.println(" The value could be true, false, or null(undefined).");
679 pw.println(" Options are:");
680 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
681 pw.println(" is specified, it will choose the default voice SIM slot.");
682 pw.println(" src get-feature-validation [-s SLOT_ID]");
683 pw.println(" Gets ims feature validation override value.");
684 pw.println(" Options are:");
685 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
686 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000687 }
688
SongFerngWang98dd5992021-05-13 17:50:00 +0800689 private void onHelpAllowedNetworkTypes() {
690 PrintWriter pw = getOutPrintWriter();
691 pw.println("Allowed Network Types Commands:");
692 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
693 pw.println(" Print allowed network types value.");
694 pw.println(" Options are:");
695 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
696 pw.println(" option is specified, it will choose the default voice SIM slot.");
697 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
698 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
699 pw.println(" Options are:");
700 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
701 pw.println(" option is specified, it will choose the default voice SIM slot.");
702 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
703 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
704 pw.println(" at TelephonyManager.java");
705 pw.println(" For example:");
706 pw.println(" NR only : 10000000000000000000");
707 pw.println(" NR|LTE : 11000001000000000000");
708 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
709 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
710 pw.println(" LTE only : 01000001000000000000");
711 }
712
jimsun3b9ccac2021-10-26 15:01:23 +0800713 private void onHelpRadio() {
714 PrintWriter pw = getOutPrintWriter();
715 pw.println("Radio Commands:");
716 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
717 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
718 pw.println(" to be the bound. Options are:");
719 pw.println(" -s: the service name that the modem service should be bound for.");
720 pw.println(" If no option is specified, it will bind to the default.");
721 pw.println(" radio get-modem-service");
722 pw.println(" Gets the service name of the currently defined modem service.");
723 pw.println(" If it is binding to default, 'default' returns.");
724 pw.println(" If it doesn't bind to any modem service for some reasons,");
725 pw.println(" the result would be 'unknown'.");
726 }
727
Ling Ma4fbab492022-01-25 22:36:16 +0000728 private void onHelpImei() {
729 PrintWriter pw = getOutPrintWriter();
730 pw.println("IMEI Commands:");
731 pw.println(" get-imei [-s SLOT_ID]");
732 pw.println(" Gets the device IMEI. Options are:");
733 pw.println(" -s: the slot ID to get the IMEI. If no option");
734 pw.println(" is specified, it will choose the default voice SIM slot.");
735 }
736
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700737 private int handleImsCommand() {
738 String arg = getNextArg();
739 if (arg == null) {
740 onHelpIms();
741 return 0;
742 }
743
744 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800745 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700746 return handleImsSetServiceCommand();
747 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800748 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700749 return handleImsGetServiceCommand();
750 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800751 case IMS_CLEAR_SERVICE_OVERRIDE: {
752 return handleImsClearCarrierServiceCommand();
753 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800754 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700755 return handleEnableIms();
756 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800757 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700758 return handleDisableIms();
759 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700760 case IMS_CEP: {
761 return handleCepChange();
762 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700763 }
764
765 return -1;
766 }
767
Shuo Qianf5125122019-12-16 17:03:07 -0800768 private int handleDataTestModeCommand() {
769 PrintWriter errPw = getErrPrintWriter();
770 String arg = getNextArgRequired();
771 if (arg == null) {
772 onHelpDataTestMode();
773 return 0;
774 }
775 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800776 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800777 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700778 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800779 } catch (RemoteException ex) {
780 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
781 errPw.println("Exception: " + ex.getMessage());
782 return -1;
783 }
784 break;
785 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800786 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800787 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700788 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800789 } catch (RemoteException ex) {
790 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
791 errPw.println("Exception: " + ex.getMessage());
792 return -1;
793 }
794 break;
795 }
796 default:
797 onHelpDataTestMode();
798 break;
799 }
800 return 0;
801 }
802
Shuo Qianccbaf742021-02-22 18:32:21 -0800803 private int handleEmergencyCallbackModeCommand() {
804 PrintWriter errPw = getErrPrintWriter();
805 try {
806 mInterface.startEmergencyCallbackMode();
807 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
808 } catch (RemoteException ex) {
809 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
810 errPw.println("Exception: " + ex.getMessage());
811 return -1;
812 }
813 return 0;
814 }
815
Grant Menke567d48f2022-08-18 20:19:10 +0000816 private void removeEmergencyNumberTestMode(String emergencyNumber) {
817 PrintWriter errPw = getErrPrintWriter();
818 for (int routingType : ROUTING_TYPES) {
819 try {
820 mInterface.updateEmergencyNumberListTestMode(
821 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
822 new EmergencyNumber(emergencyNumber, "", "",
823 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
824 new ArrayList<String>(),
825 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
826 routingType));
827 } catch (RemoteException ex) {
828 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
829 errPw.println("Exception: " + ex.getMessage());
830 }
831 }
832 }
833
sqian9d4df8b2019-01-15 18:32:07 -0800834 private int handleEmergencyNumberTestModeCommand() {
835 PrintWriter errPw = getErrPrintWriter();
836 String opt = getNextOption();
837 if (opt == null) {
838 onHelpEmergencyNumber();
839 return 0;
840 }
sqian9d4df8b2019-01-15 18:32:07 -0800841 switch (opt) {
842 case "-a": {
843 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000844 if (emergencyNumberCmd == null){
845 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800846 return -1;
847 }
Grant Menke567d48f2022-08-18 20:19:10 +0000848 String[] params = emergencyNumberCmd.split(":");
849 String emergencyNumber;
850 if (params[0] == null ||
851 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
852 errPw.println(INVALID_ENTRY_ERROR);
853 return -1;
854 } else {
855 emergencyNumber = params[0];
856 }
857 removeEmergencyNumberTestMode(emergencyNumber);
858 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
859 if (params.length > 1) {
860 switch (params[1].toLowerCase(Locale.ROOT)) {
861 case "emergency":
862 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
863 break;
864 case "normal":
865 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
866 break;
867 case "unknown":
868 break;
869 default:
870 errPw.println("\"" + params[1] + "\" is not a valid specification for "
871 + "emergency call routing. Please enter either \"normal\", "
872 + "\"unknown\", or \"emergency\" for call routing. "
873 + "(-a 1234:normal)");
874 return -1;
875 }
876 }
sqian9d4df8b2019-01-15 18:32:07 -0800877 try {
878 mInterface.updateEmergencyNumberListTestMode(
879 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000880 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800881 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
882 new ArrayList<String>(),
883 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000884 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800885 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000886 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800887 + ", error " + ex.getMessage());
888 errPw.println("Exception: " + ex.getMessage());
889 return -1;
890 }
891 break;
892 }
893 case "-c": {
894 try {
895 mInterface.updateEmergencyNumberListTestMode(
896 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
897 } catch (RemoteException ex) {
898 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
899 errPw.println("Exception: " + ex.getMessage());
900 return -1;
901 }
902 break;
903 }
904 case "-r": {
905 String emergencyNumberCmd = getNextArgRequired();
906 if (emergencyNumberCmd == null
907 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700908 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800909 + " to be specified after -r in the command ");
910 return -1;
911 }
Grant Menke567d48f2022-08-18 20:19:10 +0000912 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800913 break;
914 }
915 case "-p": {
916 try {
917 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
918 } catch (RemoteException ex) {
919 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
920 errPw.println("Exception: " + ex.getMessage());
921 return -1;
922 }
923 break;
924 }
925 default:
926 onHelpEmergencyNumber();
927 break;
928 }
929 return 0;
930 }
931
Hall Liud892bec2018-11-30 14:51:45 -0800932 private int handleNumberVerificationCommand() {
933 String arg = getNextArg();
934 if (arg == null) {
935 onHelpNumberVerification();
936 return 0;
937 }
938
Hall Liuca5af3a2018-12-04 16:58:23 -0800939 if (!checkShellUid()) {
940 return -1;
941 }
942
Hall Liud892bec2018-11-30 14:51:45 -0800943 switch (arg) {
944 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800945 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
946 return 0;
947 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800948 case NUMBER_VERIFICATION_FAKE_CALL: {
949 boolean val = NumberVerificationManager.getInstance()
950 .checkIncomingCall(getNextArg());
951 getOutPrintWriter().println(val ? "1" : "0");
952 return 0;
953 }
Hall Liud892bec2018-11-30 14:51:45 -0800954 }
955
956 return -1;
957 }
958
Jordan Liu0ccee222021-04-27 11:55:13 -0700959 private boolean subIsEsim(int subId) {
960 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
961 if (info != null) {
962 return info.isEmbedded();
963 }
964 return false;
965 }
966
967 private int handleEnablePhysicalSubscription(boolean enable) {
968 PrintWriter errPw = getErrPrintWriter();
969 int subId = 0;
970 try {
971 subId = Integer.parseInt(getNextArgRequired());
972 } catch (NumberFormatException e) {
973 errPw.println((enable ? "enable" : "disable")
974 + "-physical-subscription requires an integer as a subId.");
975 return -1;
976 }
977 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
978 // non user build.
979 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
980 errPw.println("cc: Permission denied.");
981 return -1;
982 }
983 // Verify that the subId represents a physical sub
984 if (subIsEsim(subId)) {
985 errPw.println("SubId " + subId + " is not for a physical subscription");
986 return -1;
987 }
988 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
989 + " physical subscription with subId=" + subId);
990 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
991 return 0;
992 }
993
Jack Nudelman644b91a2021-03-12 14:09:48 -0800994 private int handleThermalMitigationCommand() {
995 String arg = getNextArg();
996 String packageName = getNextArg();
997 if (arg == null || packageName == null) {
998 onHelpThermalMitigation();
999 return 0;
1000 }
1001
1002 if (!checkShellUid()) {
1003 return -1;
1004 }
1005
1006 switch (arg) {
1007 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1008 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1009 return 0;
1010 }
1011 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1012 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1013 mContext);
1014 return 0;
1015 }
1016 default:
1017 onHelpThermalMitigation();
1018 }
1019
1020 return -1;
1021
1022 }
1023
Tyler Gunn92479152021-01-20 16:30:10 -08001024 private int handleD2dCommand() {
1025 String arg = getNextArg();
1026 if (arg == null) {
1027 onHelpD2D();
1028 return 0;
1029 }
1030
1031 switch (arg) {
1032 case D2D_SEND: {
1033 return handleD2dSendCommand();
1034 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001035 case D2D_TRANSPORT: {
1036 return handleD2dTransportCommand();
1037 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001038 case D2D_SET_DEVICE_SUPPORT: {
1039 return handleD2dDeviceSupportedCommand();
1040 }
Tyler Gunn92479152021-01-20 16:30:10 -08001041 }
1042
1043 return -1;
1044 }
1045
1046 private int handleD2dSendCommand() {
1047 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001048 int messageType = -1;
1049 int messageValue = -1;
1050
Tyler Gunn92479152021-01-20 16:30:10 -08001051 String arg = getNextArg();
1052 if (arg == null) {
1053 onHelpD2D();
1054 return 0;
1055 }
1056 try {
1057 messageType = Integer.parseInt(arg);
1058 } catch (NumberFormatException e) {
1059 errPw.println("message type must be a valid integer");
1060 return -1;
1061 }
1062
1063 arg = getNextArg();
1064 if (arg == null) {
1065 onHelpD2D();
1066 return 0;
1067 }
1068 try {
1069 messageValue = Integer.parseInt(arg);
1070 } catch (NumberFormatException e) {
1071 errPw.println("message value must be a valid integer");
1072 return -1;
1073 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001074
Tyler Gunn92479152021-01-20 16:30:10 -08001075 try {
1076 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1077 } catch (RemoteException e) {
1078 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1079 errPw.println("Exception: " + e.getMessage());
1080 return -1;
1081 }
1082
1083 return 0;
1084 }
1085
Tyler Gunnbabbda02021-02-10 11:05:02 -08001086 private int handleD2dTransportCommand() {
1087 PrintWriter errPw = getErrPrintWriter();
1088
1089 String arg = getNextArg();
1090 if (arg == null) {
1091 onHelpD2D();
1092 return 0;
1093 }
1094
1095 try {
1096 mInterface.setActiveDeviceToDeviceTransport(arg);
1097 } catch (RemoteException e) {
1098 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1099 errPw.println("Exception: " + e.getMessage());
1100 return -1;
1101 }
1102 return 0;
1103 }
Nazanin014f41e2021-05-06 17:26:31 -07001104 private int handleBarringCommand() {
1105 String arg = getNextArg();
1106 if (arg == null) {
1107 onHelpBarring();
1108 return 0;
1109 }
1110
1111 switch (arg) {
1112 case BARRING_SEND_INFO: {
1113 return handleBarringSendCommand();
1114 }
1115 }
1116 return -1;
1117 }
1118
1119 private int handleBarringSendCommand() {
1120 PrintWriter errPw = getErrPrintWriter();
1121 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001122 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001123 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1124 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1125 boolean isConditionallyBarred = false;
1126 int conditionalBarringTimeSeconds = 0;
1127
1128 String opt;
1129 while ((opt = getNextOption()) != null) {
1130 switch (opt) {
1131 case "-s": {
1132 try {
1133 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001134 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001135 } catch (NumberFormatException e) {
1136 errPw.println("barring send requires an integer as a SLOT_ID.");
1137 return -1;
1138 }
1139 break;
1140 }
1141 case "-b": {
1142 try {
1143 barringType = Integer.parseInt(getNextArgRequired());
1144 if (barringType < -1 || barringType > 2) {
1145 throw new NumberFormatException();
1146 }
1147
1148 } catch (NumberFormatException e) {
1149 errPw.println("barring send requires an integer in range [-1,2] as "
1150 + "a BARRING_TYPE.");
1151 return -1;
1152 }
1153 break;
1154 }
1155 case "-c": {
1156 try {
1157 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1158 } catch (Exception e) {
1159 errPw.println("barring send requires a boolean after -c indicating"
1160 + " conditional barring");
1161 return -1;
1162 }
1163 break;
1164 }
1165 case "-t": {
1166 try {
1167 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1168 } catch (NumberFormatException e) {
1169 errPw.println("barring send requires an integer for time of barring"
1170 + " in seconds after -t for conditional barring");
1171 return -1;
1172 }
1173 break;
1174 }
1175 }
1176 }
1177 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1178 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1179 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1180 barringServiceInfos.append(0, bsi);
1181 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1182 try {
1183 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1184 } catch (Exception e) {
1185 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1186 errPw.println("Exception: " + e.getMessage());
1187 return -1;
1188 }
1189 return 0;
1190 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001191
Tyler Gunnd4575212021-05-03 14:46:49 -07001192 private int handleD2dDeviceSupportedCommand() {
1193 PrintWriter errPw = getErrPrintWriter();
1194
1195 String arg = getNextArg();
1196 if (arg == null) {
1197 onHelpD2D();
1198 return 0;
1199 }
1200
Jack Yua533d632022-09-30 13:53:46 -07001201 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001202 try {
1203 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1204 } catch (RemoteException e) {
1205 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1206 errPw.println("Exception: " + e.getMessage());
1207 return -1;
1208 }
1209 return 0;
1210 }
1211
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001212 // ims set-ims-service
1213 private int handleImsSetServiceCommand() {
1214 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001215 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001216 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001217 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001218
1219 String opt;
1220 while ((opt = getNextOption()) != null) {
1221 switch (opt) {
1222 case "-s": {
1223 try {
1224 slotId = Integer.parseInt(getNextArgRequired());
1225 } catch (NumberFormatException e) {
1226 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1227 return -1;
1228 }
1229 break;
1230 }
1231 case "-c": {
1232 isCarrierService = true;
1233 break;
1234 }
1235 case "-d": {
1236 isCarrierService = false;
1237 break;
1238 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001239 case "-f": {
1240 String featureString = getNextArgRequired();
1241 String[] features = featureString.split(",");
1242 for (int i = 0; i < features.length; i++) {
1243 try {
1244 Integer result = Integer.parseInt(features[i]);
1245 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1246 || result >= ImsFeature.FEATURE_MAX) {
1247 errPw.println("ims set-ims-service -f " + result
1248 + " is an invalid feature.");
1249 return -1;
1250 }
1251 featuresList.add(result);
1252 } catch (NumberFormatException e) {
1253 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1254 + " as an integer.");
1255 return -1;
1256 }
1257 }
1258 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001259 }
1260 }
1261 // Mandatory param, either -c or -d
1262 if (isCarrierService == null) {
1263 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1264 return -1;
1265 }
1266
1267 String packageName = getNextArg();
1268
1269 try {
1270 if (packageName == null) {
1271 packageName = "";
1272 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001273 int[] featureArray = new int[featuresList.size()];
1274 for (int i = 0; i < featuresList.size(); i++) {
1275 featureArray[i] = featuresList.get(i);
1276 }
1277 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1278 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001279 if (VDBG) {
1280 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001281 + (isCarrierService ? "-c " : "-d ")
1282 + "-f " + featuresList + " "
1283 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001284 }
1285 getOutPrintWriter().println(result);
1286 } catch (RemoteException e) {
1287 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001288 + (isCarrierService ? "-c " : "-d ")
1289 + "-f " + featuresList + " "
1290 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001291 errPw.println("Exception: " + e.getMessage());
1292 return -1;
1293 }
1294 return 0;
1295 }
1296
Brad Ebinger999d3302020-11-25 14:31:39 -08001297 // ims clear-ims-service-override
1298 private int handleImsClearCarrierServiceCommand() {
1299 PrintWriter errPw = getErrPrintWriter();
1300 int slotId = getDefaultSlot();
1301
1302 String opt;
1303 while ((opt = getNextOption()) != null) {
1304 switch (opt) {
1305 case "-s": {
1306 try {
1307 slotId = Integer.parseInt(getNextArgRequired());
1308 } catch (NumberFormatException e) {
1309 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1310 return -1;
1311 }
1312 break;
1313 }
1314 }
1315 }
1316
1317 try {
1318 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1319 if (VDBG) {
1320 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1321 + ", result=" + result);
1322 }
1323 getOutPrintWriter().println(result);
1324 } catch (RemoteException e) {
1325 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1326 + ", error" + e.getMessage());
1327 errPw.println("Exception: " + e.getMessage());
1328 return -1;
1329 }
1330 return 0;
1331 }
1332
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001333 // ims get-ims-service
1334 private int handleImsGetServiceCommand() {
1335 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001336 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001337 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001338 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001339
1340 String opt;
1341 while ((opt = getNextOption()) != null) {
1342 switch (opt) {
1343 case "-s": {
1344 try {
1345 slotId = Integer.parseInt(getNextArgRequired());
1346 } catch (NumberFormatException e) {
1347 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1348 return -1;
1349 }
1350 break;
1351 }
1352 case "-c": {
1353 isCarrierService = true;
1354 break;
1355 }
1356 case "-d": {
1357 isCarrierService = false;
1358 break;
1359 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001360 case "-f": {
1361 try {
1362 featureType = Integer.parseInt(getNextArg());
1363 } catch (NumberFormatException e) {
1364 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1365 return -1;
1366 }
1367 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1368 || featureType >= ImsFeature.FEATURE_MAX) {
1369 errPw.println("ims get-ims-service -f invalid feature.");
1370 return -1;
1371 }
1372 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001373 }
1374 }
1375 // Mandatory param, either -c or -d
1376 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001377 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001378 return -1;
1379 }
1380
1381 String result;
1382 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001383 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001384 } catch (RemoteException e) {
1385 return -1;
1386 }
1387 if (VDBG) {
1388 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001389 + (isCarrierService ? "-c " : "-d ")
1390 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1391 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001392 }
1393 getOutPrintWriter().println(result);
1394 return 0;
1395 }
1396
1397 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001398 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001399 String opt;
1400 while ((opt = getNextOption()) != null) {
1401 switch (opt) {
1402 case "-s": {
1403 try {
1404 slotId = Integer.parseInt(getNextArgRequired());
1405 } catch (NumberFormatException e) {
1406 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1407 return -1;
1408 }
1409 break;
1410 }
1411 }
1412 }
1413 try {
1414 mInterface.enableIms(slotId);
1415 } catch (RemoteException e) {
1416 return -1;
1417 }
1418 if (VDBG) {
1419 Log.v(LOG_TAG, "ims enable -s " + slotId);
1420 }
1421 return 0;
1422 }
1423
1424 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001425 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001426 String opt;
1427 while ((opt = getNextOption()) != null) {
1428 switch (opt) {
1429 case "-s": {
1430 try {
1431 slotId = Integer.parseInt(getNextArgRequired());
1432 } catch (NumberFormatException e) {
1433 getErrPrintWriter().println(
1434 "ims disable requires an integer as a SLOT_ID.");
1435 return -1;
1436 }
1437 break;
1438 }
1439 }
1440 }
1441 try {
1442 mInterface.disableIms(slotId);
1443 } catch (RemoteException e) {
1444 return -1;
1445 }
1446 if (VDBG) {
1447 Log.v(LOG_TAG, "ims disable -s " + slotId);
1448 }
1449 return 0;
1450 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001451
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001452 private int handleCepChange() {
1453 Log.i(LOG_TAG, "handleCepChange");
1454 String opt = getNextArg();
1455 if (opt == null) {
1456 return -1;
1457 }
1458 boolean isCepEnabled = opt.equals("enable");
1459
1460 try {
1461 mInterface.setCepEnabled(isCepEnabled);
1462 } catch (RemoteException e) {
1463 return -1;
1464 }
1465 return 0;
1466 }
1467
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001468 private int getDefaultSlot() {
1469 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1470 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1471 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1472 // If there is no default, default to slot 0.
1473 slotId = DEFAULT_PHONE_ID;
1474 }
1475 return slotId;
1476 }
sqian2fff4a32018-11-05 14:18:37 -08001477
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001478 // Parse options related to Carrier Config Commands.
1479 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001480 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001481 CcOptionParseResult result = new CcOptionParseResult();
1482 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1483 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001484
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001485 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001486 while ((opt = getNextOption()) != null) {
1487 switch (opt) {
1488 case "-s": {
1489 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001490 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1491 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1492 errPw.println(tag + "No valid subscription found.");
1493 return null;
1494 }
1495
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001496 } catch (IllegalArgumentException e) {
1497 // Missing slot id
1498 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001499 return null;
1500 }
1501 break;
1502 }
1503 case "-p": {
1504 if (allowOptionPersistent) {
1505 result.mPersistent = true;
1506 } else {
1507 errPw.println(tag + "Unexpected option " + opt);
1508 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001509 }
1510 break;
1511 }
1512 default: {
1513 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001514 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001515 }
1516 }
1517 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001518 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001519 }
1520
1521 private int slotStringToSubId(String tag, String slotString) {
1522 int slotId = -1;
1523 try {
1524 slotId = Integer.parseInt(slotString);
1525 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001526 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1527 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1528 }
1529
1530 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001531 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1532 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1533 }
1534
Qiong Liuf25799b2020-09-10 10:13:46 +08001535 Phone phone = PhoneFactory.getPhone(slotId);
1536 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001537 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1538 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1539 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001540 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001541 }
1542
Hall Liud892bec2018-11-30 14:51:45 -08001543 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001544 // adb can run as root or as shell, depending on whether the device is rooted.
1545 return Binder.getCallingUid() == Process.SHELL_UID
1546 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001547 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001548
1549 private int handleCcCommand() {
1550 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1551 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001552 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001553 getErrPrintWriter().println("cc: Permission denied.");
1554 return -1;
1555 }
1556
1557 String arg = getNextArg();
1558 if (arg == null) {
1559 onHelpCc();
1560 return 0;
1561 }
1562
1563 switch (arg) {
1564 case CC_GET_VALUE: {
1565 return handleCcGetValue();
1566 }
1567 case CC_SET_VALUE: {
1568 return handleCcSetValue();
1569 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001570 case CC_SET_VALUES_FROM_XML: {
1571 return handleCcSetValuesFromXml();
1572 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001573 case CC_CLEAR_VALUES: {
1574 return handleCcClearValues();
1575 }
1576 default: {
1577 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1578 }
1579 }
1580 return -1;
1581 }
1582
1583 // cc get-value
1584 private int handleCcGetValue() {
1585 PrintWriter errPw = getErrPrintWriter();
1586 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1587 String key = null;
1588
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001589 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001590 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001591 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001592 return -1;
1593 }
1594
1595 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001596 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001597 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001598 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001599 return -1;
1600 }
1601
1602 // Get the key.
1603 key = getNextArg();
1604 if (key != null) {
1605 // A key was provided. Verify if it is a valid key
1606 if (!bundle.containsKey(key)) {
1607 errPw.println(tag + key + " is not a valid key.");
1608 return -1;
1609 }
1610
1611 // Print the carrier config value for key.
1612 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1613 } else {
1614 // No key provided. Show all values.
1615 // Iterate over a sorted list of all carrier config keys and print them.
1616 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1617 for (String k : sortedSet) {
1618 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1619 }
1620 }
1621 return 0;
1622 }
1623
1624 // cc set-value
1625 private int handleCcSetValue() {
1626 PrintWriter errPw = getErrPrintWriter();
1627 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1628
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001629 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001630 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001631 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001632 return -1;
1633 }
1634
1635 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001636 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001637 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001638 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001639 return -1;
1640 }
1641
1642 // Get the key.
1643 String key = getNextArg();
1644 if (key == null || key.equals("")) {
1645 errPw.println(tag + "KEY is missing");
1646 return -1;
1647 }
1648
1649 // Verify if the key is valid
1650 if (!originalValues.containsKey(key)) {
1651 errPw.println(tag + key + " is not a valid key.");
1652 return -1;
1653 }
1654
1655 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1656 ArrayList<String> valueList = new ArrayList<String>();
1657 while (peekNextArg() != null) {
1658 valueList.add(getNextArg());
1659 }
1660
1661 // Find the type of the carrier config value
1662 CcType type = getType(tag, key, originalValues);
1663 if (type == CcType.UNKNOWN) {
1664 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1665 return -1;
1666 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001667 if (type == CcType.PERSISTABLE_BUNDLE) {
1668 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1669 + "Use set-values-from-xml instead.");
1670 return -1;
1671 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001672
1673 // Create an override bundle containing the key and value that should be overriden.
1674 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1675 if (overrideBundle == null) {
1676 return -1;
1677 }
1678
1679 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001680 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001681
1682 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001683 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001684 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001685 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001686 return -1;
1687 }
1688
1689 // Print the original and new value.
1690 String originalValueString = ccValueToString(key, type, originalValues);
1691 String newValueString = ccValueToString(key, type, newValues);
1692 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1693 getOutPrintWriter().println("New value: \n" + newValueString);
1694
1695 return 0;
1696 }
1697
Allen Xuee00f0e2022-03-14 21:04:49 +00001698 // cc set-values-from-xml
1699 private int handleCcSetValuesFromXml() {
1700 PrintWriter errPw = getErrPrintWriter();
1701 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1702
1703 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001704 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001705 if (options == null) {
1706 return -1;
1707 }
1708
1709 // Get bundle containing all current carrier configuration values.
1710 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1711 if (originalValues == null) {
1712 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1713 return -1;
1714 }
1715
1716 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1717 if (overrideBundle == null) {
1718 return -1;
1719 }
1720
1721 // Verify all values are valid types
1722 for (String key : overrideBundle.keySet()) {
1723 CcType type = getType(tag, key, originalValues);
1724 if (type == CcType.UNKNOWN) {
1725 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1726 return -1;
1727 }
1728 }
1729
1730 // Override the value
1731 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1732
1733 // Find bundle containing all new carrier configuration values after the override.
1734 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1735 if (newValues == null) {
1736 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1737 return -1;
1738 }
1739
1740 // Print the original and new values
1741 overrideBundle.keySet().forEach(key -> {
1742 CcType type = getType(tag, key, originalValues);
1743 String originalValueString = ccValueToString(key, type, originalValues);
1744 String newValueString = ccValueToString(key, type, newValues);
1745 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1746 getOutPrintWriter().println("New value: \n" + newValueString);
1747 });
1748
1749 return 0;
1750 }
1751
1752 private PersistableBundle readPersistableBundleFromXml(String tag) {
1753 PersistableBundle subIdBundles;
1754 try {
1755 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1756 } catch (IOException | RuntimeException e) {
1757 PrintWriter errPw = getErrPrintWriter();
1758 errPw.println(tag + e);
1759 return null;
1760 }
1761
1762 return subIdBundles;
1763 }
1764
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001765 // cc clear-values
1766 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001767 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1768
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001769 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001770 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001771 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001772 return -1;
1773 }
1774
1775 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001776 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001777 getOutPrintWriter()
1778 .println("All previously set carrier config override values has been cleared");
1779 return 0;
1780 }
1781
1782 private CcType getType(String tag, String key, PersistableBundle bundle) {
1783 // Find the type by checking the type of the current value stored in the bundle.
1784 Object value = bundle.get(key);
1785
1786 if (CC_TYPE_MAP.containsKey(key)) {
1787 return CC_TYPE_MAP.get(key);
1788 } else if (value != null) {
1789 if (value instanceof Boolean) {
1790 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001791 }
1792 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001793 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001794 }
1795 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001796 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001797 }
1798 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001799 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001800 }
1801 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001802 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001803 }
1804 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001805 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001806 }
1807 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001808 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001809 }
1810 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001811 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001812 }
1813 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001814 return CcType.STRING_ARRAY;
1815 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001816 if (value instanceof PersistableBundle) {
1817 return CcType.PERSISTABLE_BUNDLE;
1818 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001819 } else {
1820 // Current value was null and can therefore not be used in order to find the type.
1821 // Check the name of the key to infer the type. This check is not needed for primitive
1822 // data types (boolean, double, int and long), since they can not be null.
1823 if (key.endsWith("double_array")) {
1824 return CcType.DOUBLE_ARRAY;
1825 }
1826 if (key.endsWith("int_array")) {
1827 return CcType.INT_ARRAY;
1828 }
1829 if (key.endsWith("long_array")) {
1830 return CcType.LONG_ARRAY;
1831 }
1832 if (key.endsWith("string")) {
1833 return CcType.STRING;
1834 }
1835 if (key.endsWith("string_array") || key.endsWith("strings")) {
1836 return CcType.STRING_ARRAY;
1837 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001838 if (key.endsWith("bundle")) {
1839 return CcType.PERSISTABLE_BUNDLE;
1840 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001841 }
1842
1843 // Not possible to infer the type by looking at the current value or the key.
1844 PrintWriter errPw = getErrPrintWriter();
1845 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1846 return CcType.UNKNOWN;
1847 }
1848
1849 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1850 String result;
1851 StringBuilder valueString = new StringBuilder();
1852 String typeString = type.toString();
1853 Object value = bundle.get(key);
1854
1855 if (value == null) {
1856 valueString.append("null");
1857 } else {
1858 switch (type) {
1859 case DOUBLE_ARRAY: {
1860 // Format the string representation of the int array as value1 value2......
1861 double[] valueArray = (double[]) value;
1862 for (int i = 0; i < valueArray.length; i++) {
1863 if (i != 0) {
1864 valueString.append(" ");
1865 }
1866 valueString.append(valueArray[i]);
1867 }
1868 break;
1869 }
1870 case INT_ARRAY: {
1871 // Format the string representation of the int array as value1 value2......
1872 int[] valueArray = (int[]) value;
1873 for (int i = 0; i < valueArray.length; i++) {
1874 if (i != 0) {
1875 valueString.append(" ");
1876 }
1877 valueString.append(valueArray[i]);
1878 }
1879 break;
1880 }
1881 case LONG_ARRAY: {
1882 // Format the string representation of the int array as value1 value2......
1883 long[] valueArray = (long[]) value;
1884 for (int i = 0; i < valueArray.length; i++) {
1885 if (i != 0) {
1886 valueString.append(" ");
1887 }
1888 valueString.append(valueArray[i]);
1889 }
1890 break;
1891 }
1892 case STRING: {
1893 valueString.append("\"" + value.toString() + "\"");
1894 break;
1895 }
1896 case STRING_ARRAY: {
1897 // Format the string representation of the string array as "value1" "value2"....
1898 String[] valueArray = (String[]) value;
1899 for (int i = 0; i < valueArray.length; i++) {
1900 if (i != 0) {
1901 valueString.append(" ");
1902 }
1903 if (valueArray[i] != null) {
1904 valueString.append("\"" + valueArray[i] + "\"");
1905 } else {
1906 valueString.append("null");
1907 }
1908 }
1909 break;
1910 }
1911 default: {
1912 valueString.append(value.toString());
1913 }
1914 }
1915 }
1916 return String.format("%-70s %-15s %s", key, typeString, valueString);
1917 }
1918
1919 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1920 ArrayList<String> valueList) {
1921 PrintWriter errPw = getErrPrintWriter();
1922 PersistableBundle bundle = new PersistableBundle();
1923
1924 // First verify that a valid number of values has been provided for the type.
1925 switch (type) {
1926 case BOOLEAN:
1927 case DOUBLE:
1928 case INT:
1929 case LONG: {
1930 if (valueList.size() != 1) {
1931 errPw.println(tag + "Expected 1 value for type " + type
1932 + ". Found: " + valueList.size());
1933 return null;
1934 }
1935 break;
1936 }
1937 case STRING: {
1938 if (valueList.size() > 1) {
1939 errPw.println(tag + "Expected 0 or 1 values for type " + type
1940 + ". Found: " + valueList.size());
1941 return null;
1942 }
1943 break;
1944 }
1945 }
1946
1947 // Parse the value according to type and add it to the Bundle.
1948 switch (type) {
1949 case BOOLEAN: {
1950 if ("true".equalsIgnoreCase(valueList.get(0))) {
1951 bundle.putBoolean(key, true);
1952 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1953 bundle.putBoolean(key, false);
1954 } else {
1955 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1956 return null;
1957 }
1958 break;
1959 }
1960 case DOUBLE: {
1961 try {
1962 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1963 } catch (NumberFormatException nfe) {
1964 // Not a valid double
1965 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1966 return null;
1967 }
1968 break;
1969 }
1970 case DOUBLE_ARRAY: {
1971 double[] valueDoubleArray = null;
1972 if (valueList.size() > 0) {
1973 valueDoubleArray = new double[valueList.size()];
1974 for (int i = 0; i < valueList.size(); i++) {
1975 try {
1976 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1977 } catch (NumberFormatException nfe) {
1978 // Not a valid double
1979 errPw.println(
1980 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1981 return null;
1982 }
1983 }
1984 }
1985 bundle.putDoubleArray(key, valueDoubleArray);
1986 break;
1987 }
1988 case INT: {
1989 try {
1990 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1991 } catch (NumberFormatException nfe) {
1992 // Not a valid integer
1993 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1994 return null;
1995 }
1996 break;
1997 }
1998 case INT_ARRAY: {
1999 int[] valueIntArray = null;
2000 if (valueList.size() > 0) {
2001 valueIntArray = new int[valueList.size()];
2002 for (int i = 0; i < valueList.size(); i++) {
2003 try {
2004 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2005 } catch (NumberFormatException nfe) {
2006 // Not a valid integer
2007 errPw.println(tag
2008 + "Unable to parse " + valueList.get(i) + " as an integer.");
2009 return null;
2010 }
2011 }
2012 }
2013 bundle.putIntArray(key, valueIntArray);
2014 break;
2015 }
2016 case LONG: {
2017 try {
2018 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2019 } catch (NumberFormatException nfe) {
2020 // Not a valid long
2021 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2022 return null;
2023 }
2024 break;
2025 }
2026 case LONG_ARRAY: {
2027 long[] valueLongArray = null;
2028 if (valueList.size() > 0) {
2029 valueLongArray = new long[valueList.size()];
2030 for (int i = 0; i < valueList.size(); i++) {
2031 try {
2032 valueLongArray[i] = Long.parseLong(valueList.get(i));
2033 } catch (NumberFormatException nfe) {
2034 // Not a valid long
2035 errPw.println(
2036 tag + "Unable to parse " + valueList.get(i) + " as a long");
2037 return null;
2038 }
2039 }
2040 }
2041 bundle.putLongArray(key, valueLongArray);
2042 break;
2043 }
2044 case STRING: {
2045 String value = null;
2046 if (valueList.size() > 0) {
2047 value = valueList.get(0);
2048 }
2049 bundle.putString(key, value);
2050 break;
2051 }
2052 case STRING_ARRAY: {
2053 String[] valueStringArray = null;
2054 if (valueList.size() > 0) {
2055 valueStringArray = new String[valueList.size()];
2056 valueList.toArray(valueStringArray);
2057 }
2058 bundle.putStringArray(key, valueStringArray);
2059 break;
2060 }
2061 }
2062 return bundle;
2063 }
Shuo Qian489d9282020-07-09 11:30:03 -07002064
2065 private int handleEndBlockSuppressionCommand() {
2066 if (!checkShellUid()) {
2067 return -1;
2068 }
2069
2070 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2071 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2072 }
2073 return 0;
2074 }
Hui Wang641e81c2020-10-12 12:14:23 -07002075
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002076 private int handleEuiccCommand() {
2077 String arg = getNextArg();
2078 if (arg == null) {
2079 onHelpEuicc();
2080 return 0;
2081 }
2082
2083 switch (arg) {
2084 case EUICC_SET_UI_COMPONENT: {
2085 return handleEuiccServiceCommand();
2086 }
2087 }
2088 return -1;
2089 }
2090
2091 private int handleEuiccServiceCommand() {
2092 String uiComponent = getNextArg();
2093 String packageName = getNextArg();
2094 if (packageName == null || uiComponent == null) {
2095 return -1;
2096 }
2097 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2098 if (VDBG) {
2099 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2100 + packageName);
2101 }
2102 return 0;
2103 }
2104
Michele Berionne54af4632020-12-28 20:23:16 +00002105 private int handleRestartModemCommand() {
2106 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2107 // non user build.
2108 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2109 getErrPrintWriter().println("RestartModem: Permission denied.");
2110 return -1;
2111 }
2112
2113 boolean result = TelephonyManager.getDefault().rebootRadio();
2114 getOutPrintWriter().println(result);
2115
2116 return result ? 0 : -1;
2117 }
2118
Ling Ma4fbab492022-01-25 22:36:16 +00002119 private int handleGetImei() {
2120 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2121 // non user build.
2122 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2123 getErrPrintWriter().println("Device IMEI: Permission denied.");
2124 return -1;
2125 }
2126
2127 final long identity = Binder.clearCallingIdentity();
2128
2129 String imei = null;
2130 String arg = getNextArg();
2131 if (arg != null) {
2132 try {
2133 int specifiedSlotIndex = Integer.parseInt(arg);
2134 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2135 } catch (NumberFormatException exception) {
2136 PrintWriter errPw = getErrPrintWriter();
2137 errPw.println("-s requires an integer as slot index.");
2138 return -1;
2139 }
2140
2141 } else {
2142 imei = TelephonyManager.from(mContext).getImei();
2143 }
2144 getOutPrintWriter().println("Device IMEI: " + imei);
2145
2146 Binder.restoreCallingIdentity(identity);
2147 return 0;
2148 }
2149
Michele Berionne5e411512020-11-13 02:36:59 +00002150 private int handleUnattendedReboot() {
2151 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2152 // non user build.
2153 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2154 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2155 return -1;
2156 }
2157
2158 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2159 getOutPrintWriter().println("result: " + result);
2160
2161 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2162 }
2163
Aman Gupta07124872022-02-09 08:02:14 +00002164 private int handleGetSimSlotsMapping() {
2165 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2166 // non user build.
2167 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2168 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2169 return -1;
2170 }
2171 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2172 String result = telephonyManager.getSimSlotMapping().toString();
2173 getOutPrintWriter().println("simSlotsMapping: " + result);
2174
2175 return 0;
2176 }
2177
Hui Wang641e81c2020-10-12 12:14:23 -07002178 private int handleGbaCommand() {
2179 String arg = getNextArg();
2180 if (arg == null) {
2181 onHelpGba();
2182 return 0;
2183 }
2184
2185 switch (arg) {
2186 case GBA_SET_SERVICE: {
2187 return handleGbaSetServiceCommand();
2188 }
2189 case GBA_GET_SERVICE: {
2190 return handleGbaGetServiceCommand();
2191 }
2192 case GBA_SET_RELEASE_TIME: {
2193 return handleGbaSetReleaseCommand();
2194 }
2195 case GBA_GET_RELEASE_TIME: {
2196 return handleGbaGetReleaseCommand();
2197 }
2198 }
2199
2200 return -1;
2201 }
2202
2203 private int getSubId(String cmd) {
2204 int slotId = getDefaultSlot();
2205 String opt = getNextOption();
2206 if (opt != null && opt.equals("-s")) {
2207 try {
2208 slotId = Integer.parseInt(getNextArgRequired());
2209 } catch (NumberFormatException e) {
2210 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2211 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2212 }
2213 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002214 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002215 }
2216
2217 private int handleGbaSetServiceCommand() {
2218 int subId = getSubId("gba set-service");
2219 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2220 return -1;
2221 }
2222
2223 String packageName = getNextArg();
2224 try {
2225 if (packageName == null) {
2226 packageName = "";
2227 }
2228 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2229 if (VDBG) {
2230 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2231 + packageName + ", result=" + result);
2232 }
2233 getOutPrintWriter().println(result);
2234 } catch (RemoteException e) {
2235 Log.w(LOG_TAG, "gba set-service " + subId + " "
2236 + packageName + ", error" + e.getMessage());
2237 getErrPrintWriter().println("Exception: " + e.getMessage());
2238 return -1;
2239 }
2240 return 0;
2241 }
2242
2243 private int handleGbaGetServiceCommand() {
2244 String result;
2245
2246 int subId = getSubId("gba get-service");
2247 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2248 return -1;
2249 }
2250
2251 try {
2252 result = mInterface.getBoundGbaService(subId);
2253 } catch (RemoteException e) {
2254 return -1;
2255 }
2256 if (VDBG) {
2257 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2258 }
2259 getOutPrintWriter().println(result);
2260 return 0;
2261 }
2262
2263 private int handleGbaSetReleaseCommand() {
2264 //the release time value could be -1
2265 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2266 : SubscriptionManager.getDefaultSubscriptionId();
2267 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2268 return -1;
2269 }
2270
2271 String intervalStr = getNextArg();
2272 if (intervalStr == null) {
2273 return -1;
2274 }
2275
2276 try {
2277 int interval = Integer.parseInt(intervalStr);
2278 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2279 if (VDBG) {
2280 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2281 + intervalStr + ", result=" + result);
2282 }
2283 getOutPrintWriter().println(result);
2284 } catch (NumberFormatException | RemoteException e) {
2285 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2286 + intervalStr + ", error" + e.getMessage());
2287 getErrPrintWriter().println("Exception: " + e.getMessage());
2288 return -1;
2289 }
2290 return 0;
2291 }
2292
2293 private int handleGbaGetReleaseCommand() {
2294 int subId = getSubId("gba get-release");
2295 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2296 return -1;
2297 }
2298
2299 int result = 0;
2300 try {
2301 result = mInterface.getGbaReleaseTime(subId);
2302 } catch (RemoteException e) {
2303 return -1;
2304 }
2305 if (VDBG) {
2306 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2307 }
2308 getOutPrintWriter().println(result);
2309 return 0;
2310 }
Hui Wang761a6682020-10-31 05:12:53 +00002311
2312 private int handleSingleRegistrationConfigCommand() {
2313 String arg = getNextArg();
2314 if (arg == null) {
2315 onHelpSrc();
2316 return 0;
2317 }
2318
2319 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002320 case SRC_SET_TEST_ENABLED: {
2321 return handleSrcSetTestEnabledCommand();
2322 }
2323 case SRC_GET_TEST_ENABLED: {
2324 return handleSrcGetTestEnabledCommand();
2325 }
Hui Wang761a6682020-10-31 05:12:53 +00002326 case SRC_SET_DEVICE_ENABLED: {
2327 return handleSrcSetDeviceEnabledCommand();
2328 }
2329 case SRC_GET_DEVICE_ENABLED: {
2330 return handleSrcGetDeviceEnabledCommand();
2331 }
2332 case SRC_SET_CARRIER_ENABLED: {
2333 return handleSrcSetCarrierEnabledCommand();
2334 }
2335 case SRC_GET_CARRIER_ENABLED: {
2336 return handleSrcGetCarrierEnabledCommand();
2337 }
Hui Wangb647abe2021-02-26 09:33:38 -08002338 case SRC_SET_FEATURE_ENABLED: {
2339 return handleSrcSetFeatureValidationCommand();
2340 }
2341 case SRC_GET_FEATURE_ENABLED: {
2342 return handleSrcGetFeatureValidationCommand();
2343 }
Hui Wang761a6682020-10-31 05:12:53 +00002344 }
2345
2346 return -1;
2347 }
2348
James.cf Linbcdf8b32021-01-14 16:44:13 +08002349 private int handleRcsUceCommand() {
2350 String arg = getNextArg();
2351 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002352 onHelpUce();
2353 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002354 }
2355
2356 switch (arg) {
2357 case UCE_REMOVE_EAB_CONTACT:
2358 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002359 case UCE_GET_EAB_CONTACT:
2360 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002361 case UCE_GET_EAB_CAPABILITY:
2362 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002363 case UCE_GET_DEVICE_ENABLED:
2364 return handleUceGetDeviceEnabledCommand();
2365 case UCE_SET_DEVICE_ENABLED:
2366 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002367 case UCE_OVERRIDE_PUBLISH_CAPS:
2368 return handleUceOverridePublishCaps();
2369 case UCE_GET_LAST_PIDF_XML:
2370 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002371 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2372 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002373 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2374 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002375 }
2376 return -1;
2377 }
2378
2379 private int handleRemovingEabContactCommand() {
2380 int subId = getSubId("uce remove-eab-contact");
2381 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2382 return -1;
2383 }
2384
2385 String phoneNumber = getNextArgRequired();
2386 if (TextUtils.isEmpty(phoneNumber)) {
2387 return -1;
2388 }
2389 int result = 0;
2390 try {
2391 result = mInterface.removeContactFromEab(subId, phoneNumber);
2392 } catch (RemoteException e) {
2393 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2394 getErrPrintWriter().println("Exception: " + e.getMessage());
2395 return -1;
2396 }
2397
2398 if (VDBG) {
2399 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2400 }
calvinpan293ea1b2021-02-04 17:52:13 +08002401 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002402 }
2403
calvinpane4a8a1d2021-01-25 13:51:18 +08002404 private int handleGettingEabContactCommand() {
2405 String phoneNumber = getNextArgRequired();
2406 if (TextUtils.isEmpty(phoneNumber)) {
2407 return -1;
2408 }
2409 String result = "";
2410 try {
2411 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002412 } catch (RemoteException e) {
2413 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2414 getErrPrintWriter().println("Exception: " + e.getMessage());
2415 return -1;
2416 }
2417
2418 if (VDBG) {
2419 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2420 }
calvinpan293ea1b2021-02-04 17:52:13 +08002421 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002422 return 0;
2423 }
2424
Calvin Pana1434322021-07-01 19:27:01 +08002425 private int handleGettingEabCapabilityCommand() {
2426 String phoneNumber = getNextArgRequired();
2427 if (TextUtils.isEmpty(phoneNumber)) {
2428 return -1;
2429 }
2430 String result = "";
2431 try {
2432 result = mInterface.getCapabilityFromEab(phoneNumber);
2433 } catch (RemoteException e) {
2434 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2435 getErrPrintWriter().println("Exception: " + e.getMessage());
2436 return -1;
2437 }
2438
2439 if (VDBG) {
2440 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2441 }
2442 getOutPrintWriter().println(result);
2443 return 0;
2444 }
2445
James.cf Lin4b784aa2021-01-31 03:25:15 +08002446 private int handleUceGetDeviceEnabledCommand() {
2447 boolean result = false;
2448 try {
2449 result = mInterface.getDeviceUceEnabled();
2450 } catch (RemoteException e) {
2451 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2452 return -1;
2453 }
2454 if (VDBG) {
2455 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2456 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002457 getOutPrintWriter().println(result);
2458 return 0;
2459 }
2460
James.cf Lin4b784aa2021-01-31 03:25:15 +08002461 private int handleUceSetDeviceEnabledCommand() {
2462 String enabledStr = getNextArg();
2463 if (TextUtils.isEmpty(enabledStr)) {
2464 return -1;
2465 }
2466
2467 try {
2468 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2469 mInterface.setDeviceUceEnabled(isEnabled);
2470 if (VDBG) {
2471 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2472 }
2473 } catch (NumberFormatException | RemoteException e) {
2474 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2475 getErrPrintWriter().println("Exception: " + e.getMessage());
2476 return -1;
2477 }
2478 return 0;
2479 }
2480
James.cf Line8713a42021-04-29 16:04:26 +08002481 private int handleUceRemoveRequestDisallowedStatus() {
2482 int subId = getSubId("uce remove-request-disallowed-status");
2483 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2484 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2485 return -1;
2486 }
2487 boolean result;
2488 try {
2489 result = mInterface.removeUceRequestDisallowedStatus(subId);
2490 } catch (RemoteException e) {
2491 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2492 return -1;
2493 }
2494 if (VDBG) {
2495 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2496 }
2497 getOutPrintWriter().println(result);
2498 return 0;
2499 }
2500
James.cf Lin0fc71b02021-05-25 01:37:38 +08002501 private int handleUceSetCapRequestTimeout() {
2502 int subId = getSubId("uce set-capabilities-request-timeout");
2503 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2504 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2505 return -1;
2506 }
2507 long timeoutAfterMs = Long.valueOf(getNextArg());
2508 boolean result;
2509 try {
2510 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2511 } catch (RemoteException e) {
2512 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2513 return -1;
2514 }
2515 if (VDBG) {
2516 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2517 }
2518 getOutPrintWriter().println(result);
2519 return 0;
2520 }
2521
Hui Wangbaaee6a2021-02-19 20:45:36 -08002522 private int handleSrcSetTestEnabledCommand() {
2523 String enabledStr = getNextArg();
2524 if (enabledStr == null) {
2525 return -1;
2526 }
2527
2528 try {
2529 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2530 if (VDBG) {
2531 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2532 }
2533 getOutPrintWriter().println("Done");
2534 } catch (NumberFormatException | RemoteException e) {
2535 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2536 getErrPrintWriter().println("Exception: " + e.getMessage());
2537 return -1;
2538 }
2539 return 0;
2540 }
2541
2542 private int handleSrcGetTestEnabledCommand() {
2543 boolean result = false;
2544 try {
2545 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2546 } catch (RemoteException e) {
2547 return -1;
2548 }
2549 if (VDBG) {
2550 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2551 }
2552 getOutPrintWriter().println(result);
2553 return 0;
2554 }
2555
Brad Ebinger14d467f2021-02-12 06:18:28 +00002556 private int handleUceOverridePublishCaps() {
2557 int subId = getSubId("uce override-published-caps");
2558 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2559 return -1;
2560 }
2561 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2562 String operation = getNextArgRequired();
2563 String caps = getNextArg();
2564 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2565 && !"list".equals(operation)) {
2566 getErrPrintWriter().println("Invalid operation: " + operation);
2567 return -1;
2568 }
2569
2570 // add/remove requires capabilities to be specified.
2571 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2572 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2573 + "specified");
2574 return -1;
2575 }
2576
2577 ArraySet<String> capSet = new ArraySet<>();
2578 if (!TextUtils.isEmpty(caps)) {
2579 String[] capArray = caps.split(":");
2580 for (String cap : capArray) {
2581 // Allow unknown tags to be passed in as well.
2582 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2583 }
2584 }
2585
2586 RcsContactUceCapability result = null;
2587 try {
2588 switch (operation) {
2589 case "add":
2590 result = mInterface.addUceRegistrationOverrideShell(subId,
2591 new ArrayList<>(capSet));
2592 break;
2593 case "remove":
2594 result = mInterface.removeUceRegistrationOverrideShell(subId,
2595 new ArrayList<>(capSet));
2596 break;
2597 case "clear":
2598 result = mInterface.clearUceRegistrationOverrideShell(subId);
2599 break;
2600 case "list":
2601 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2602 break;
2603 }
2604 } catch (RemoteException e) {
2605 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2606 getErrPrintWriter().println("Exception: " + e.getMessage());
2607 return -1;
2608 } catch (ServiceSpecificException sse) {
2609 // Reconstruct ImsException
2610 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2611 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2612 getErrPrintWriter().println("Exception: " + imsException);
2613 return -1;
2614 }
2615 if (result == null) {
2616 getErrPrintWriter().println("Service not available");
2617 return -1;
2618 }
2619 getOutPrintWriter().println(result);
2620 return 0;
2621 }
2622
2623 private int handleUceGetPidfXml() {
2624 int subId = getSubId("uce get-last-publish-pidf");
2625 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2626 return -1;
2627 }
2628
2629 String result;
2630 try {
2631 result = mInterface.getLastUcePidfXmlShell(subId);
2632 } catch (RemoteException e) {
2633 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2634 getErrPrintWriter().println("Exception: " + e.getMessage());
2635 return -1;
2636 } catch (ServiceSpecificException sse) {
2637 // Reconstruct ImsException
2638 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2639 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2640 getErrPrintWriter().println("Exception: " + imsException);
2641 return -1;
2642 }
2643 if (result == null) {
2644 getErrPrintWriter().println("Service not available");
2645 return -1;
2646 }
2647 getOutPrintWriter().println(result);
2648 return 0;
2649 }
2650
Hui Wang761a6682020-10-31 05:12:53 +00002651 private int handleSrcSetDeviceEnabledCommand() {
2652 String enabledStr = getNextArg();
2653 if (enabledStr == null) {
2654 return -1;
2655 }
2656
2657 try {
2658 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2659 if (VDBG) {
2660 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2661 }
2662 getOutPrintWriter().println("Done");
2663 } catch (NumberFormatException | RemoteException e) {
2664 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2665 getErrPrintWriter().println("Exception: " + e.getMessage());
2666 return -1;
2667 }
2668 return 0;
2669 }
2670
2671 private int handleSrcGetDeviceEnabledCommand() {
2672 boolean result = false;
2673 try {
2674 result = mInterface.getDeviceSingleRegistrationEnabled();
2675 } catch (RemoteException e) {
2676 return -1;
2677 }
2678 if (VDBG) {
2679 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2680 }
2681 getOutPrintWriter().println(result);
2682 return 0;
2683 }
2684
2685 private int handleSrcSetCarrierEnabledCommand() {
2686 //the release time value could be -1
2687 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2688 : SubscriptionManager.getDefaultSubscriptionId();
2689 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2690 return -1;
2691 }
2692
2693 String enabledStr = getNextArg();
2694 if (enabledStr == null) {
2695 return -1;
2696 }
2697
2698 try {
2699 boolean result =
2700 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2701 if (VDBG) {
2702 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2703 + enabledStr + ", result=" + result);
2704 }
2705 getOutPrintWriter().println(result);
2706 } catch (NumberFormatException | RemoteException e) {
2707 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2708 + enabledStr + ", error" + e.getMessage());
2709 getErrPrintWriter().println("Exception: " + e.getMessage());
2710 return -1;
2711 }
2712 return 0;
2713 }
2714
2715 private int handleSrcGetCarrierEnabledCommand() {
2716 int subId = getSubId("src get-carrier-enabled");
2717 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2718 return -1;
2719 }
2720
2721 boolean result = false;
2722 try {
2723 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2724 } catch (RemoteException e) {
2725 return -1;
2726 }
2727 if (VDBG) {
2728 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2729 }
2730 getOutPrintWriter().println(result);
2731 return 0;
2732 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002733
Hui Wangb647abe2021-02-26 09:33:38 -08002734 private int handleSrcSetFeatureValidationCommand() {
2735 //the release time value could be -1
2736 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2737 : SubscriptionManager.getDefaultSubscriptionId();
2738 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2739 return -1;
2740 }
2741
2742 String enabledStr = getNextArg();
2743 if (enabledStr == null) {
2744 return -1;
2745 }
2746
2747 try {
2748 boolean result =
2749 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2750 if (VDBG) {
2751 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2752 + enabledStr + ", result=" + result);
2753 }
2754 getOutPrintWriter().println(result);
2755 } catch (NumberFormatException | RemoteException e) {
2756 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2757 + enabledStr + ", error" + e.getMessage());
2758 getErrPrintWriter().println("Exception: " + e.getMessage());
2759 return -1;
2760 }
2761 return 0;
2762 }
2763
2764 private int handleSrcGetFeatureValidationCommand() {
2765 int subId = getSubId("src get-feature-validation");
2766 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2767 return -1;
2768 }
2769
2770 Boolean result = false;
2771 try {
2772 result = mInterface.getImsFeatureValidationOverride(subId);
2773 } catch (RemoteException e) {
2774 return -1;
2775 }
2776 if (VDBG) {
2777 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2778 }
2779 getOutPrintWriter().println(result);
2780 return 0;
2781 }
2782
2783
Hall Liuaa4211e2021-01-20 15:43:39 -08002784 private void onHelpCallComposer() {
2785 PrintWriter pw = getOutPrintWriter();
2786 pw.println("Call composer commands");
2787 pw.println(" callcomposer test-mode enable|disable|query");
2788 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2789 pw.println(" upload/download from carrier servers is disabled, and operations are");
2790 pw.println(" performed using emulated local files instead.");
2791 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2792 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2793 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002794 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2795 pw.println(" Enables or disables the user setting for call composer, as set by");
2796 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002797 }
2798
2799 private int handleCallComposerCommand() {
2800 String arg = getNextArg();
2801 if (arg == null) {
2802 onHelpCallComposer();
2803 return 0;
2804 }
2805
2806 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2807 "MODIFY_PHONE_STATE required for call composer shell cmds");
2808 switch (arg) {
2809 case CALL_COMPOSER_TEST_MODE: {
2810 String enabledStr = getNextArg();
2811 if (ENABLE.equals(enabledStr)) {
2812 CallComposerPictureManager.sTestMode = true;
2813 } else if (DISABLE.equals(enabledStr)) {
2814 CallComposerPictureManager.sTestMode = false;
2815 } else if (QUERY.equals(enabledStr)) {
2816 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2817 } else {
2818 onHelpCallComposer();
2819 return 1;
2820 }
2821 break;
2822 }
2823 case CALL_COMPOSER_SIMULATE_CALL: {
2824 int subscriptionId = Integer.valueOf(getNextArg());
2825 String uuidString = getNextArg();
2826 UUID uuid = UUID.fromString(uuidString);
2827 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2828 Binder.withCleanCallingIdentity(() -> {
2829 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2830 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2831 });
2832 try {
2833 Uri uri = storageUriFuture.get();
2834 getOutPrintWriter().println(String.valueOf(uri));
2835 } catch (Exception e) {
2836 throw new RuntimeException(e);
2837 }
2838 break;
2839 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002840 case CALL_COMPOSER_USER_SETTING: {
2841 try {
2842 int subscriptionId = Integer.valueOf(getNextArg());
2843 String enabledStr = getNextArg();
2844 if (ENABLE.equals(enabledStr)) {
2845 mInterface.setCallComposerStatus(subscriptionId,
2846 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2847 } else if (DISABLE.equals(enabledStr)) {
2848 mInterface.setCallComposerStatus(subscriptionId,
2849 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2850 } else if (QUERY.equals(enabledStr)) {
2851 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2852 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2853 } else {
2854 onHelpCallComposer();
2855 return 1;
2856 }
2857 } catch (RemoteException e) {
2858 e.printStackTrace(getOutPrintWriter());
2859 return 1;
2860 }
2861 break;
2862 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002863 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002864 return 0;
2865 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002866
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002867 private int handleHasCarrierPrivilegesCommand() {
2868 String packageName = getNextArgRequired();
2869
2870 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002871 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002872 try {
2873 hasCarrierPrivileges =
2874 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2875 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2876 } catch (RemoteException e) {
2877 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2878 getErrPrintWriter().println("Exception: " + e.getMessage());
2879 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002880 } finally {
2881 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002882 }
2883
2884 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002885 return 0;
2886 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002887
2888 private int handleAllowedNetworkTypesCommand(String command) {
2889 if (!checkShellUid()) {
2890 return -1;
2891 }
2892
2893 PrintWriter errPw = getErrPrintWriter();
2894 String tag = command + ": ";
2895 String opt;
2896 int subId = -1;
2897 Log.v(LOG_TAG, command + " start");
2898
2899 while ((opt = getNextOption()) != null) {
2900 if (opt.equals("-s")) {
2901 try {
2902 subId = slotStringToSubId(tag, getNextArgRequired());
2903 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2904 errPw.println(tag + "No valid subscription found.");
2905 return -1;
2906 }
2907 } catch (IllegalArgumentException e) {
2908 // Missing slot id
2909 errPw.println(tag + "SLOT_ID expected after -s.");
2910 return -1;
2911 }
2912 } else {
2913 errPw.println(tag + "Unknown option " + opt);
2914 return -1;
2915 }
2916 }
2917
2918 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2919 return handleGetAllowedNetworkTypesCommand(subId);
2920 }
2921 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2922 return handleSetAllowedNetworkTypesCommand(subId);
2923 }
2924 return -1;
2925 }
2926
2927 private int handleGetAllowedNetworkTypesCommand(int subId) {
2928 PrintWriter errPw = getErrPrintWriter();
2929
2930 long result = -1;
2931 try {
2932 if (mInterface != null) {
2933 result = mInterface.getAllowedNetworkTypesForReason(subId,
2934 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2935 } else {
2936 throw new IllegalStateException("telephony service is null.");
2937 }
2938 } catch (RemoteException e) {
2939 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2940 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2941 return -1;
2942 }
2943
2944 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2945 return 0;
2946 }
2947
2948 private int handleSetAllowedNetworkTypesCommand(int subId) {
2949 PrintWriter errPw = getErrPrintWriter();
2950
2951 String bitmaskString = getNextArg();
2952 if (TextUtils.isEmpty(bitmaskString)) {
2953 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2954 return -1;
2955 }
2956 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2957 if (allowedNetworkTypes < 0) {
2958 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2959 return -1;
2960 }
2961 boolean result = false;
2962 try {
2963 if (mInterface != null) {
2964 result = mInterface.setAllowedNetworkTypesForReason(subId,
2965 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2966 } else {
2967 throw new IllegalStateException("telephony service is null.");
2968 }
2969 } catch (RemoteException e) {
2970 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2971 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2972 return -1;
2973 }
2974
2975 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2976 if (result) {
2977 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2978 }
2979 getOutPrintWriter().println(resultMessage);
2980 return 0;
2981 }
2982
2983 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2984 if (TextUtils.isEmpty(bitmaskString)) {
2985 return -1;
2986 }
2987 if (VDBG) {
2988 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2989 + ", length: " + bitmaskString.length());
2990 }
2991 try {
2992 return Long.parseLong(bitmaskString, 2);
2993 } catch (NumberFormatException e) {
2994 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2995 return -1;
2996 }
2997 }
Jack Yu4c0a5502021-12-03 23:58:26 -08002998
jimsun3b9ccac2021-10-26 15:01:23 +08002999 private int handleRadioSetModemServiceCommand() {
3000 PrintWriter errPw = getErrPrintWriter();
3001 String serviceName = null;
3002
3003 String opt;
3004 while ((opt = getNextOption()) != null) {
3005 switch (opt) {
3006 case "-s": {
3007 serviceName = getNextArgRequired();
3008 break;
3009 }
3010 }
3011 }
3012
3013 try {
3014 boolean result = mInterface.setModemService(serviceName);
3015 if (VDBG) {
3016 Log.v(LOG_TAG,
3017 "RadioSetModemService " + serviceName + ", result = " + result);
3018 }
3019 getOutPrintWriter().println(result);
3020 } catch (RemoteException e) {
3021 Log.w(LOG_TAG,
3022 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3023 errPw.println("Exception: " + e.getMessage());
3024 return -1;
3025 }
3026 return 0;
3027 }
3028
3029 private int handleRadioGetModemServiceCommand() {
3030 PrintWriter errPw = getErrPrintWriter();
3031 String result;
3032
3033 try {
3034 result = mInterface.getModemService();
3035 getOutPrintWriter().println(result);
3036 } catch (RemoteException e) {
3037 errPw.println("Exception: " + e.getMessage());
3038 return -1;
3039 }
3040 if (VDBG) {
3041 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3042 }
3043 return 0;
3044 }
3045
3046 private int handleRadioCommand() {
3047 String arg = getNextArg();
3048 if (arg == null) {
3049 onHelpRadio();
3050 return 0;
3051 }
3052
3053 switch (arg) {
3054 case RADIO_SET_MODEM_SERVICE:
3055 return handleRadioSetModemServiceCommand();
3056
3057 case RADIO_GET_MODEM_SERVICE:
3058 return handleRadioGetModemServiceCommand();
3059 }
3060
3061 return -1;
3062 }
arunvoddud7401012022-12-15 16:08:12 +00003063
3064 private int handleCarrierRestrictionStatusCommand() {
3065 try {
3066 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3067 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3068 mInterface.getModemService()))) {
3069 Log.v(LOG_TAG,
3070 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3071 + " checkShellUid fails");
3072 return -1;
3073 }
3074 } catch (RemoteException ex) {
3075 ex.printStackTrace();
3076 }
3077 String callerInfo = getNextOption();
3078 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3079 if (TextUtils.isEmpty(callerInfo)) {
3080 // reset the Json content after testing
3081 allowListInfo.updateJsonForTest(null);
3082 return 0;
3083 }
3084 if (callerInfo.startsWith("--")) {
3085 callerInfo = callerInfo.replace("--", "");
3086 }
3087 String params[] = callerInfo.split(",");
3088 StringBuffer jsonStrBuffer = new StringBuffer();
3089 String tokens;
3090 for (int index = 0; index < params.length; index++) {
3091 tokens = convertToJsonString(index, params[index]);
3092 if (TextUtils.isEmpty(tokens)) {
3093 // received wrong format from CTS
3094 if (VDBG) {
3095 Log.v(LOG_TAG,
3096 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3097 }
3098 return -1;
3099 }
3100 jsonStrBuffer.append(tokens);
3101 }
3102 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3103 return result;
3104 }
3105
3106
3107 /**
3108 * Building the string that can be used to build the JsonObject which supports to stub the data
3109 * in CarrierAllowListInfo for CTS testing. sample format is like
3110 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3111 */
3112 private String convertToJsonString(int index, String param) {
3113
3114 String token[] = param.split(":");
3115 String jSonString;
3116 switch (index) {
3117 case 0:
3118 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3119 break;
3120 case 1:
3121 jSonString =
3122 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3123 break;
3124 case 2:
3125 jSonString =
3126 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3127 break;
3128 default:
3129 jSonString = null;
3130 }
3131 return jSonString;
3132 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003133}