blob: 14eba74f993718ade527f784937f99efca9f26a9 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Cole Faustc16d5292022-10-15 21:33:27 -070024import static java.util.Map.entry;
25
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010027import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080028import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080031import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000033import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070034import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070035import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010036import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070037import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000039import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070040import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080041import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000042import android.telephony.ims.ImsException;
43import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080044import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080045import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000046import android.util.ArrayMap;
47import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070049import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050
Brad Ebinger14d467f2021-02-12 06:18:28 +000051import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080053import com.android.internal.telephony.Phone;
54import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080055import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080056import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080057import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080058import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080059import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000060import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000061import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070062
Allen Xuee00f0e2022-03-14 21:04:49 +000063import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080065import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Arrays;
67import java.util.Collections;
Brad Ebinger24c29992019-12-05 13:03:21 -080068import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000069import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010070import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000071import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080073import java.util.UUID;
74import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070075
76/**
77 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
78 * permission checks have been done before onCommand was called. Make sure any commands processed
79 * here also contain the appropriate permissions checks.
80 */
81
Hall Liua1548bd2019-12-24 14:14:12 -080082public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
84 private static final String LOG_TAG = "TelephonyShellCommand";
85 // Don't commit with this true.
86 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070087 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070088
Hall Liuaa4211e2021-01-20 15:43:39 -080089 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070090 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080091 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080092 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080093 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070094 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000095 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000096 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010097 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080098 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String ENABLE = "enable";
100 private static final String DISABLE = "disable";
101 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000102 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000103 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
104 "set-carrier-service-package-override";
105 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
106 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000107 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800108
Hall Liu7135e502021-02-04 16:58:17 -0800109 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800110 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800111 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Brad Ebinger999d3302020-11-25 14:31:39 -0800113 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
114 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
115 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700116 // Used to disable or enable processing of conference event package data from the network.
117 // This is handy for testing scenarios where CEP data does not exist on a network which does
118 // support CEP data.
119 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700120
Hall Liud892bec2018-11-30 14:51:45 -0800121 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800122 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800123
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100124 private static final String CC_GET_VALUE = "get-value";
125 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000126 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private static final String CC_CLEAR_VALUES = "clear-values";
128
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000129 private static final String EUICC_SUBCOMMAND = "euicc";
130 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
131
Hui Wang641e81c2020-10-12 12:14:23 -0700132 private static final String GBA_SUBCOMMAND = "gba";
133 private static final String GBA_SET_SERVICE = "set-service";
134 private static final String GBA_GET_SERVICE = "get-service";
135 private static final String GBA_SET_RELEASE_TIME = "set-release";
136 private static final String GBA_GET_RELEASE_TIME = "get-release";
137
Hui Wang761a6682020-10-31 05:12:53 +0000138 private static final String SINGLE_REGISTATION_CONFIG = "src";
139 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
140 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
141 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
142 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800143 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
144 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800145 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
146 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000147
Tyler Gunn92479152021-01-20 16:30:10 -0800148 private static final String D2D_SUBCOMMAND = "d2d";
149 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800150 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700151 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800152
Nazanin014f41e2021-05-06 17:26:31 -0700153 private static final String BARRING_SUBCOMMAND = "barring";
154 private static final String BARRING_SEND_INFO = "send";
155
James.cf Linbcdf8b32021-01-14 16:44:13 +0800156 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800157 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800158 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800159 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800160 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
161 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000162 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
163 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800164 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
165 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800166 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
167 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800168
jimsun3b9ccac2021-10-26 15:01:23 +0800169 private static final String RADIO_SUBCOMMAND = "radio";
170 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
171 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
172
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800173 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
174 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
175
Jordan Liu0ccee222021-04-27 11:55:13 -0700176 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
177 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
178
Jack Nudelman644b91a2021-03-12 14:09:48 -0800179 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
180 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
181 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
182
Grant Menke567d48f2022-08-18 20:19:10 +0000183 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
184 + "'*', '#' or '+') needs to be specified after -a in the command ";
185
186 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
187 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
188 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
189
SongFerngWang98dd5992021-05-13 17:50:00 +0800190 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
191 "get-allowed-network-types-for-users";
192 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
193 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000194 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000195 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700196 // Take advantage of existing methods that already contain permissions checks when possible.
197 private final ITelephony mInterface;
198
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100199 private SubscriptionManager mSubscriptionManager;
200 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700201 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700202 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100203
204 private enum CcType {
205 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000206 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100207 }
208
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100209 private class CcOptionParseResult {
210 public int mSubId;
211 public boolean mPersistent;
212 }
213
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100214 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
215 // keys by looking at the end of the string which usually tells the type.
216 // For instance: "xxxx_string", "xxxx_string_array", etc.
217 // The carrier config keys in this map does not follow this convention. It is therefore not
218 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700219 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
220 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
221 CcType.STRING),
222 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
223 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
224 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
225 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
226 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
227 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
228 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
229 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
230 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
231 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
232 CcType.STRING),
233 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
234 CcType.STRING_ARRAY),
235 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
236 CcType.STRING_ARRAY),
237 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
238 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
239 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
240 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
241 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
242 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
243 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
244 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100245
Brad Ebinger14d467f2021-02-12 06:18:28 +0000246 /**
247 * Map from a shorthand string to the feature tags required in registration required in order
248 * for the RCS feature to be considered "capable".
249 */
250 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
251 static {
252 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
253 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
254 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
255 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
256 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
257 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
258 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
259 FeatureTags.FEATURE_TAG_VIDEO)));
260 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
261 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
262 map.put("call_comp",
263 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
264 map.put("call_comp_mmtel",
265 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
266 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
267 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
268 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
269 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
270 // version
271 map.put("chatbot", new ArraySet<>(Arrays.asList(
272 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
273 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
274 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
275 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000276 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000277 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
278 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
279 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
280 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
281 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000282 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000283 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
284 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
285 }
286
287
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100288 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700289 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100290 mCarrierConfigManager =
291 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
292 mSubscriptionManager = (SubscriptionManager)
293 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700294 mTelephonyRegistryManager = (TelephonyRegistryManager)
295 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700296 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700297 }
298
299 @Override
300 public int onCommand(String cmd) {
301 if (cmd == null) {
302 return handleDefaultCommands(null);
303 }
304
305 switch (cmd) {
306 case IMS_SUBCOMMAND: {
307 return handleImsCommand();
308 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800309 case RCS_UCE_COMMAND:
310 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800311 case NUMBER_VERIFICATION_SUBCOMMAND:
312 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800313 case EMERGENCY_CALLBACK_MODE:
314 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800315 case EMERGENCY_NUMBER_TEST_MODE:
316 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100317 case CARRIER_CONFIG_SUBCOMMAND: {
318 return handleCcCommand();
319 }
Shuo Qianf5125122019-12-16 17:03:07 -0800320 case DATA_TEST_MODE:
321 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700322 case END_BLOCK_SUPPRESSION:
323 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000324 case EUICC_SUBCOMMAND:
325 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700326 case GBA_SUBCOMMAND:
327 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800328 case D2D_SUBCOMMAND:
329 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700330 case BARRING_SUBCOMMAND:
331 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000332 case SINGLE_REGISTATION_CONFIG:
333 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000334 case RESTART_MODEM:
335 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800336 case CALL_COMPOSER_SUBCOMMAND:
337 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000338 case UNATTENDED_REBOOT:
339 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800340 case HAS_CARRIER_PRIVILEGES_COMMAND:
341 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800342 case THERMAL_MITIGATION_COMMAND:
343 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700344 case DISABLE_PHYSICAL_SUBSCRIPTION:
345 return handleEnablePhysicalSubscription(false);
346 case ENABLE_PHYSICAL_SUBSCRIPTION:
347 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800348 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
349 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
350 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000351 case GET_IMEI:
352 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000353 case GET_SIM_SLOTS_MAPPING:
354 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800355 case RADIO_SUBCOMMAND:
356 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000357 case CARRIER_RESTRICTION_STATUS_TEST:
358 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000359 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
360 return setCarrierServicePackageOverride();
361 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
362 return clearCarrierServicePackageOverride();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700363 default: {
364 return handleDefaultCommands(cmd);
365 }
366 }
367 }
368
369 @Override
370 public void onHelp() {
371 PrintWriter pw = getOutPrintWriter();
372 pw.println("Telephony Commands:");
373 pw.println(" help");
374 pw.println(" Print this help text.");
375 pw.println(" ims");
376 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800377 pw.println(" uce");
378 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800379 pw.println(" emergency-number-test-mode");
380 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700381 pw.println(" end-block-suppression");
382 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800383 pw.println(" data");
384 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100385 pw.println(" cc");
386 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700387 pw.println(" gba");
388 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000389 pw.println(" src");
390 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000391 pw.println(" restart-modem");
392 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000393 pw.println(" unattended-reboot");
394 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800395 pw.println(" has-carrier-privileges [package]");
396 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800397 pw.println(" get-allowed-network-types-for-users");
398 pw.println(" Get the Allowed Network Types.");
399 pw.println(" set-allowed-network-types-for-users");
400 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800401 pw.println(" radio");
402 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700403 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800404 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800405 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700406 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800407 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100408 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700409 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000410 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800411 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700412 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800413 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800414 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000415 onHelpImei();
Tyler Gunn92479152021-01-20 16:30:10 -0800416 }
417
418 private void onHelpD2D() {
419 PrintWriter pw = getOutPrintWriter();
420 pw.println("D2D Comms Commands:");
421 pw.println(" d2d send TYPE VALUE");
422 pw.println(" Sends a D2D message of specified type and value.");
423 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
424 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
425 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
426 MESSAGE_CALL_AUDIO_CODEC));
427 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
428 + Communicator.messageToString(
429 MESSAGE_DEVICE_BATTERY_STATE));
430 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
431 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800432 pw.println(" d2d transport TYPE");
433 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
434 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700435 pw.println(" d2d set-device-support true/default");
436 pw.println(" true - forces device support to be enabled for D2D.");
437 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
438 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700439 }
440
Nazanin014f41e2021-05-06 17:26:31 -0700441 private void onHelpBarring() {
442 PrintWriter pw = getOutPrintWriter();
443 pw.println("Barring Commands:");
444 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
445 + " -t CONDITIONAL_BARRING_TIME_SECS");
446 pw.println(" Notifies of a barring info change for the specified slot id.");
447 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
448 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
449 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
450 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
451 }
452
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700453 private void onHelpIms() {
454 PrintWriter pw = getOutPrintWriter();
455 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800456 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700457 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
458 pw.println(" ImsService. Options are:");
459 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
460 pw.println(" is specified, it will choose the default voice SIM slot.");
461 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
462 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800463 pw.println(" -f: Set the feature that this override if for, if no option is");
464 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700465 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
466 pw.println(" Gets the package name of the currently defined ImsService.");
467 pw.println(" Options are:");
468 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
469 pw.println(" is specified, it will choose the default voice SIM slot.");
470 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000471 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800472 pw.println(" -f: The feature type that the query will be requested for. If none is");
473 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800474 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
475 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
476 pw.println(" configuration overrides. Options are:");
477 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
478 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700479 pw.println(" ims enable [-s SLOT_ID]");
480 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
481 pw.println(" if none is specified.");
482 pw.println(" ims disable [-s SLOT_ID]");
483 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
484 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700485 pw.println(" ims conference-event-package [enable/disable]");
486 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700487 }
488
James.cf Linbcdf8b32021-01-14 16:44:13 +0800489 private void onHelpUce() {
490 PrintWriter pw = getOutPrintWriter();
491 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800492 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
493 pw.println(" Get the EAB contacts from the EAB database.");
494 pw.println(" Options are:");
495 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
496 pw.println(" Expected output format :");
497 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800498 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
499 pw.println(" Remove the EAB contacts from the EAB database.");
500 pw.println(" Options are:");
501 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
502 pw.println(" is specified, it will choose the default voice SIM slot.");
503 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800504 pw.println(" uce get-device-enabled");
505 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
506 pw.println(" uce set-device-enabled true|false");
507 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
508 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000509 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
510 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
511 pw.println(" Options are:");
512 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
513 pw.println(" is specified, it will choose the default voice SIM slot.");
514 pw.println(" add [CAPABILITY]: add a new capability");
515 pw.println(" remove [CAPABILITY]: remove a capability");
516 pw.println(" clear: clear all capability overrides");
517 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
518 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
519 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
520 pw.println(" chatbot_sa, chatbot_role] as well as full length");
521 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
522 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
523 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
524 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800525 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
526 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800527 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
528 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800529 }
530
Hall Liud892bec2018-11-30 14:51:45 -0800531 private void onHelpNumberVerification() {
532 PrintWriter pw = getOutPrintWriter();
533 pw.println("Number verification commands");
534 pw.println(" numverify override-package PACKAGE_NAME;");
535 pw.println(" Set the authorized package for number verification.");
536 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800537 pw.println(" numverify fake-call NUMBER;");
538 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
539 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800540 }
541
Jack Nudelman644b91a2021-03-12 14:09:48 -0800542 private void onHelpThermalMitigation() {
543 PrintWriter pw = getOutPrintWriter();
544 pw.println("Thermal mitigation commands");
545 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
546 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
547 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
548 pw.println(" Remove the package from one of the authorized packages for thermal "
549 + "mitigation.");
550 }
551
Jordan Liu0ccee222021-04-27 11:55:13 -0700552 private void onHelpDisableOrEnablePhysicalSubscription() {
553 PrintWriter pw = getOutPrintWriter();
554 pw.println("Disable or enable a physical subscription");
555 pw.println(" disable-physical-subscription SUB_ID");
556 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
557 pw.println(" enable-physical-subscription SUB_ID");
558 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
559 }
560
Shuo Qianf5125122019-12-16 17:03:07 -0800561 private void onHelpDataTestMode() {
562 PrintWriter pw = getOutPrintWriter();
563 pw.println("Mobile Data Test Mode Commands:");
564 pw.println(" data enable: enable mobile data connectivity");
565 pw.println(" data disable: disable mobile data connectivity");
566 }
567
sqian9d4df8b2019-01-15 18:32:07 -0800568 private void onHelpEmergencyNumber() {
569 PrintWriter pw = getOutPrintWriter();
570 pw.println("Emergency Number Test Mode Commands:");
571 pw.println(" emergency-number-test-mode ");
572 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
573 + " the test mode");
574 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700575 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800576 pw.println(" -c: clear the emergency number list in the test mode.");
577 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700578 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800579 pw.println(" -p: get the full emergency number list in the test mode.");
580 }
581
Shuo Qian489d9282020-07-09 11:30:03 -0700582 private void onHelpEndBlockSupperssion() {
583 PrintWriter pw = getOutPrintWriter();
584 pw.println("End Block Suppression command:");
585 pw.println(" end-block-suppression: disable suppressing blocking by contact");
586 pw.println(" with emergency services.");
587 }
588
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100589 private void onHelpCc() {
590 PrintWriter pw = getOutPrintWriter();
591 pw.println("Carrier Config Commands:");
592 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
593 pw.println(" Print carrier config values.");
594 pw.println(" Options are:");
595 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
596 pw.println(" is specified, it will choose the default voice SIM slot.");
597 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
598 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100599 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100600 pw.println(" Set carrier config KEY to NEW_VALUE.");
601 pw.println(" Options are:");
602 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
603 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100604 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100605 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
606 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
607 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
608 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000609 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
610 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
611 pw.println(" provided through standard input and follow CarrierConfig XML format.");
612 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
613 pw.println(" Options are:");
614 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
615 pw.println(" is specified, it will choose the default voice SIM slot.");
616 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100617 pw.println(" cc clear-values [-s SLOT_ID]");
618 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000619 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100620 pw.println(" Options are:");
621 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
622 pw.println(" is specified, it will choose the default voice SIM slot.");
623 }
624
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000625 private void onHelpEuicc() {
626 PrintWriter pw = getOutPrintWriter();
627 pw.println("Euicc Commands:");
628 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
629 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
630 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
631 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
632 }
633
Hui Wang641e81c2020-10-12 12:14:23 -0700634 private void onHelpGba() {
635 PrintWriter pw = getOutPrintWriter();
636 pw.println("Gba Commands:");
637 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
638 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
639 pw.println(" Options are:");
640 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
641 pw.println(" is specified, it will choose the default voice SIM slot.");
642 pw.println(" gba get-service [-s SLOT_ID]");
643 pw.println(" Gets the package name of the currently defined GbaService.");
644 pw.println(" Options are:");
645 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
646 pw.println(" is specified, it will choose the default voice SIM slot.");
647 pw.println(" gba set-release [-s SLOT_ID] n");
648 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
649 pw.println(" Do not release/unbind if n is -1.");
650 pw.println(" Options are:");
651 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
652 pw.println(" is specified, it will choose the default voice SIM slot.");
653 pw.println(" gba get-release [-s SLOT_ID]");
654 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
655 pw.println(" Options are:");
656 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
657 pw.println(" is specified, it will choose the default voice SIM slot.");
658 }
659
Hui Wang761a6682020-10-31 05:12:53 +0000660 private void onHelpSrc() {
661 PrintWriter pw = getOutPrintWriter();
662 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800663 pw.println(" src set-test-enabled true|false");
664 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
665 pw.println(" The value could be true, false, or null(undefined).");
666 pw.println(" src get-test-enabled");
667 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000668 pw.println(" src set-device-enabled true|false|null");
669 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
670 pw.println(" The value could be true, false, or null(undefined).");
671 pw.println(" src get-device-enabled");
672 pw.println(" Gets the device config for RCS VoLTE single registration.");
673 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
674 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
675 pw.println(" The value could be true, false, or null(undefined).");
676 pw.println(" Options are:");
677 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
678 pw.println(" is specified, it will choose the default voice SIM slot.");
679 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
680 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
681 pw.println(" Options are:");
682 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
683 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800684 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
685 pw.println(" Sets ims feature validation result.");
686 pw.println(" The value could be true, false, or null(undefined).");
687 pw.println(" Options are:");
688 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
689 pw.println(" is specified, it will choose the default voice SIM slot.");
690 pw.println(" src get-feature-validation [-s SLOT_ID]");
691 pw.println(" Gets ims feature validation override value.");
692 pw.println(" Options are:");
693 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
694 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000695 }
696
SongFerngWang98dd5992021-05-13 17:50:00 +0800697 private void onHelpAllowedNetworkTypes() {
698 PrintWriter pw = getOutPrintWriter();
699 pw.println("Allowed Network Types Commands:");
700 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
701 pw.println(" Print allowed network types value.");
702 pw.println(" Options are:");
703 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
704 pw.println(" option is specified, it will choose the default voice SIM slot.");
705 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
706 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
707 pw.println(" Options are:");
708 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
709 pw.println(" option is specified, it will choose the default voice SIM slot.");
710 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
711 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
712 pw.println(" at TelephonyManager.java");
713 pw.println(" For example:");
714 pw.println(" NR only : 10000000000000000000");
715 pw.println(" NR|LTE : 11000001000000000000");
716 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
717 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
718 pw.println(" LTE only : 01000001000000000000");
719 }
720
jimsun3b9ccac2021-10-26 15:01:23 +0800721 private void onHelpRadio() {
722 PrintWriter pw = getOutPrintWriter();
723 pw.println("Radio Commands:");
724 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
725 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
726 pw.println(" to be the bound. Options are:");
727 pw.println(" -s: the service name that the modem service should be bound for.");
728 pw.println(" If no option is specified, it will bind to the default.");
729 pw.println(" radio get-modem-service");
730 pw.println(" Gets the service name of the currently defined modem service.");
731 pw.println(" If it is binding to default, 'default' returns.");
732 pw.println(" If it doesn't bind to any modem service for some reasons,");
733 pw.println(" the result would be 'unknown'.");
734 }
735
Ling Ma4fbab492022-01-25 22:36:16 +0000736 private void onHelpImei() {
737 PrintWriter pw = getOutPrintWriter();
738 pw.println("IMEI Commands:");
739 pw.println(" get-imei [-s SLOT_ID]");
740 pw.println(" Gets the device IMEI. Options are:");
741 pw.println(" -s: the slot ID to get the IMEI. If no option");
742 pw.println(" is specified, it will choose the default voice SIM slot.");
743 }
744
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700745 private int handleImsCommand() {
746 String arg = getNextArg();
747 if (arg == null) {
748 onHelpIms();
749 return 0;
750 }
751
752 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800753 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700754 return handleImsSetServiceCommand();
755 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800756 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700757 return handleImsGetServiceCommand();
758 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800759 case IMS_CLEAR_SERVICE_OVERRIDE: {
760 return handleImsClearCarrierServiceCommand();
761 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800762 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700763 return handleEnableIms();
764 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800765 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700766 return handleDisableIms();
767 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700768 case IMS_CEP: {
769 return handleCepChange();
770 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700771 }
772
773 return -1;
774 }
775
Shuo Qianf5125122019-12-16 17:03:07 -0800776 private int handleDataTestModeCommand() {
777 PrintWriter errPw = getErrPrintWriter();
778 String arg = getNextArgRequired();
779 if (arg == null) {
780 onHelpDataTestMode();
781 return 0;
782 }
783 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800784 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800785 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700786 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800787 } catch (RemoteException ex) {
788 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
789 errPw.println("Exception: " + ex.getMessage());
790 return -1;
791 }
792 break;
793 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800794 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800795 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700796 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800797 } catch (RemoteException ex) {
798 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
799 errPw.println("Exception: " + ex.getMessage());
800 return -1;
801 }
802 break;
803 }
804 default:
805 onHelpDataTestMode();
806 break;
807 }
808 return 0;
809 }
810
Shuo Qianccbaf742021-02-22 18:32:21 -0800811 private int handleEmergencyCallbackModeCommand() {
812 PrintWriter errPw = getErrPrintWriter();
813 try {
814 mInterface.startEmergencyCallbackMode();
815 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
816 } catch (RemoteException ex) {
817 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
818 errPw.println("Exception: " + ex.getMessage());
819 return -1;
820 }
821 return 0;
822 }
823
Grant Menke567d48f2022-08-18 20:19:10 +0000824 private void removeEmergencyNumberTestMode(String emergencyNumber) {
825 PrintWriter errPw = getErrPrintWriter();
826 for (int routingType : ROUTING_TYPES) {
827 try {
828 mInterface.updateEmergencyNumberListTestMode(
829 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
830 new EmergencyNumber(emergencyNumber, "", "",
831 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
832 new ArrayList<String>(),
833 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
834 routingType));
835 } catch (RemoteException ex) {
836 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
837 errPw.println("Exception: " + ex.getMessage());
838 }
839 }
840 }
841
sqian9d4df8b2019-01-15 18:32:07 -0800842 private int handleEmergencyNumberTestModeCommand() {
843 PrintWriter errPw = getErrPrintWriter();
844 String opt = getNextOption();
845 if (opt == null) {
846 onHelpEmergencyNumber();
847 return 0;
848 }
sqian9d4df8b2019-01-15 18:32:07 -0800849 switch (opt) {
850 case "-a": {
851 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000852 if (emergencyNumberCmd == null){
853 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800854 return -1;
855 }
Grant Menke567d48f2022-08-18 20:19:10 +0000856 String[] params = emergencyNumberCmd.split(":");
857 String emergencyNumber;
858 if (params[0] == null ||
859 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
860 errPw.println(INVALID_ENTRY_ERROR);
861 return -1;
862 } else {
863 emergencyNumber = params[0];
864 }
865 removeEmergencyNumberTestMode(emergencyNumber);
866 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
867 if (params.length > 1) {
868 switch (params[1].toLowerCase(Locale.ROOT)) {
869 case "emergency":
870 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
871 break;
872 case "normal":
873 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
874 break;
875 case "unknown":
876 break;
877 default:
878 errPw.println("\"" + params[1] + "\" is not a valid specification for "
879 + "emergency call routing. Please enter either \"normal\", "
880 + "\"unknown\", or \"emergency\" for call routing. "
881 + "(-a 1234:normal)");
882 return -1;
883 }
884 }
sqian9d4df8b2019-01-15 18:32:07 -0800885 try {
886 mInterface.updateEmergencyNumberListTestMode(
887 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000888 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800889 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
890 new ArrayList<String>(),
891 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000892 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800893 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000894 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800895 + ", error " + ex.getMessage());
896 errPw.println("Exception: " + ex.getMessage());
897 return -1;
898 }
899 break;
900 }
901 case "-c": {
902 try {
903 mInterface.updateEmergencyNumberListTestMode(
904 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
905 } catch (RemoteException ex) {
906 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
907 errPw.println("Exception: " + ex.getMessage());
908 return -1;
909 }
910 break;
911 }
912 case "-r": {
913 String emergencyNumberCmd = getNextArgRequired();
914 if (emergencyNumberCmd == null
915 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700916 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800917 + " to be specified after -r in the command ");
918 return -1;
919 }
Grant Menke567d48f2022-08-18 20:19:10 +0000920 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800921 break;
922 }
923 case "-p": {
924 try {
925 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
926 } catch (RemoteException ex) {
927 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
928 errPw.println("Exception: " + ex.getMessage());
929 return -1;
930 }
931 break;
932 }
933 default:
934 onHelpEmergencyNumber();
935 break;
936 }
937 return 0;
938 }
939
Hall Liud892bec2018-11-30 14:51:45 -0800940 private int handleNumberVerificationCommand() {
941 String arg = getNextArg();
942 if (arg == null) {
943 onHelpNumberVerification();
944 return 0;
945 }
946
Hall Liuca5af3a2018-12-04 16:58:23 -0800947 if (!checkShellUid()) {
948 return -1;
949 }
950
Hall Liud892bec2018-11-30 14:51:45 -0800951 switch (arg) {
952 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800953 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
954 return 0;
955 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800956 case NUMBER_VERIFICATION_FAKE_CALL: {
957 boolean val = NumberVerificationManager.getInstance()
958 .checkIncomingCall(getNextArg());
959 getOutPrintWriter().println(val ? "1" : "0");
960 return 0;
961 }
Hall Liud892bec2018-11-30 14:51:45 -0800962 }
963
964 return -1;
965 }
966
Jordan Liu0ccee222021-04-27 11:55:13 -0700967 private boolean subIsEsim(int subId) {
968 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
969 if (info != null) {
970 return info.isEmbedded();
971 }
972 return false;
973 }
974
975 private int handleEnablePhysicalSubscription(boolean enable) {
976 PrintWriter errPw = getErrPrintWriter();
977 int subId = 0;
978 try {
979 subId = Integer.parseInt(getNextArgRequired());
980 } catch (NumberFormatException e) {
981 errPw.println((enable ? "enable" : "disable")
982 + "-physical-subscription requires an integer as a subId.");
983 return -1;
984 }
985 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
986 // non user build.
987 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
988 errPw.println("cc: Permission denied.");
989 return -1;
990 }
991 // Verify that the subId represents a physical sub
992 if (subIsEsim(subId)) {
993 errPw.println("SubId " + subId + " is not for a physical subscription");
994 return -1;
995 }
996 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
997 + " physical subscription with subId=" + subId);
998 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
999 return 0;
1000 }
1001
Jack Nudelman644b91a2021-03-12 14:09:48 -08001002 private int handleThermalMitigationCommand() {
1003 String arg = getNextArg();
1004 String packageName = getNextArg();
1005 if (arg == null || packageName == null) {
1006 onHelpThermalMitigation();
1007 return 0;
1008 }
1009
1010 if (!checkShellUid()) {
1011 return -1;
1012 }
1013
1014 switch (arg) {
1015 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1016 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1017 return 0;
1018 }
1019 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1020 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1021 mContext);
1022 return 0;
1023 }
1024 default:
1025 onHelpThermalMitigation();
1026 }
1027
1028 return -1;
1029
1030 }
1031
Tyler Gunn92479152021-01-20 16:30:10 -08001032 private int handleD2dCommand() {
1033 String arg = getNextArg();
1034 if (arg == null) {
1035 onHelpD2D();
1036 return 0;
1037 }
1038
1039 switch (arg) {
1040 case D2D_SEND: {
1041 return handleD2dSendCommand();
1042 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001043 case D2D_TRANSPORT: {
1044 return handleD2dTransportCommand();
1045 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001046 case D2D_SET_DEVICE_SUPPORT: {
1047 return handleD2dDeviceSupportedCommand();
1048 }
Tyler Gunn92479152021-01-20 16:30:10 -08001049 }
1050
1051 return -1;
1052 }
1053
1054 private int handleD2dSendCommand() {
1055 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001056 int messageType = -1;
1057 int messageValue = -1;
1058
Tyler Gunn92479152021-01-20 16:30:10 -08001059 String arg = getNextArg();
1060 if (arg == null) {
1061 onHelpD2D();
1062 return 0;
1063 }
1064 try {
1065 messageType = Integer.parseInt(arg);
1066 } catch (NumberFormatException e) {
1067 errPw.println("message type must be a valid integer");
1068 return -1;
1069 }
1070
1071 arg = getNextArg();
1072 if (arg == null) {
1073 onHelpD2D();
1074 return 0;
1075 }
1076 try {
1077 messageValue = Integer.parseInt(arg);
1078 } catch (NumberFormatException e) {
1079 errPw.println("message value must be a valid integer");
1080 return -1;
1081 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001082
Tyler Gunn92479152021-01-20 16:30:10 -08001083 try {
1084 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1085 } catch (RemoteException e) {
1086 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1087 errPw.println("Exception: " + e.getMessage());
1088 return -1;
1089 }
1090
1091 return 0;
1092 }
1093
Tyler Gunnbabbda02021-02-10 11:05:02 -08001094 private int handleD2dTransportCommand() {
1095 PrintWriter errPw = getErrPrintWriter();
1096
1097 String arg = getNextArg();
1098 if (arg == null) {
1099 onHelpD2D();
1100 return 0;
1101 }
1102
1103 try {
1104 mInterface.setActiveDeviceToDeviceTransport(arg);
1105 } catch (RemoteException e) {
1106 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1107 errPw.println("Exception: " + e.getMessage());
1108 return -1;
1109 }
1110 return 0;
1111 }
Nazanin014f41e2021-05-06 17:26:31 -07001112 private int handleBarringCommand() {
1113 String arg = getNextArg();
1114 if (arg == null) {
1115 onHelpBarring();
1116 return 0;
1117 }
1118
1119 switch (arg) {
1120 case BARRING_SEND_INFO: {
1121 return handleBarringSendCommand();
1122 }
1123 }
1124 return -1;
1125 }
1126
1127 private int handleBarringSendCommand() {
1128 PrintWriter errPw = getErrPrintWriter();
1129 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001130 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001131 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1132 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1133 boolean isConditionallyBarred = false;
1134 int conditionalBarringTimeSeconds = 0;
1135
1136 String opt;
1137 while ((opt = getNextOption()) != null) {
1138 switch (opt) {
1139 case "-s": {
1140 try {
1141 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001142 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001143 } catch (NumberFormatException e) {
1144 errPw.println("barring send requires an integer as a SLOT_ID.");
1145 return -1;
1146 }
1147 break;
1148 }
1149 case "-b": {
1150 try {
1151 barringType = Integer.parseInt(getNextArgRequired());
1152 if (barringType < -1 || barringType > 2) {
1153 throw new NumberFormatException();
1154 }
1155
1156 } catch (NumberFormatException e) {
1157 errPw.println("barring send requires an integer in range [-1,2] as "
1158 + "a BARRING_TYPE.");
1159 return -1;
1160 }
1161 break;
1162 }
1163 case "-c": {
1164 try {
1165 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1166 } catch (Exception e) {
1167 errPw.println("barring send requires a boolean after -c indicating"
1168 + " conditional barring");
1169 return -1;
1170 }
1171 break;
1172 }
1173 case "-t": {
1174 try {
1175 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1176 } catch (NumberFormatException e) {
1177 errPw.println("barring send requires an integer for time of barring"
1178 + " in seconds after -t for conditional barring");
1179 return -1;
1180 }
1181 break;
1182 }
1183 }
1184 }
1185 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1186 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1187 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1188 barringServiceInfos.append(0, bsi);
1189 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1190 try {
1191 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1192 } catch (Exception e) {
1193 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1194 errPw.println("Exception: " + e.getMessage());
1195 return -1;
1196 }
1197 return 0;
1198 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001199
Tyler Gunnd4575212021-05-03 14:46:49 -07001200 private int handleD2dDeviceSupportedCommand() {
1201 PrintWriter errPw = getErrPrintWriter();
1202
1203 String arg = getNextArg();
1204 if (arg == null) {
1205 onHelpD2D();
1206 return 0;
1207 }
1208
Jack Yua533d632022-09-30 13:53:46 -07001209 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001210 try {
1211 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1212 } catch (RemoteException e) {
1213 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1214 errPw.println("Exception: " + e.getMessage());
1215 return -1;
1216 }
1217 return 0;
1218 }
1219
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001220 // ims set-ims-service
1221 private int handleImsSetServiceCommand() {
1222 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001223 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001224 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001225 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001226
1227 String opt;
1228 while ((opt = getNextOption()) != null) {
1229 switch (opt) {
1230 case "-s": {
1231 try {
1232 slotId = Integer.parseInt(getNextArgRequired());
1233 } catch (NumberFormatException e) {
1234 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1235 return -1;
1236 }
1237 break;
1238 }
1239 case "-c": {
1240 isCarrierService = true;
1241 break;
1242 }
1243 case "-d": {
1244 isCarrierService = false;
1245 break;
1246 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001247 case "-f": {
1248 String featureString = getNextArgRequired();
1249 String[] features = featureString.split(",");
1250 for (int i = 0; i < features.length; i++) {
1251 try {
1252 Integer result = Integer.parseInt(features[i]);
1253 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1254 || result >= ImsFeature.FEATURE_MAX) {
1255 errPw.println("ims set-ims-service -f " + result
1256 + " is an invalid feature.");
1257 return -1;
1258 }
1259 featuresList.add(result);
1260 } catch (NumberFormatException e) {
1261 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1262 + " as an integer.");
1263 return -1;
1264 }
1265 }
1266 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001267 }
1268 }
1269 // Mandatory param, either -c or -d
1270 if (isCarrierService == null) {
1271 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1272 return -1;
1273 }
1274
1275 String packageName = getNextArg();
1276
1277 try {
1278 if (packageName == null) {
1279 packageName = "";
1280 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001281 int[] featureArray = new int[featuresList.size()];
1282 for (int i = 0; i < featuresList.size(); i++) {
1283 featureArray[i] = featuresList.get(i);
1284 }
1285 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1286 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001287 if (VDBG) {
1288 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001289 + (isCarrierService ? "-c " : "-d ")
1290 + "-f " + featuresList + " "
1291 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001292 }
1293 getOutPrintWriter().println(result);
1294 } catch (RemoteException e) {
1295 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001296 + (isCarrierService ? "-c " : "-d ")
1297 + "-f " + featuresList + " "
1298 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001299 errPw.println("Exception: " + e.getMessage());
1300 return -1;
1301 }
1302 return 0;
1303 }
1304
Brad Ebinger999d3302020-11-25 14:31:39 -08001305 // ims clear-ims-service-override
1306 private int handleImsClearCarrierServiceCommand() {
1307 PrintWriter errPw = getErrPrintWriter();
1308 int slotId = getDefaultSlot();
1309
1310 String opt;
1311 while ((opt = getNextOption()) != null) {
1312 switch (opt) {
1313 case "-s": {
1314 try {
1315 slotId = Integer.parseInt(getNextArgRequired());
1316 } catch (NumberFormatException e) {
1317 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1318 return -1;
1319 }
1320 break;
1321 }
1322 }
1323 }
1324
1325 try {
1326 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1327 if (VDBG) {
1328 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1329 + ", result=" + result);
1330 }
1331 getOutPrintWriter().println(result);
1332 } catch (RemoteException e) {
1333 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1334 + ", error" + e.getMessage());
1335 errPw.println("Exception: " + e.getMessage());
1336 return -1;
1337 }
1338 return 0;
1339 }
1340
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001341 // ims get-ims-service
1342 private int handleImsGetServiceCommand() {
1343 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001344 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001345 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001346 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001347
1348 String opt;
1349 while ((opt = getNextOption()) != null) {
1350 switch (opt) {
1351 case "-s": {
1352 try {
1353 slotId = Integer.parseInt(getNextArgRequired());
1354 } catch (NumberFormatException e) {
1355 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1356 return -1;
1357 }
1358 break;
1359 }
1360 case "-c": {
1361 isCarrierService = true;
1362 break;
1363 }
1364 case "-d": {
1365 isCarrierService = false;
1366 break;
1367 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001368 case "-f": {
1369 try {
1370 featureType = Integer.parseInt(getNextArg());
1371 } catch (NumberFormatException e) {
1372 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1373 return -1;
1374 }
1375 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1376 || featureType >= ImsFeature.FEATURE_MAX) {
1377 errPw.println("ims get-ims-service -f invalid feature.");
1378 return -1;
1379 }
1380 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001381 }
1382 }
1383 // Mandatory param, either -c or -d
1384 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001385 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001386 return -1;
1387 }
1388
1389 String result;
1390 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001391 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001392 } catch (RemoteException e) {
1393 return -1;
1394 }
1395 if (VDBG) {
1396 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001397 + (isCarrierService ? "-c " : "-d ")
1398 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1399 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001400 }
1401 getOutPrintWriter().println(result);
1402 return 0;
1403 }
1404
1405 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001406 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001407 String opt;
1408 while ((opt = getNextOption()) != null) {
1409 switch (opt) {
1410 case "-s": {
1411 try {
1412 slotId = Integer.parseInt(getNextArgRequired());
1413 } catch (NumberFormatException e) {
1414 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1415 return -1;
1416 }
1417 break;
1418 }
1419 }
1420 }
1421 try {
1422 mInterface.enableIms(slotId);
1423 } catch (RemoteException e) {
1424 return -1;
1425 }
1426 if (VDBG) {
1427 Log.v(LOG_TAG, "ims enable -s " + slotId);
1428 }
1429 return 0;
1430 }
1431
1432 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001433 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001434 String opt;
1435 while ((opt = getNextOption()) != null) {
1436 switch (opt) {
1437 case "-s": {
1438 try {
1439 slotId = Integer.parseInt(getNextArgRequired());
1440 } catch (NumberFormatException e) {
1441 getErrPrintWriter().println(
1442 "ims disable requires an integer as a SLOT_ID.");
1443 return -1;
1444 }
1445 break;
1446 }
1447 }
1448 }
1449 try {
1450 mInterface.disableIms(slotId);
1451 } catch (RemoteException e) {
1452 return -1;
1453 }
1454 if (VDBG) {
1455 Log.v(LOG_TAG, "ims disable -s " + slotId);
1456 }
1457 return 0;
1458 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001459
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001460 private int handleCepChange() {
1461 Log.i(LOG_TAG, "handleCepChange");
1462 String opt = getNextArg();
1463 if (opt == null) {
1464 return -1;
1465 }
1466 boolean isCepEnabled = opt.equals("enable");
1467
1468 try {
1469 mInterface.setCepEnabled(isCepEnabled);
1470 } catch (RemoteException e) {
1471 return -1;
1472 }
1473 return 0;
1474 }
1475
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001476 private int getDefaultSlot() {
1477 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1478 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1479 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1480 // If there is no default, default to slot 0.
1481 slotId = DEFAULT_PHONE_ID;
1482 }
1483 return slotId;
1484 }
sqian2fff4a32018-11-05 14:18:37 -08001485
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001486 // Parse options related to Carrier Config Commands.
1487 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001488 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001489 CcOptionParseResult result = new CcOptionParseResult();
1490 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1491 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001492
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001493 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001494 while ((opt = getNextOption()) != null) {
1495 switch (opt) {
1496 case "-s": {
1497 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001498 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1499 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1500 errPw.println(tag + "No valid subscription found.");
1501 return null;
1502 }
1503
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001504 } catch (IllegalArgumentException e) {
1505 // Missing slot id
1506 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001507 return null;
1508 }
1509 break;
1510 }
1511 case "-p": {
1512 if (allowOptionPersistent) {
1513 result.mPersistent = true;
1514 } else {
1515 errPw.println(tag + "Unexpected option " + opt);
1516 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001517 }
1518 break;
1519 }
1520 default: {
1521 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001522 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001523 }
1524 }
1525 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001526 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001527 }
1528
1529 private int slotStringToSubId(String tag, String slotString) {
1530 int slotId = -1;
1531 try {
1532 slotId = Integer.parseInt(slotString);
1533 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001534 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1535 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1536 }
1537
1538 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001539 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1540 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1541 }
1542
Qiong Liuf25799b2020-09-10 10:13:46 +08001543 Phone phone = PhoneFactory.getPhone(slotId);
1544 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001545 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1546 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1547 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001548 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001549 }
1550
Hall Liud892bec2018-11-30 14:51:45 -08001551 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001552 // adb can run as root or as shell, depending on whether the device is rooted.
1553 return Binder.getCallingUid() == Process.SHELL_UID
1554 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001555 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001556
1557 private int handleCcCommand() {
1558 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1559 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001560 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001561 getErrPrintWriter().println("cc: Permission denied.");
1562 return -1;
1563 }
1564
1565 String arg = getNextArg();
1566 if (arg == null) {
1567 onHelpCc();
1568 return 0;
1569 }
1570
1571 switch (arg) {
1572 case CC_GET_VALUE: {
1573 return handleCcGetValue();
1574 }
1575 case CC_SET_VALUE: {
1576 return handleCcSetValue();
1577 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001578 case CC_SET_VALUES_FROM_XML: {
1579 return handleCcSetValuesFromXml();
1580 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001581 case CC_CLEAR_VALUES: {
1582 return handleCcClearValues();
1583 }
1584 default: {
1585 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1586 }
1587 }
1588 return -1;
1589 }
1590
1591 // cc get-value
1592 private int handleCcGetValue() {
1593 PrintWriter errPw = getErrPrintWriter();
1594 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1595 String key = null;
1596
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001597 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001598 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001599 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001600 return -1;
1601 }
1602
1603 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001604 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001605 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001606 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001607 return -1;
1608 }
1609
1610 // Get the key.
1611 key = getNextArg();
1612 if (key != null) {
1613 // A key was provided. Verify if it is a valid key
1614 if (!bundle.containsKey(key)) {
1615 errPw.println(tag + key + " is not a valid key.");
1616 return -1;
1617 }
1618
1619 // Print the carrier config value for key.
1620 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1621 } else {
1622 // No key provided. Show all values.
1623 // Iterate over a sorted list of all carrier config keys and print them.
1624 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1625 for (String k : sortedSet) {
1626 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1627 }
1628 }
1629 return 0;
1630 }
1631
1632 // cc set-value
1633 private int handleCcSetValue() {
1634 PrintWriter errPw = getErrPrintWriter();
1635 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1636
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001637 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001638 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001639 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001640 return -1;
1641 }
1642
1643 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001644 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001645 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001646 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001647 return -1;
1648 }
1649
1650 // Get the key.
1651 String key = getNextArg();
1652 if (key == null || key.equals("")) {
1653 errPw.println(tag + "KEY is missing");
1654 return -1;
1655 }
1656
1657 // Verify if the key is valid
1658 if (!originalValues.containsKey(key)) {
1659 errPw.println(tag + key + " is not a valid key.");
1660 return -1;
1661 }
1662
1663 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1664 ArrayList<String> valueList = new ArrayList<String>();
1665 while (peekNextArg() != null) {
1666 valueList.add(getNextArg());
1667 }
1668
1669 // Find the type of the carrier config value
1670 CcType type = getType(tag, key, originalValues);
1671 if (type == CcType.UNKNOWN) {
1672 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1673 return -1;
1674 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001675 if (type == CcType.PERSISTABLE_BUNDLE) {
1676 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1677 + "Use set-values-from-xml instead.");
1678 return -1;
1679 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001680
1681 // Create an override bundle containing the key and value that should be overriden.
1682 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1683 if (overrideBundle == null) {
1684 return -1;
1685 }
1686
1687 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001688 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001689
1690 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001691 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001692 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001693 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001694 return -1;
1695 }
1696
1697 // Print the original and new value.
1698 String originalValueString = ccValueToString(key, type, originalValues);
1699 String newValueString = ccValueToString(key, type, newValues);
1700 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1701 getOutPrintWriter().println("New value: \n" + newValueString);
1702
1703 return 0;
1704 }
1705
Allen Xuee00f0e2022-03-14 21:04:49 +00001706 // cc set-values-from-xml
1707 private int handleCcSetValuesFromXml() {
1708 PrintWriter errPw = getErrPrintWriter();
1709 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1710
1711 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001712 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001713 if (options == null) {
1714 return -1;
1715 }
1716
1717 // Get bundle containing all current carrier configuration values.
1718 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1719 if (originalValues == null) {
1720 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1721 return -1;
1722 }
1723
1724 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1725 if (overrideBundle == null) {
1726 return -1;
1727 }
1728
1729 // Verify all values are valid types
1730 for (String key : overrideBundle.keySet()) {
1731 CcType type = getType(tag, key, originalValues);
1732 if (type == CcType.UNKNOWN) {
1733 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1734 return -1;
1735 }
1736 }
1737
1738 // Override the value
1739 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1740
1741 // Find bundle containing all new carrier configuration values after the override.
1742 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1743 if (newValues == null) {
1744 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1745 return -1;
1746 }
1747
1748 // Print the original and new values
1749 overrideBundle.keySet().forEach(key -> {
1750 CcType type = getType(tag, key, originalValues);
1751 String originalValueString = ccValueToString(key, type, originalValues);
1752 String newValueString = ccValueToString(key, type, newValues);
1753 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1754 getOutPrintWriter().println("New value: \n" + newValueString);
1755 });
1756
1757 return 0;
1758 }
1759
1760 private PersistableBundle readPersistableBundleFromXml(String tag) {
1761 PersistableBundle subIdBundles;
1762 try {
1763 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1764 } catch (IOException | RuntimeException e) {
1765 PrintWriter errPw = getErrPrintWriter();
1766 errPw.println(tag + e);
1767 return null;
1768 }
1769
1770 return subIdBundles;
1771 }
1772
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001773 // cc clear-values
1774 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001775 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1776
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001777 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001778 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001779 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001780 return -1;
1781 }
1782
1783 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001784 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001785 getOutPrintWriter()
1786 .println("All previously set carrier config override values has been cleared");
1787 return 0;
1788 }
1789
1790 private CcType getType(String tag, String key, PersistableBundle bundle) {
1791 // Find the type by checking the type of the current value stored in the bundle.
1792 Object value = bundle.get(key);
1793
1794 if (CC_TYPE_MAP.containsKey(key)) {
1795 return CC_TYPE_MAP.get(key);
1796 } else if (value != null) {
1797 if (value instanceof Boolean) {
1798 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001799 }
1800 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001801 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001802 }
1803 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001804 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001805 }
1806 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001807 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001808 }
1809 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001810 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001811 }
1812 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001813 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001814 }
1815 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001816 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001817 }
1818 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001819 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001820 }
1821 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001822 return CcType.STRING_ARRAY;
1823 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001824 if (value instanceof PersistableBundle) {
1825 return CcType.PERSISTABLE_BUNDLE;
1826 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001827 } else {
1828 // Current value was null and can therefore not be used in order to find the type.
1829 // Check the name of the key to infer the type. This check is not needed for primitive
1830 // data types (boolean, double, int and long), since they can not be null.
1831 if (key.endsWith("double_array")) {
1832 return CcType.DOUBLE_ARRAY;
1833 }
1834 if (key.endsWith("int_array")) {
1835 return CcType.INT_ARRAY;
1836 }
1837 if (key.endsWith("long_array")) {
1838 return CcType.LONG_ARRAY;
1839 }
1840 if (key.endsWith("string")) {
1841 return CcType.STRING;
1842 }
1843 if (key.endsWith("string_array") || key.endsWith("strings")) {
1844 return CcType.STRING_ARRAY;
1845 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001846 if (key.endsWith("bundle")) {
1847 return CcType.PERSISTABLE_BUNDLE;
1848 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001849 }
1850
1851 // Not possible to infer the type by looking at the current value or the key.
1852 PrintWriter errPw = getErrPrintWriter();
1853 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1854 return CcType.UNKNOWN;
1855 }
1856
1857 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1858 String result;
1859 StringBuilder valueString = new StringBuilder();
1860 String typeString = type.toString();
1861 Object value = bundle.get(key);
1862
1863 if (value == null) {
1864 valueString.append("null");
1865 } else {
1866 switch (type) {
1867 case DOUBLE_ARRAY: {
1868 // Format the string representation of the int array as value1 value2......
1869 double[] valueArray = (double[]) value;
1870 for (int i = 0; i < valueArray.length; i++) {
1871 if (i != 0) {
1872 valueString.append(" ");
1873 }
1874 valueString.append(valueArray[i]);
1875 }
1876 break;
1877 }
1878 case INT_ARRAY: {
1879 // Format the string representation of the int array as value1 value2......
1880 int[] valueArray = (int[]) value;
1881 for (int i = 0; i < valueArray.length; i++) {
1882 if (i != 0) {
1883 valueString.append(" ");
1884 }
1885 valueString.append(valueArray[i]);
1886 }
1887 break;
1888 }
1889 case LONG_ARRAY: {
1890 // Format the string representation of the int array as value1 value2......
1891 long[] valueArray = (long[]) value;
1892 for (int i = 0; i < valueArray.length; i++) {
1893 if (i != 0) {
1894 valueString.append(" ");
1895 }
1896 valueString.append(valueArray[i]);
1897 }
1898 break;
1899 }
1900 case STRING: {
1901 valueString.append("\"" + value.toString() + "\"");
1902 break;
1903 }
1904 case STRING_ARRAY: {
1905 // Format the string representation of the string array as "value1" "value2"....
1906 String[] valueArray = (String[]) value;
1907 for (int i = 0; i < valueArray.length; i++) {
1908 if (i != 0) {
1909 valueString.append(" ");
1910 }
1911 if (valueArray[i] != null) {
1912 valueString.append("\"" + valueArray[i] + "\"");
1913 } else {
1914 valueString.append("null");
1915 }
1916 }
1917 break;
1918 }
1919 default: {
1920 valueString.append(value.toString());
1921 }
1922 }
1923 }
1924 return String.format("%-70s %-15s %s", key, typeString, valueString);
1925 }
1926
1927 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1928 ArrayList<String> valueList) {
1929 PrintWriter errPw = getErrPrintWriter();
1930 PersistableBundle bundle = new PersistableBundle();
1931
1932 // First verify that a valid number of values has been provided for the type.
1933 switch (type) {
1934 case BOOLEAN:
1935 case DOUBLE:
1936 case INT:
1937 case LONG: {
1938 if (valueList.size() != 1) {
1939 errPw.println(tag + "Expected 1 value for type " + type
1940 + ". Found: " + valueList.size());
1941 return null;
1942 }
1943 break;
1944 }
1945 case STRING: {
1946 if (valueList.size() > 1) {
1947 errPw.println(tag + "Expected 0 or 1 values for type " + type
1948 + ". Found: " + valueList.size());
1949 return null;
1950 }
1951 break;
1952 }
1953 }
1954
1955 // Parse the value according to type and add it to the Bundle.
1956 switch (type) {
1957 case BOOLEAN: {
1958 if ("true".equalsIgnoreCase(valueList.get(0))) {
1959 bundle.putBoolean(key, true);
1960 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1961 bundle.putBoolean(key, false);
1962 } else {
1963 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1964 return null;
1965 }
1966 break;
1967 }
1968 case DOUBLE: {
1969 try {
1970 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1971 } catch (NumberFormatException nfe) {
1972 // Not a valid double
1973 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1974 return null;
1975 }
1976 break;
1977 }
1978 case DOUBLE_ARRAY: {
1979 double[] valueDoubleArray = null;
1980 if (valueList.size() > 0) {
1981 valueDoubleArray = new double[valueList.size()];
1982 for (int i = 0; i < valueList.size(); i++) {
1983 try {
1984 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1985 } catch (NumberFormatException nfe) {
1986 // Not a valid double
1987 errPw.println(
1988 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1989 return null;
1990 }
1991 }
1992 }
1993 bundle.putDoubleArray(key, valueDoubleArray);
1994 break;
1995 }
1996 case INT: {
1997 try {
1998 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1999 } catch (NumberFormatException nfe) {
2000 // Not a valid integer
2001 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2002 return null;
2003 }
2004 break;
2005 }
2006 case INT_ARRAY: {
2007 int[] valueIntArray = null;
2008 if (valueList.size() > 0) {
2009 valueIntArray = new int[valueList.size()];
2010 for (int i = 0; i < valueList.size(); i++) {
2011 try {
2012 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2013 } catch (NumberFormatException nfe) {
2014 // Not a valid integer
2015 errPw.println(tag
2016 + "Unable to parse " + valueList.get(i) + " as an integer.");
2017 return null;
2018 }
2019 }
2020 }
2021 bundle.putIntArray(key, valueIntArray);
2022 break;
2023 }
2024 case LONG: {
2025 try {
2026 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2027 } catch (NumberFormatException nfe) {
2028 // Not a valid long
2029 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2030 return null;
2031 }
2032 break;
2033 }
2034 case LONG_ARRAY: {
2035 long[] valueLongArray = null;
2036 if (valueList.size() > 0) {
2037 valueLongArray = new long[valueList.size()];
2038 for (int i = 0; i < valueList.size(); i++) {
2039 try {
2040 valueLongArray[i] = Long.parseLong(valueList.get(i));
2041 } catch (NumberFormatException nfe) {
2042 // Not a valid long
2043 errPw.println(
2044 tag + "Unable to parse " + valueList.get(i) + " as a long");
2045 return null;
2046 }
2047 }
2048 }
2049 bundle.putLongArray(key, valueLongArray);
2050 break;
2051 }
2052 case STRING: {
2053 String value = null;
2054 if (valueList.size() > 0) {
2055 value = valueList.get(0);
2056 }
2057 bundle.putString(key, value);
2058 break;
2059 }
2060 case STRING_ARRAY: {
2061 String[] valueStringArray = null;
2062 if (valueList.size() > 0) {
2063 valueStringArray = new String[valueList.size()];
2064 valueList.toArray(valueStringArray);
2065 }
2066 bundle.putStringArray(key, valueStringArray);
2067 break;
2068 }
2069 }
2070 return bundle;
2071 }
Shuo Qian489d9282020-07-09 11:30:03 -07002072
2073 private int handleEndBlockSuppressionCommand() {
2074 if (!checkShellUid()) {
2075 return -1;
2076 }
2077
2078 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2079 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2080 }
2081 return 0;
2082 }
Hui Wang641e81c2020-10-12 12:14:23 -07002083
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002084 private int handleEuiccCommand() {
2085 String arg = getNextArg();
2086 if (arg == null) {
2087 onHelpEuicc();
2088 return 0;
2089 }
2090
2091 switch (arg) {
2092 case EUICC_SET_UI_COMPONENT: {
2093 return handleEuiccServiceCommand();
2094 }
2095 }
2096 return -1;
2097 }
2098
2099 private int handleEuiccServiceCommand() {
2100 String uiComponent = getNextArg();
2101 String packageName = getNextArg();
2102 if (packageName == null || uiComponent == null) {
2103 return -1;
2104 }
2105 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2106 if (VDBG) {
2107 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2108 + packageName);
2109 }
2110 return 0;
2111 }
2112
Michele Berionne54af4632020-12-28 20:23:16 +00002113 private int handleRestartModemCommand() {
2114 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2115 // non user build.
2116 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2117 getErrPrintWriter().println("RestartModem: Permission denied.");
2118 return -1;
2119 }
2120
2121 boolean result = TelephonyManager.getDefault().rebootRadio();
2122 getOutPrintWriter().println(result);
2123
2124 return result ? 0 : -1;
2125 }
2126
Ling Ma4fbab492022-01-25 22:36:16 +00002127 private int handleGetImei() {
2128 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2129 // non user build.
2130 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2131 getErrPrintWriter().println("Device IMEI: Permission denied.");
2132 return -1;
2133 }
2134
2135 final long identity = Binder.clearCallingIdentity();
2136
2137 String imei = null;
2138 String arg = getNextArg();
2139 if (arg != null) {
2140 try {
2141 int specifiedSlotIndex = Integer.parseInt(arg);
2142 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2143 } catch (NumberFormatException exception) {
2144 PrintWriter errPw = getErrPrintWriter();
2145 errPw.println("-s requires an integer as slot index.");
2146 return -1;
2147 }
2148
2149 } else {
2150 imei = TelephonyManager.from(mContext).getImei();
2151 }
2152 getOutPrintWriter().println("Device IMEI: " + imei);
2153
2154 Binder.restoreCallingIdentity(identity);
2155 return 0;
2156 }
2157
Michele Berionne5e411512020-11-13 02:36:59 +00002158 private int handleUnattendedReboot() {
2159 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2160 // non user build.
2161 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2162 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2163 return -1;
2164 }
2165
2166 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2167 getOutPrintWriter().println("result: " + result);
2168
2169 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2170 }
2171
Aman Gupta07124872022-02-09 08:02:14 +00002172 private int handleGetSimSlotsMapping() {
2173 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2174 // non user build.
2175 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2176 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2177 return -1;
2178 }
2179 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2180 String result = telephonyManager.getSimSlotMapping().toString();
2181 getOutPrintWriter().println("simSlotsMapping: " + result);
2182
2183 return 0;
2184 }
2185
Hui Wang641e81c2020-10-12 12:14:23 -07002186 private int handleGbaCommand() {
2187 String arg = getNextArg();
2188 if (arg == null) {
2189 onHelpGba();
2190 return 0;
2191 }
2192
2193 switch (arg) {
2194 case GBA_SET_SERVICE: {
2195 return handleGbaSetServiceCommand();
2196 }
2197 case GBA_GET_SERVICE: {
2198 return handleGbaGetServiceCommand();
2199 }
2200 case GBA_SET_RELEASE_TIME: {
2201 return handleGbaSetReleaseCommand();
2202 }
2203 case GBA_GET_RELEASE_TIME: {
2204 return handleGbaGetReleaseCommand();
2205 }
2206 }
2207
2208 return -1;
2209 }
2210
2211 private int getSubId(String cmd) {
2212 int slotId = getDefaultSlot();
2213 String opt = getNextOption();
2214 if (opt != null && opt.equals("-s")) {
2215 try {
2216 slotId = Integer.parseInt(getNextArgRequired());
2217 } catch (NumberFormatException e) {
2218 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2219 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2220 }
2221 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002222 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002223 }
2224
2225 private int handleGbaSetServiceCommand() {
2226 int subId = getSubId("gba set-service");
2227 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2228 return -1;
2229 }
2230
2231 String packageName = getNextArg();
2232 try {
2233 if (packageName == null) {
2234 packageName = "";
2235 }
2236 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2237 if (VDBG) {
2238 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2239 + packageName + ", result=" + result);
2240 }
2241 getOutPrintWriter().println(result);
2242 } catch (RemoteException e) {
2243 Log.w(LOG_TAG, "gba set-service " + subId + " "
2244 + packageName + ", error" + e.getMessage());
2245 getErrPrintWriter().println("Exception: " + e.getMessage());
2246 return -1;
2247 }
2248 return 0;
2249 }
2250
2251 private int handleGbaGetServiceCommand() {
2252 String result;
2253
2254 int subId = getSubId("gba get-service");
2255 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2256 return -1;
2257 }
2258
2259 try {
2260 result = mInterface.getBoundGbaService(subId);
2261 } catch (RemoteException e) {
2262 return -1;
2263 }
2264 if (VDBG) {
2265 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2266 }
2267 getOutPrintWriter().println(result);
2268 return 0;
2269 }
2270
2271 private int handleGbaSetReleaseCommand() {
2272 //the release time value could be -1
2273 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2274 : SubscriptionManager.getDefaultSubscriptionId();
2275 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2276 return -1;
2277 }
2278
2279 String intervalStr = getNextArg();
2280 if (intervalStr == null) {
2281 return -1;
2282 }
2283
2284 try {
2285 int interval = Integer.parseInt(intervalStr);
2286 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2287 if (VDBG) {
2288 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2289 + intervalStr + ", result=" + result);
2290 }
2291 getOutPrintWriter().println(result);
2292 } catch (NumberFormatException | RemoteException e) {
2293 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2294 + intervalStr + ", error" + e.getMessage());
2295 getErrPrintWriter().println("Exception: " + e.getMessage());
2296 return -1;
2297 }
2298 return 0;
2299 }
2300
2301 private int handleGbaGetReleaseCommand() {
2302 int subId = getSubId("gba get-release");
2303 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2304 return -1;
2305 }
2306
2307 int result = 0;
2308 try {
2309 result = mInterface.getGbaReleaseTime(subId);
2310 } catch (RemoteException e) {
2311 return -1;
2312 }
2313 if (VDBG) {
2314 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2315 }
2316 getOutPrintWriter().println(result);
2317 return 0;
2318 }
Hui Wang761a6682020-10-31 05:12:53 +00002319
2320 private int handleSingleRegistrationConfigCommand() {
2321 String arg = getNextArg();
2322 if (arg == null) {
2323 onHelpSrc();
2324 return 0;
2325 }
2326
2327 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002328 case SRC_SET_TEST_ENABLED: {
2329 return handleSrcSetTestEnabledCommand();
2330 }
2331 case SRC_GET_TEST_ENABLED: {
2332 return handleSrcGetTestEnabledCommand();
2333 }
Hui Wang761a6682020-10-31 05:12:53 +00002334 case SRC_SET_DEVICE_ENABLED: {
2335 return handleSrcSetDeviceEnabledCommand();
2336 }
2337 case SRC_GET_DEVICE_ENABLED: {
2338 return handleSrcGetDeviceEnabledCommand();
2339 }
2340 case SRC_SET_CARRIER_ENABLED: {
2341 return handleSrcSetCarrierEnabledCommand();
2342 }
2343 case SRC_GET_CARRIER_ENABLED: {
2344 return handleSrcGetCarrierEnabledCommand();
2345 }
Hui Wangb647abe2021-02-26 09:33:38 -08002346 case SRC_SET_FEATURE_ENABLED: {
2347 return handleSrcSetFeatureValidationCommand();
2348 }
2349 case SRC_GET_FEATURE_ENABLED: {
2350 return handleSrcGetFeatureValidationCommand();
2351 }
Hui Wang761a6682020-10-31 05:12:53 +00002352 }
2353
2354 return -1;
2355 }
2356
James.cf Linbcdf8b32021-01-14 16:44:13 +08002357 private int handleRcsUceCommand() {
2358 String arg = getNextArg();
2359 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002360 onHelpUce();
2361 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002362 }
2363
2364 switch (arg) {
2365 case UCE_REMOVE_EAB_CONTACT:
2366 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002367 case UCE_GET_EAB_CONTACT:
2368 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002369 case UCE_GET_EAB_CAPABILITY:
2370 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002371 case UCE_GET_DEVICE_ENABLED:
2372 return handleUceGetDeviceEnabledCommand();
2373 case UCE_SET_DEVICE_ENABLED:
2374 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002375 case UCE_OVERRIDE_PUBLISH_CAPS:
2376 return handleUceOverridePublishCaps();
2377 case UCE_GET_LAST_PIDF_XML:
2378 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002379 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2380 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002381 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2382 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002383 }
2384 return -1;
2385 }
2386
2387 private int handleRemovingEabContactCommand() {
2388 int subId = getSubId("uce remove-eab-contact");
2389 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2390 return -1;
2391 }
2392
2393 String phoneNumber = getNextArgRequired();
2394 if (TextUtils.isEmpty(phoneNumber)) {
2395 return -1;
2396 }
2397 int result = 0;
2398 try {
2399 result = mInterface.removeContactFromEab(subId, phoneNumber);
2400 } catch (RemoteException e) {
2401 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2402 getErrPrintWriter().println("Exception: " + e.getMessage());
2403 return -1;
2404 }
2405
2406 if (VDBG) {
2407 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2408 }
calvinpan293ea1b2021-02-04 17:52:13 +08002409 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002410 }
2411
calvinpane4a8a1d2021-01-25 13:51:18 +08002412 private int handleGettingEabContactCommand() {
2413 String phoneNumber = getNextArgRequired();
2414 if (TextUtils.isEmpty(phoneNumber)) {
2415 return -1;
2416 }
2417 String result = "";
2418 try {
2419 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002420 } catch (RemoteException e) {
2421 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2422 getErrPrintWriter().println("Exception: " + e.getMessage());
2423 return -1;
2424 }
2425
2426 if (VDBG) {
2427 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2428 }
calvinpan293ea1b2021-02-04 17:52:13 +08002429 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002430 return 0;
2431 }
2432
Calvin Pana1434322021-07-01 19:27:01 +08002433 private int handleGettingEabCapabilityCommand() {
2434 String phoneNumber = getNextArgRequired();
2435 if (TextUtils.isEmpty(phoneNumber)) {
2436 return -1;
2437 }
2438 String result = "";
2439 try {
2440 result = mInterface.getCapabilityFromEab(phoneNumber);
2441 } catch (RemoteException e) {
2442 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2443 getErrPrintWriter().println("Exception: " + e.getMessage());
2444 return -1;
2445 }
2446
2447 if (VDBG) {
2448 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2449 }
2450 getOutPrintWriter().println(result);
2451 return 0;
2452 }
2453
James.cf Lin4b784aa2021-01-31 03:25:15 +08002454 private int handleUceGetDeviceEnabledCommand() {
2455 boolean result = false;
2456 try {
2457 result = mInterface.getDeviceUceEnabled();
2458 } catch (RemoteException e) {
2459 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2460 return -1;
2461 }
2462 if (VDBG) {
2463 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2464 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002465 getOutPrintWriter().println(result);
2466 return 0;
2467 }
2468
James.cf Lin4b784aa2021-01-31 03:25:15 +08002469 private int handleUceSetDeviceEnabledCommand() {
2470 String enabledStr = getNextArg();
2471 if (TextUtils.isEmpty(enabledStr)) {
2472 return -1;
2473 }
2474
2475 try {
2476 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2477 mInterface.setDeviceUceEnabled(isEnabled);
2478 if (VDBG) {
2479 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2480 }
2481 } catch (NumberFormatException | RemoteException e) {
2482 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2483 getErrPrintWriter().println("Exception: " + e.getMessage());
2484 return -1;
2485 }
2486 return 0;
2487 }
2488
James.cf Line8713a42021-04-29 16:04:26 +08002489 private int handleUceRemoveRequestDisallowedStatus() {
2490 int subId = getSubId("uce remove-request-disallowed-status");
2491 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2492 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2493 return -1;
2494 }
2495 boolean result;
2496 try {
2497 result = mInterface.removeUceRequestDisallowedStatus(subId);
2498 } catch (RemoteException e) {
2499 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2500 return -1;
2501 }
2502 if (VDBG) {
2503 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2504 }
2505 getOutPrintWriter().println(result);
2506 return 0;
2507 }
2508
James.cf Lin0fc71b02021-05-25 01:37:38 +08002509 private int handleUceSetCapRequestTimeout() {
2510 int subId = getSubId("uce set-capabilities-request-timeout");
2511 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2512 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2513 return -1;
2514 }
2515 long timeoutAfterMs = Long.valueOf(getNextArg());
2516 boolean result;
2517 try {
2518 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2519 } catch (RemoteException e) {
2520 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2521 return -1;
2522 }
2523 if (VDBG) {
2524 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2525 }
2526 getOutPrintWriter().println(result);
2527 return 0;
2528 }
2529
Hui Wangbaaee6a2021-02-19 20:45:36 -08002530 private int handleSrcSetTestEnabledCommand() {
2531 String enabledStr = getNextArg();
2532 if (enabledStr == null) {
2533 return -1;
2534 }
2535
2536 try {
2537 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2538 if (VDBG) {
2539 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2540 }
2541 getOutPrintWriter().println("Done");
2542 } catch (NumberFormatException | RemoteException e) {
2543 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2544 getErrPrintWriter().println("Exception: " + e.getMessage());
2545 return -1;
2546 }
2547 return 0;
2548 }
2549
2550 private int handleSrcGetTestEnabledCommand() {
2551 boolean result = false;
2552 try {
2553 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2554 } catch (RemoteException e) {
2555 return -1;
2556 }
2557 if (VDBG) {
2558 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2559 }
2560 getOutPrintWriter().println(result);
2561 return 0;
2562 }
2563
Brad Ebinger14d467f2021-02-12 06:18:28 +00002564 private int handleUceOverridePublishCaps() {
2565 int subId = getSubId("uce override-published-caps");
2566 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2567 return -1;
2568 }
2569 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2570 String operation = getNextArgRequired();
2571 String caps = getNextArg();
2572 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2573 && !"list".equals(operation)) {
2574 getErrPrintWriter().println("Invalid operation: " + operation);
2575 return -1;
2576 }
2577
2578 // add/remove requires capabilities to be specified.
2579 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2580 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2581 + "specified");
2582 return -1;
2583 }
2584
2585 ArraySet<String> capSet = new ArraySet<>();
2586 if (!TextUtils.isEmpty(caps)) {
2587 String[] capArray = caps.split(":");
2588 for (String cap : capArray) {
2589 // Allow unknown tags to be passed in as well.
2590 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2591 }
2592 }
2593
2594 RcsContactUceCapability result = null;
2595 try {
2596 switch (operation) {
2597 case "add":
2598 result = mInterface.addUceRegistrationOverrideShell(subId,
2599 new ArrayList<>(capSet));
2600 break;
2601 case "remove":
2602 result = mInterface.removeUceRegistrationOverrideShell(subId,
2603 new ArrayList<>(capSet));
2604 break;
2605 case "clear":
2606 result = mInterface.clearUceRegistrationOverrideShell(subId);
2607 break;
2608 case "list":
2609 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2610 break;
2611 }
2612 } catch (RemoteException e) {
2613 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2614 getErrPrintWriter().println("Exception: " + e.getMessage());
2615 return -1;
2616 } catch (ServiceSpecificException sse) {
2617 // Reconstruct ImsException
2618 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2619 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2620 getErrPrintWriter().println("Exception: " + imsException);
2621 return -1;
2622 }
2623 if (result == null) {
2624 getErrPrintWriter().println("Service not available");
2625 return -1;
2626 }
2627 getOutPrintWriter().println(result);
2628 return 0;
2629 }
2630
2631 private int handleUceGetPidfXml() {
2632 int subId = getSubId("uce get-last-publish-pidf");
2633 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2634 return -1;
2635 }
2636
2637 String result;
2638 try {
2639 result = mInterface.getLastUcePidfXmlShell(subId);
2640 } catch (RemoteException e) {
2641 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2642 getErrPrintWriter().println("Exception: " + e.getMessage());
2643 return -1;
2644 } catch (ServiceSpecificException sse) {
2645 // Reconstruct ImsException
2646 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2647 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2648 getErrPrintWriter().println("Exception: " + imsException);
2649 return -1;
2650 }
2651 if (result == null) {
2652 getErrPrintWriter().println("Service not available");
2653 return -1;
2654 }
2655 getOutPrintWriter().println(result);
2656 return 0;
2657 }
2658
Hui Wang761a6682020-10-31 05:12:53 +00002659 private int handleSrcSetDeviceEnabledCommand() {
2660 String enabledStr = getNextArg();
2661 if (enabledStr == null) {
2662 return -1;
2663 }
2664
2665 try {
2666 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2667 if (VDBG) {
2668 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2669 }
2670 getOutPrintWriter().println("Done");
2671 } catch (NumberFormatException | RemoteException e) {
2672 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2673 getErrPrintWriter().println("Exception: " + e.getMessage());
2674 return -1;
2675 }
2676 return 0;
2677 }
2678
2679 private int handleSrcGetDeviceEnabledCommand() {
2680 boolean result = false;
2681 try {
2682 result = mInterface.getDeviceSingleRegistrationEnabled();
2683 } catch (RemoteException e) {
2684 return -1;
2685 }
2686 if (VDBG) {
2687 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2688 }
2689 getOutPrintWriter().println(result);
2690 return 0;
2691 }
2692
2693 private int handleSrcSetCarrierEnabledCommand() {
2694 //the release time value could be -1
2695 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2696 : SubscriptionManager.getDefaultSubscriptionId();
2697 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2698 return -1;
2699 }
2700
2701 String enabledStr = getNextArg();
2702 if (enabledStr == null) {
2703 return -1;
2704 }
2705
2706 try {
2707 boolean result =
2708 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2709 if (VDBG) {
2710 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2711 + enabledStr + ", result=" + result);
2712 }
2713 getOutPrintWriter().println(result);
2714 } catch (NumberFormatException | RemoteException e) {
2715 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2716 + enabledStr + ", error" + e.getMessage());
2717 getErrPrintWriter().println("Exception: " + e.getMessage());
2718 return -1;
2719 }
2720 return 0;
2721 }
2722
2723 private int handleSrcGetCarrierEnabledCommand() {
2724 int subId = getSubId("src get-carrier-enabled");
2725 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2726 return -1;
2727 }
2728
2729 boolean result = false;
2730 try {
2731 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2732 } catch (RemoteException e) {
2733 return -1;
2734 }
2735 if (VDBG) {
2736 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2737 }
2738 getOutPrintWriter().println(result);
2739 return 0;
2740 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002741
Hui Wangb647abe2021-02-26 09:33:38 -08002742 private int handleSrcSetFeatureValidationCommand() {
2743 //the release time value could be -1
2744 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2745 : SubscriptionManager.getDefaultSubscriptionId();
2746 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2747 return -1;
2748 }
2749
2750 String enabledStr = getNextArg();
2751 if (enabledStr == null) {
2752 return -1;
2753 }
2754
2755 try {
2756 boolean result =
2757 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2758 if (VDBG) {
2759 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2760 + enabledStr + ", result=" + result);
2761 }
2762 getOutPrintWriter().println(result);
2763 } catch (NumberFormatException | RemoteException e) {
2764 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2765 + enabledStr + ", error" + e.getMessage());
2766 getErrPrintWriter().println("Exception: " + e.getMessage());
2767 return -1;
2768 }
2769 return 0;
2770 }
2771
2772 private int handleSrcGetFeatureValidationCommand() {
2773 int subId = getSubId("src get-feature-validation");
2774 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2775 return -1;
2776 }
2777
2778 Boolean result = false;
2779 try {
2780 result = mInterface.getImsFeatureValidationOverride(subId);
2781 } catch (RemoteException e) {
2782 return -1;
2783 }
2784 if (VDBG) {
2785 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2786 }
2787 getOutPrintWriter().println(result);
2788 return 0;
2789 }
2790
2791
Hall Liuaa4211e2021-01-20 15:43:39 -08002792 private void onHelpCallComposer() {
2793 PrintWriter pw = getOutPrintWriter();
2794 pw.println("Call composer commands");
2795 pw.println(" callcomposer test-mode enable|disable|query");
2796 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2797 pw.println(" upload/download from carrier servers is disabled, and operations are");
2798 pw.println(" performed using emulated local files instead.");
2799 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2800 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2801 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002802 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2803 pw.println(" Enables or disables the user setting for call composer, as set by");
2804 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002805 }
2806
2807 private int handleCallComposerCommand() {
2808 String arg = getNextArg();
2809 if (arg == null) {
2810 onHelpCallComposer();
2811 return 0;
2812 }
2813
2814 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2815 "MODIFY_PHONE_STATE required for call composer shell cmds");
2816 switch (arg) {
2817 case CALL_COMPOSER_TEST_MODE: {
2818 String enabledStr = getNextArg();
2819 if (ENABLE.equals(enabledStr)) {
2820 CallComposerPictureManager.sTestMode = true;
2821 } else if (DISABLE.equals(enabledStr)) {
2822 CallComposerPictureManager.sTestMode = false;
2823 } else if (QUERY.equals(enabledStr)) {
2824 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2825 } else {
2826 onHelpCallComposer();
2827 return 1;
2828 }
2829 break;
2830 }
2831 case CALL_COMPOSER_SIMULATE_CALL: {
2832 int subscriptionId = Integer.valueOf(getNextArg());
2833 String uuidString = getNextArg();
2834 UUID uuid = UUID.fromString(uuidString);
2835 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2836 Binder.withCleanCallingIdentity(() -> {
2837 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2838 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2839 });
2840 try {
2841 Uri uri = storageUriFuture.get();
2842 getOutPrintWriter().println(String.valueOf(uri));
2843 } catch (Exception e) {
2844 throw new RuntimeException(e);
2845 }
2846 break;
2847 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002848 case CALL_COMPOSER_USER_SETTING: {
2849 try {
2850 int subscriptionId = Integer.valueOf(getNextArg());
2851 String enabledStr = getNextArg();
2852 if (ENABLE.equals(enabledStr)) {
2853 mInterface.setCallComposerStatus(subscriptionId,
2854 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2855 } else if (DISABLE.equals(enabledStr)) {
2856 mInterface.setCallComposerStatus(subscriptionId,
2857 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2858 } else if (QUERY.equals(enabledStr)) {
2859 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2860 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2861 } else {
2862 onHelpCallComposer();
2863 return 1;
2864 }
2865 } catch (RemoteException e) {
2866 e.printStackTrace(getOutPrintWriter());
2867 return 1;
2868 }
2869 break;
2870 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002871 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002872 return 0;
2873 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002874
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002875 private int handleHasCarrierPrivilegesCommand() {
2876 String packageName = getNextArgRequired();
2877
2878 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002879 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002880 try {
2881 hasCarrierPrivileges =
2882 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2883 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2884 } catch (RemoteException e) {
2885 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2886 getErrPrintWriter().println("Exception: " + e.getMessage());
2887 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002888 } finally {
2889 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002890 }
2891
2892 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002893 return 0;
2894 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002895
2896 private int handleAllowedNetworkTypesCommand(String command) {
2897 if (!checkShellUid()) {
2898 return -1;
2899 }
2900
2901 PrintWriter errPw = getErrPrintWriter();
2902 String tag = command + ": ";
2903 String opt;
2904 int subId = -1;
2905 Log.v(LOG_TAG, command + " start");
2906
2907 while ((opt = getNextOption()) != null) {
2908 if (opt.equals("-s")) {
2909 try {
2910 subId = slotStringToSubId(tag, getNextArgRequired());
2911 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2912 errPw.println(tag + "No valid subscription found.");
2913 return -1;
2914 }
2915 } catch (IllegalArgumentException e) {
2916 // Missing slot id
2917 errPw.println(tag + "SLOT_ID expected after -s.");
2918 return -1;
2919 }
2920 } else {
2921 errPw.println(tag + "Unknown option " + opt);
2922 return -1;
2923 }
2924 }
2925
2926 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2927 return handleGetAllowedNetworkTypesCommand(subId);
2928 }
2929 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2930 return handleSetAllowedNetworkTypesCommand(subId);
2931 }
2932 return -1;
2933 }
2934
2935 private int handleGetAllowedNetworkTypesCommand(int subId) {
2936 PrintWriter errPw = getErrPrintWriter();
2937
2938 long result = -1;
2939 try {
2940 if (mInterface != null) {
2941 result = mInterface.getAllowedNetworkTypesForReason(subId,
2942 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2943 } else {
2944 throw new IllegalStateException("telephony service is null.");
2945 }
2946 } catch (RemoteException e) {
2947 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2948 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2949 return -1;
2950 }
2951
2952 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2953 return 0;
2954 }
2955
2956 private int handleSetAllowedNetworkTypesCommand(int subId) {
2957 PrintWriter errPw = getErrPrintWriter();
2958
2959 String bitmaskString = getNextArg();
2960 if (TextUtils.isEmpty(bitmaskString)) {
2961 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2962 return -1;
2963 }
2964 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2965 if (allowedNetworkTypes < 0) {
2966 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2967 return -1;
2968 }
2969 boolean result = false;
2970 try {
2971 if (mInterface != null) {
2972 result = mInterface.setAllowedNetworkTypesForReason(subId,
2973 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2974 } else {
2975 throw new IllegalStateException("telephony service is null.");
2976 }
2977 } catch (RemoteException e) {
2978 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2979 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2980 return -1;
2981 }
2982
2983 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2984 if (result) {
2985 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2986 }
2987 getOutPrintWriter().println(resultMessage);
2988 return 0;
2989 }
2990
2991 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2992 if (TextUtils.isEmpty(bitmaskString)) {
2993 return -1;
2994 }
2995 if (VDBG) {
2996 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2997 + ", length: " + bitmaskString.length());
2998 }
2999 try {
3000 return Long.parseLong(bitmaskString, 2);
3001 } catch (NumberFormatException e) {
3002 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3003 return -1;
3004 }
3005 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003006
jimsun3b9ccac2021-10-26 15:01:23 +08003007 private int handleRadioSetModemServiceCommand() {
3008 PrintWriter errPw = getErrPrintWriter();
3009 String serviceName = null;
3010
3011 String opt;
3012 while ((opt = getNextOption()) != null) {
3013 switch (opt) {
3014 case "-s": {
3015 serviceName = getNextArgRequired();
3016 break;
3017 }
3018 }
3019 }
3020
3021 try {
3022 boolean result = mInterface.setModemService(serviceName);
3023 if (VDBG) {
3024 Log.v(LOG_TAG,
3025 "RadioSetModemService " + serviceName + ", result = " + result);
3026 }
3027 getOutPrintWriter().println(result);
3028 } catch (RemoteException e) {
3029 Log.w(LOG_TAG,
3030 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3031 errPw.println("Exception: " + e.getMessage());
3032 return -1;
3033 }
3034 return 0;
3035 }
3036
3037 private int handleRadioGetModemServiceCommand() {
3038 PrintWriter errPw = getErrPrintWriter();
3039 String result;
3040
3041 try {
3042 result = mInterface.getModemService();
3043 getOutPrintWriter().println(result);
3044 } catch (RemoteException e) {
3045 errPw.println("Exception: " + e.getMessage());
3046 return -1;
3047 }
3048 if (VDBG) {
3049 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3050 }
3051 return 0;
3052 }
3053
3054 private int handleRadioCommand() {
3055 String arg = getNextArg();
3056 if (arg == null) {
3057 onHelpRadio();
3058 return 0;
3059 }
3060
3061 switch (arg) {
3062 case RADIO_SET_MODEM_SERVICE:
3063 return handleRadioSetModemServiceCommand();
3064
3065 case RADIO_GET_MODEM_SERVICE:
3066 return handleRadioGetModemServiceCommand();
3067 }
3068
3069 return -1;
3070 }
arunvoddud7401012022-12-15 16:08:12 +00003071
3072 private int handleCarrierRestrictionStatusCommand() {
3073 try {
3074 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3075 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3076 mInterface.getModemService()))) {
3077 Log.v(LOG_TAG,
3078 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3079 + " checkShellUid fails");
3080 return -1;
3081 }
3082 } catch (RemoteException ex) {
3083 ex.printStackTrace();
3084 }
3085 String callerInfo = getNextOption();
3086 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3087 if (TextUtils.isEmpty(callerInfo)) {
3088 // reset the Json content after testing
3089 allowListInfo.updateJsonForTest(null);
3090 return 0;
3091 }
3092 if (callerInfo.startsWith("--")) {
3093 callerInfo = callerInfo.replace("--", "");
3094 }
3095 String params[] = callerInfo.split(",");
3096 StringBuffer jsonStrBuffer = new StringBuffer();
3097 String tokens;
3098 for (int index = 0; index < params.length; index++) {
3099 tokens = convertToJsonString(index, params[index]);
3100 if (TextUtils.isEmpty(tokens)) {
3101 // received wrong format from CTS
3102 if (VDBG) {
3103 Log.v(LOG_TAG,
3104 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3105 }
3106 return -1;
3107 }
3108 jsonStrBuffer.append(tokens);
3109 }
3110 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3111 return result;
3112 }
3113
Benedict Wong66477622023-02-03 23:30:57 +00003114 // set-carrier-service-package-override
3115 private int setCarrierServicePackageOverride() {
3116 PrintWriter errPw = getErrPrintWriter();
3117 int subId = SubscriptionManager.getDefaultSubscriptionId();
3118
3119 String opt;
3120 while ((opt = getNextOption()) != null) {
3121 switch (opt) {
3122 case "-s":
3123 try {
3124 subId = Integer.parseInt(getNextArgRequired());
3125 } catch (NumberFormatException e) {
3126 errPw.println(
3127 "set-carrier-service-package-override requires an integer as a"
3128 + " subscription ID.");
3129 return -1;
3130 }
3131 break;
3132 }
3133 }
3134
3135 String packageName = getNextArg();
3136 if (packageName == null) {
3137 errPw.println("set-carrier-service-package-override requires a override package name.");
3138 return -1;
3139 }
3140
3141 try {
3142 mInterface.setCarrierServicePackageOverride(
3143 subId, packageName, mContext.getOpPackageName());
3144
3145 if (VDBG) {
3146 Log.v(
3147 LOG_TAG,
3148 "set-carrier-service-package-override -s " + subId + " " + packageName);
3149 }
3150 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3151 Log.w(
3152 LOG_TAG,
3153 "set-carrier-service-package-override -s "
3154 + subId
3155 + " "
3156 + packageName
3157 + ", error"
3158 + e.getMessage());
3159 errPw.println("Exception: " + e.getMessage());
3160 return -1;
3161 }
3162 return 0;
3163 }
3164
3165 // clear-carrier-service-package-override
3166 private int clearCarrierServicePackageOverride() {
3167 PrintWriter errPw = getErrPrintWriter();
3168 int subId = getDefaultSlot();
3169
3170 String opt;
3171 while ((opt = getNextOption()) != null) {
3172 switch (opt) {
3173 case "-s":
3174 try {
3175 subId = Integer.parseInt(getNextArgRequired());
3176 } catch (NumberFormatException e) {
3177 errPw.println(
3178 "clear-carrier-service-package-override requires an integer as a"
3179 + " subscription ID.");
3180 return -1;
3181 }
3182 break;
3183 }
3184 }
3185
3186 try {
3187 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3188
3189 if (VDBG) {
3190 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3191 }
3192 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3193 Log.w(
3194 LOG_TAG,
3195 "clear-carrier-service-package-override -s "
3196 + subId
3197 + ", error"
3198 + e.getMessage());
3199 errPw.println("Exception: " + e.getMessage());
3200 return -1;
3201 }
3202 return 0;
3203 }
arunvoddud7401012022-12-15 16:08:12 +00003204
3205 /**
3206 * Building the string that can be used to build the JsonObject which supports to stub the data
3207 * in CarrierAllowListInfo for CTS testing. sample format is like
3208 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3209 */
3210 private String convertToJsonString(int index, String param) {
3211
3212 String token[] = param.split(":");
3213 String jSonString;
3214 switch (index) {
3215 case 0:
3216 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3217 break;
3218 case 1:
3219 jSonString =
3220 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3221 break;
3222 case 2:
3223 jSonString =
3224 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3225 break;
3226 default:
3227 jSonString = null;
3228 }
3229 return jSonString;
3230 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003231}