blob: 53c7f4ed1cf72ddd29706411862569b941f29156 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Cole Faustc16d5292022-10-15 21:33:27 -070024import static java.util.Map.entry;
25
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010027import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080028import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080031import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000033import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070034import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070035import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010036import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070037import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000039import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070040import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080041import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000042import android.telephony.ims.ImsException;
43import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080044import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080045import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000046import android.util.ArrayMap;
47import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070049import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050
Brad Ebinger14d467f2021-02-12 06:18:28 +000051import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080053import com.android.internal.telephony.Phone;
54import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080055import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080056import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080057import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080058import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080059import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000060import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000061import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070062
Allen Xuee00f0e2022-03-14 21:04:49 +000063import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080065import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Arrays;
67import java.util.Collections;
Brad Ebinger24c29992019-12-05 13:03:21 -080068import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000069import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010070import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000071import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080073import java.util.UUID;
74import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070075
76/**
77 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
78 * permission checks have been done before onCommand was called. Make sure any commands processed
79 * here also contain the appropriate permissions checks.
80 */
81
Hall Liua1548bd2019-12-24 14:14:12 -080082public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
84 private static final String LOG_TAG = "TelephonyShellCommand";
85 // Don't commit with this true.
86 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070087 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070088
Hall Liuaa4211e2021-01-20 15:43:39 -080089 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070090 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080091 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080092 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080093 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070094 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000095 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000096 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010097 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080098 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String ENABLE = "enable";
100 private static final String DISABLE = "disable";
101 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000102 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000103 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
104 "set-carrier-service-package-override";
105 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
106 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000107 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800108
Hall Liu7135e502021-02-04 16:58:17 -0800109 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800110 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800111 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Brad Ebinger999d3302020-11-25 14:31:39 -0800113 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
114 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
115 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700116 // Used to disable or enable processing of conference event package data from the network.
117 // This is handy for testing scenarios where CEP data does not exist on a network which does
118 // support CEP data.
119 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700120
Hall Liud892bec2018-11-30 14:51:45 -0800121 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800122 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800123
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100124 private static final String CC_GET_VALUE = "get-value";
125 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000126 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private static final String CC_CLEAR_VALUES = "clear-values";
128
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000129 private static final String EUICC_SUBCOMMAND = "euicc";
130 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
131
Hui Wang641e81c2020-10-12 12:14:23 -0700132 private static final String GBA_SUBCOMMAND = "gba";
133 private static final String GBA_SET_SERVICE = "set-service";
134 private static final String GBA_GET_SERVICE = "get-service";
135 private static final String GBA_SET_RELEASE_TIME = "set-release";
136 private static final String GBA_GET_RELEASE_TIME = "get-release";
137
Hui Wang761a6682020-10-31 05:12:53 +0000138 private static final String SINGLE_REGISTATION_CONFIG = "src";
139 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
140 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
141 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
142 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800143 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
144 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800145 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
146 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000147
Tyler Gunn92479152021-01-20 16:30:10 -0800148 private static final String D2D_SUBCOMMAND = "d2d";
149 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800150 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700151 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800152
Nazanin014f41e2021-05-06 17:26:31 -0700153 private static final String BARRING_SUBCOMMAND = "barring";
154 private static final String BARRING_SEND_INFO = "send";
155
James.cf Linbcdf8b32021-01-14 16:44:13 +0800156 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800157 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800158 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800159 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800160 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
161 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000162 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
163 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800164 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
165 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800166 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
167 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800168
jimsun3b9ccac2021-10-26 15:01:23 +0800169 private static final String RADIO_SUBCOMMAND = "radio";
170 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
171 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
172
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800173 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
174 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
175
Jordan Liu0ccee222021-04-27 11:55:13 -0700176 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
177 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
178
Jack Nudelman644b91a2021-03-12 14:09:48 -0800179 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
180 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
181 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700182 private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
183 "set-satellite-service-package-name";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800184
Grant Menke567d48f2022-08-18 20:19:10 +0000185 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
186 + "'*', '#' or '+') needs to be specified after -a in the command ";
187
188 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
189 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
190 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
191
SongFerngWang98dd5992021-05-13 17:50:00 +0800192 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
193 "get-allowed-network-types-for-users";
194 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
195 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000196 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000197 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700198 // Take advantage of existing methods that already contain permissions checks when possible.
199 private final ITelephony mInterface;
200
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100201 private SubscriptionManager mSubscriptionManager;
202 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700203 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700204 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100205
206 private enum CcType {
207 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000208 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100209 }
210
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100211 private class CcOptionParseResult {
212 public int mSubId;
213 public boolean mPersistent;
214 }
215
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100216 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
217 // keys by looking at the end of the string which usually tells the type.
218 // For instance: "xxxx_string", "xxxx_string_array", etc.
219 // The carrier config keys in this map does not follow this convention. It is therefore not
220 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700221 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
222 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
223 CcType.STRING),
224 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
225 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
226 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
227 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
228 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
229 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
230 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
231 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
232 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
233 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
234 CcType.STRING),
235 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
236 CcType.STRING_ARRAY),
237 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
238 CcType.STRING_ARRAY),
239 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
240 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
241 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
242 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
243 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
244 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
245 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
246 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100247
Brad Ebinger14d467f2021-02-12 06:18:28 +0000248 /**
249 * Map from a shorthand string to the feature tags required in registration required in order
250 * for the RCS feature to be considered "capable".
251 */
252 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
253 static {
254 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
255 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
256 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
257 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
258 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
259 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
260 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
261 FeatureTags.FEATURE_TAG_VIDEO)));
262 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
263 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
264 map.put("call_comp",
265 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
266 map.put("call_comp_mmtel",
267 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
268 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
269 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
270 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
271 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
272 // version
273 map.put("chatbot", new ArraySet<>(Arrays.asList(
274 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
275 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
276 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
277 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000278 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000279 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
280 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
281 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
282 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
283 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000284 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000285 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
286 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
287 }
288
289
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100290 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700291 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100292 mCarrierConfigManager =
293 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
294 mSubscriptionManager = (SubscriptionManager)
295 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700296 mTelephonyRegistryManager = (TelephonyRegistryManager)
297 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700298 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700299 }
300
301 @Override
302 public int onCommand(String cmd) {
303 if (cmd == null) {
304 return handleDefaultCommands(null);
305 }
306
307 switch (cmd) {
308 case IMS_SUBCOMMAND: {
309 return handleImsCommand();
310 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800311 case RCS_UCE_COMMAND:
312 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800313 case NUMBER_VERIFICATION_SUBCOMMAND:
314 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800315 case EMERGENCY_CALLBACK_MODE:
316 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800317 case EMERGENCY_NUMBER_TEST_MODE:
318 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100319 case CARRIER_CONFIG_SUBCOMMAND: {
320 return handleCcCommand();
321 }
Shuo Qianf5125122019-12-16 17:03:07 -0800322 case DATA_TEST_MODE:
323 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700324 case END_BLOCK_SUPPRESSION:
325 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000326 case EUICC_SUBCOMMAND:
327 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700328 case GBA_SUBCOMMAND:
329 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800330 case D2D_SUBCOMMAND:
331 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700332 case BARRING_SUBCOMMAND:
333 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000334 case SINGLE_REGISTATION_CONFIG:
335 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000336 case RESTART_MODEM:
337 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800338 case CALL_COMPOSER_SUBCOMMAND:
339 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000340 case UNATTENDED_REBOOT:
341 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800342 case HAS_CARRIER_PRIVILEGES_COMMAND:
343 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800344 case THERMAL_MITIGATION_COMMAND:
345 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700346 case DISABLE_PHYSICAL_SUBSCRIPTION:
347 return handleEnablePhysicalSubscription(false);
348 case ENABLE_PHYSICAL_SUBSCRIPTION:
349 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800350 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
351 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
352 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000353 case GET_IMEI:
354 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000355 case GET_SIM_SLOTS_MAPPING:
356 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800357 case RADIO_SUBCOMMAND:
358 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000359 case CARRIER_RESTRICTION_STATUS_TEST:
360 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000361 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
362 return setCarrierServicePackageOverride();
363 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
364 return clearCarrierServicePackageOverride();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700365 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
366 return handleSetSatelliteServicePackageNameCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700367 default: {
368 return handleDefaultCommands(cmd);
369 }
370 }
371 }
372
373 @Override
374 public void onHelp() {
375 PrintWriter pw = getOutPrintWriter();
376 pw.println("Telephony Commands:");
377 pw.println(" help");
378 pw.println(" Print this help text.");
379 pw.println(" ims");
380 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800381 pw.println(" uce");
382 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800383 pw.println(" emergency-number-test-mode");
384 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700385 pw.println(" end-block-suppression");
386 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800387 pw.println(" data");
388 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100389 pw.println(" cc");
390 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700391 pw.println(" gba");
392 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000393 pw.println(" src");
394 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000395 pw.println(" restart-modem");
396 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000397 pw.println(" unattended-reboot");
398 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800399 pw.println(" has-carrier-privileges [package]");
400 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800401 pw.println(" get-allowed-network-types-for-users");
402 pw.println(" Get the Allowed Network Types.");
403 pw.println(" set-allowed-network-types-for-users");
404 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800405 pw.println(" radio");
406 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700407 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800408 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800409 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700410 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800411 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100412 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700413 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000414 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800415 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700416 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800417 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800418 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000419 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700420 onHelpSatellite();
Tyler Gunn92479152021-01-20 16:30:10 -0800421 }
422
423 private void onHelpD2D() {
424 PrintWriter pw = getOutPrintWriter();
425 pw.println("D2D Comms Commands:");
426 pw.println(" d2d send TYPE VALUE");
427 pw.println(" Sends a D2D message of specified type and value.");
428 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
429 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
430 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
431 MESSAGE_CALL_AUDIO_CODEC));
432 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
433 + Communicator.messageToString(
434 MESSAGE_DEVICE_BATTERY_STATE));
435 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
436 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800437 pw.println(" d2d transport TYPE");
438 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
439 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700440 pw.println(" d2d set-device-support true/default");
441 pw.println(" true - forces device support to be enabled for D2D.");
442 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
443 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700444 }
445
Nazanin014f41e2021-05-06 17:26:31 -0700446 private void onHelpBarring() {
447 PrintWriter pw = getOutPrintWriter();
448 pw.println("Barring Commands:");
449 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
450 + " -t CONDITIONAL_BARRING_TIME_SECS");
451 pw.println(" Notifies of a barring info change for the specified slot id.");
452 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
453 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
454 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
455 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
456 }
457
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700458 private void onHelpIms() {
459 PrintWriter pw = getOutPrintWriter();
460 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800461 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700462 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
463 pw.println(" ImsService. Options are:");
464 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
465 pw.println(" is specified, it will choose the default voice SIM slot.");
466 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
467 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800468 pw.println(" -f: Set the feature that this override if for, if no option is");
469 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700470 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
471 pw.println(" Gets the package name of the currently defined ImsService.");
472 pw.println(" Options are:");
473 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
474 pw.println(" is specified, it will choose the default voice SIM slot.");
475 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000476 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800477 pw.println(" -f: The feature type that the query will be requested for. If none is");
478 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800479 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
480 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
481 pw.println(" configuration overrides. Options are:");
482 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
483 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700484 pw.println(" ims enable [-s SLOT_ID]");
485 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
486 pw.println(" if none is specified.");
487 pw.println(" ims disable [-s SLOT_ID]");
488 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
489 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700490 pw.println(" ims conference-event-package [enable/disable]");
491 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700492 }
493
James.cf Linbcdf8b32021-01-14 16:44:13 +0800494 private void onHelpUce() {
495 PrintWriter pw = getOutPrintWriter();
496 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800497 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
498 pw.println(" Get the EAB contacts from the EAB database.");
499 pw.println(" Options are:");
500 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
501 pw.println(" Expected output format :");
502 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800503 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
504 pw.println(" Remove the EAB contacts from the EAB database.");
505 pw.println(" Options are:");
506 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
507 pw.println(" is specified, it will choose the default voice SIM slot.");
508 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800509 pw.println(" uce get-device-enabled");
510 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
511 pw.println(" uce set-device-enabled true|false");
512 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
513 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000514 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
515 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
516 pw.println(" Options are:");
517 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
518 pw.println(" is specified, it will choose the default voice SIM slot.");
519 pw.println(" add [CAPABILITY]: add a new capability");
520 pw.println(" remove [CAPABILITY]: remove a capability");
521 pw.println(" clear: clear all capability overrides");
522 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
523 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
524 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
525 pw.println(" chatbot_sa, chatbot_role] as well as full length");
526 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
527 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
528 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
529 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800530 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
531 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800532 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
533 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800534 }
535
Hall Liud892bec2018-11-30 14:51:45 -0800536 private void onHelpNumberVerification() {
537 PrintWriter pw = getOutPrintWriter();
538 pw.println("Number verification commands");
539 pw.println(" numverify override-package PACKAGE_NAME;");
540 pw.println(" Set the authorized package for number verification.");
541 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800542 pw.println(" numverify fake-call NUMBER;");
543 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
544 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800545 }
546
Jack Nudelman644b91a2021-03-12 14:09:48 -0800547 private void onHelpThermalMitigation() {
548 PrintWriter pw = getOutPrintWriter();
549 pw.println("Thermal mitigation commands");
550 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
551 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
552 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
553 pw.println(" Remove the package from one of the authorized packages for thermal "
554 + "mitigation.");
555 }
556
Jordan Liu0ccee222021-04-27 11:55:13 -0700557 private void onHelpDisableOrEnablePhysicalSubscription() {
558 PrintWriter pw = getOutPrintWriter();
559 pw.println("Disable or enable a physical subscription");
560 pw.println(" disable-physical-subscription SUB_ID");
561 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
562 pw.println(" enable-physical-subscription SUB_ID");
563 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
564 }
565
Shuo Qianf5125122019-12-16 17:03:07 -0800566 private void onHelpDataTestMode() {
567 PrintWriter pw = getOutPrintWriter();
568 pw.println("Mobile Data Test Mode Commands:");
569 pw.println(" data enable: enable mobile data connectivity");
570 pw.println(" data disable: disable mobile data connectivity");
571 }
572
sqian9d4df8b2019-01-15 18:32:07 -0800573 private void onHelpEmergencyNumber() {
574 PrintWriter pw = getOutPrintWriter();
575 pw.println("Emergency Number Test Mode Commands:");
576 pw.println(" emergency-number-test-mode ");
577 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
578 + " the test mode");
579 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700580 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800581 pw.println(" -c: clear the emergency number list in the test mode.");
582 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700583 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800584 pw.println(" -p: get the full emergency number list in the test mode.");
585 }
586
Shuo Qian489d9282020-07-09 11:30:03 -0700587 private void onHelpEndBlockSupperssion() {
588 PrintWriter pw = getOutPrintWriter();
589 pw.println("End Block Suppression command:");
590 pw.println(" end-block-suppression: disable suppressing blocking by contact");
591 pw.println(" with emergency services.");
592 }
593
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100594 private void onHelpCc() {
595 PrintWriter pw = getOutPrintWriter();
596 pw.println("Carrier Config Commands:");
597 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
598 pw.println(" Print carrier config values.");
599 pw.println(" Options are:");
600 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
601 pw.println(" is specified, it will choose the default voice SIM slot.");
602 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
603 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100604 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100605 pw.println(" Set carrier config KEY to NEW_VALUE.");
606 pw.println(" Options are:");
607 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
608 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100609 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100610 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
611 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
612 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
613 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000614 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
615 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
616 pw.println(" provided through standard input and follow CarrierConfig XML format.");
617 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
618 pw.println(" Options are:");
619 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
620 pw.println(" is specified, it will choose the default voice SIM slot.");
621 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100622 pw.println(" cc clear-values [-s SLOT_ID]");
623 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000624 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100625 pw.println(" Options are:");
626 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
627 pw.println(" is specified, it will choose the default voice SIM slot.");
628 }
629
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000630 private void onHelpEuicc() {
631 PrintWriter pw = getOutPrintWriter();
632 pw.println("Euicc Commands:");
633 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
634 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
635 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
636 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
637 }
638
Hui Wang641e81c2020-10-12 12:14:23 -0700639 private void onHelpGba() {
640 PrintWriter pw = getOutPrintWriter();
641 pw.println("Gba Commands:");
642 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
643 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
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 get-service [-s SLOT_ID]");
648 pw.println(" Gets the package name of the currently defined GbaService.");
649 pw.println(" Options are:");
650 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
651 pw.println(" is specified, it will choose the default voice SIM slot.");
652 pw.println(" gba set-release [-s SLOT_ID] n");
653 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
654 pw.println(" Do not release/unbind if n is -1.");
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 pw.println(" gba get-release [-s SLOT_ID]");
659 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
660 pw.println(" Options are:");
661 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
662 pw.println(" is specified, it will choose the default voice SIM slot.");
663 }
664
Hui Wang761a6682020-10-31 05:12:53 +0000665 private void onHelpSrc() {
666 PrintWriter pw = getOutPrintWriter();
667 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800668 pw.println(" src set-test-enabled true|false");
669 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
670 pw.println(" The value could be true, false, or null(undefined).");
671 pw.println(" src get-test-enabled");
672 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000673 pw.println(" src set-device-enabled true|false|null");
674 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
675 pw.println(" The value could be true, false, or null(undefined).");
676 pw.println(" src get-device-enabled");
677 pw.println(" Gets the device config for RCS VoLTE single registration.");
678 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
679 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
680 pw.println(" The value could be true, false, or null(undefined).");
681 pw.println(" Options are:");
682 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
683 pw.println(" is specified, it will choose the default voice SIM slot.");
684 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
685 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
686 pw.println(" Options are:");
687 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
688 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800689 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
690 pw.println(" Sets ims feature validation result.");
691 pw.println(" The value could be true, false, or null(undefined).");
692 pw.println(" Options are:");
693 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
694 pw.println(" is specified, it will choose the default voice SIM slot.");
695 pw.println(" src get-feature-validation [-s SLOT_ID]");
696 pw.println(" Gets ims feature validation override value.");
697 pw.println(" Options are:");
698 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
699 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000700 }
701
SongFerngWang98dd5992021-05-13 17:50:00 +0800702 private void onHelpAllowedNetworkTypes() {
703 PrintWriter pw = getOutPrintWriter();
704 pw.println("Allowed Network Types Commands:");
705 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
706 pw.println(" Print allowed network types value.");
707 pw.println(" Options are:");
708 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
709 pw.println(" option is specified, it will choose the default voice SIM slot.");
710 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
711 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
712 pw.println(" Options are:");
713 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
714 pw.println(" option is specified, it will choose the default voice SIM slot.");
715 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
716 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
717 pw.println(" at TelephonyManager.java");
718 pw.println(" For example:");
719 pw.println(" NR only : 10000000000000000000");
720 pw.println(" NR|LTE : 11000001000000000000");
721 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
722 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
723 pw.println(" LTE only : 01000001000000000000");
724 }
725
jimsun3b9ccac2021-10-26 15:01:23 +0800726 private void onHelpRadio() {
727 PrintWriter pw = getOutPrintWriter();
728 pw.println("Radio Commands:");
729 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
730 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
731 pw.println(" to be the bound. Options are:");
732 pw.println(" -s: the service name that the modem service should be bound for.");
733 pw.println(" If no option is specified, it will bind to the default.");
734 pw.println(" radio get-modem-service");
735 pw.println(" Gets the service name of the currently defined modem service.");
736 pw.println(" If it is binding to default, 'default' returns.");
737 pw.println(" If it doesn't bind to any modem service for some reasons,");
738 pw.println(" the result would be 'unknown'.");
739 }
740
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700741 private void onHelpSatellite() {
742 PrintWriter pw = getOutPrintWriter();
743 pw.println("Satellite Commands:");
744 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
745 pw.println(" Sets the package name of satellite service defined in");
746 pw.println(" SERVICE_PACKAGE_NAME to be the bound. Options are:");
747 pw.println(" -s: the satellite service package name that Telephony will bind to.");
748 pw.println(" If no option is specified, it will bind to the default.");
749 }
750
Ling Ma4fbab492022-01-25 22:36:16 +0000751 private void onHelpImei() {
752 PrintWriter pw = getOutPrintWriter();
753 pw.println("IMEI Commands:");
754 pw.println(" get-imei [-s SLOT_ID]");
755 pw.println(" Gets the device IMEI. Options are:");
756 pw.println(" -s: the slot ID to get the IMEI. If no option");
757 pw.println(" is specified, it will choose the default voice SIM slot.");
758 }
759
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700760 private int handleImsCommand() {
761 String arg = getNextArg();
762 if (arg == null) {
763 onHelpIms();
764 return 0;
765 }
766
767 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800768 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700769 return handleImsSetServiceCommand();
770 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800771 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700772 return handleImsGetServiceCommand();
773 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800774 case IMS_CLEAR_SERVICE_OVERRIDE: {
775 return handleImsClearCarrierServiceCommand();
776 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800777 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700778 return handleEnableIms();
779 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800780 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700781 return handleDisableIms();
782 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700783 case IMS_CEP: {
784 return handleCepChange();
785 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700786 }
787
788 return -1;
789 }
790
Shuo Qianf5125122019-12-16 17:03:07 -0800791 private int handleDataTestModeCommand() {
792 PrintWriter errPw = getErrPrintWriter();
793 String arg = getNextArgRequired();
794 if (arg == null) {
795 onHelpDataTestMode();
796 return 0;
797 }
798 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800799 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800800 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700801 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800802 } catch (RemoteException ex) {
803 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
804 errPw.println("Exception: " + ex.getMessage());
805 return -1;
806 }
807 break;
808 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800809 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800810 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700811 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800812 } catch (RemoteException ex) {
813 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
814 errPw.println("Exception: " + ex.getMessage());
815 return -1;
816 }
817 break;
818 }
819 default:
820 onHelpDataTestMode();
821 break;
822 }
823 return 0;
824 }
825
Shuo Qianccbaf742021-02-22 18:32:21 -0800826 private int handleEmergencyCallbackModeCommand() {
827 PrintWriter errPw = getErrPrintWriter();
828 try {
829 mInterface.startEmergencyCallbackMode();
830 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
831 } catch (RemoteException ex) {
832 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
833 errPw.println("Exception: " + ex.getMessage());
834 return -1;
835 }
836 return 0;
837 }
838
Grant Menke567d48f2022-08-18 20:19:10 +0000839 private void removeEmergencyNumberTestMode(String emergencyNumber) {
840 PrintWriter errPw = getErrPrintWriter();
841 for (int routingType : ROUTING_TYPES) {
842 try {
843 mInterface.updateEmergencyNumberListTestMode(
844 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
845 new EmergencyNumber(emergencyNumber, "", "",
846 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
847 new ArrayList<String>(),
848 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
849 routingType));
850 } catch (RemoteException ex) {
851 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
852 errPw.println("Exception: " + ex.getMessage());
853 }
854 }
855 }
856
sqian9d4df8b2019-01-15 18:32:07 -0800857 private int handleEmergencyNumberTestModeCommand() {
858 PrintWriter errPw = getErrPrintWriter();
859 String opt = getNextOption();
860 if (opt == null) {
861 onHelpEmergencyNumber();
862 return 0;
863 }
sqian9d4df8b2019-01-15 18:32:07 -0800864 switch (opt) {
865 case "-a": {
866 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000867 if (emergencyNumberCmd == null){
868 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800869 return -1;
870 }
Grant Menke567d48f2022-08-18 20:19:10 +0000871 String[] params = emergencyNumberCmd.split(":");
872 String emergencyNumber;
873 if (params[0] == null ||
874 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
875 errPw.println(INVALID_ENTRY_ERROR);
876 return -1;
877 } else {
878 emergencyNumber = params[0];
879 }
880 removeEmergencyNumberTestMode(emergencyNumber);
881 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
882 if (params.length > 1) {
883 switch (params[1].toLowerCase(Locale.ROOT)) {
884 case "emergency":
885 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
886 break;
887 case "normal":
888 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
889 break;
890 case "unknown":
891 break;
892 default:
893 errPw.println("\"" + params[1] + "\" is not a valid specification for "
894 + "emergency call routing. Please enter either \"normal\", "
895 + "\"unknown\", or \"emergency\" for call routing. "
896 + "(-a 1234:normal)");
897 return -1;
898 }
899 }
sqian9d4df8b2019-01-15 18:32:07 -0800900 try {
901 mInterface.updateEmergencyNumberListTestMode(
902 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000903 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800904 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
905 new ArrayList<String>(),
906 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000907 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800908 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000909 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800910 + ", error " + ex.getMessage());
911 errPw.println("Exception: " + ex.getMessage());
912 return -1;
913 }
914 break;
915 }
916 case "-c": {
917 try {
918 mInterface.updateEmergencyNumberListTestMode(
919 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
920 } catch (RemoteException ex) {
921 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
922 errPw.println("Exception: " + ex.getMessage());
923 return -1;
924 }
925 break;
926 }
927 case "-r": {
928 String emergencyNumberCmd = getNextArgRequired();
929 if (emergencyNumberCmd == null
930 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700931 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800932 + " to be specified after -r in the command ");
933 return -1;
934 }
Grant Menke567d48f2022-08-18 20:19:10 +0000935 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800936 break;
937 }
938 case "-p": {
939 try {
940 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
941 } catch (RemoteException ex) {
942 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
943 errPw.println("Exception: " + ex.getMessage());
944 return -1;
945 }
946 break;
947 }
948 default:
949 onHelpEmergencyNumber();
950 break;
951 }
952 return 0;
953 }
954
Hall Liud892bec2018-11-30 14:51:45 -0800955 private int handleNumberVerificationCommand() {
956 String arg = getNextArg();
957 if (arg == null) {
958 onHelpNumberVerification();
959 return 0;
960 }
961
Hall Liuca5af3a2018-12-04 16:58:23 -0800962 if (!checkShellUid()) {
963 return -1;
964 }
965
Hall Liud892bec2018-11-30 14:51:45 -0800966 switch (arg) {
967 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800968 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
969 return 0;
970 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800971 case NUMBER_VERIFICATION_FAKE_CALL: {
972 boolean val = NumberVerificationManager.getInstance()
973 .checkIncomingCall(getNextArg());
974 getOutPrintWriter().println(val ? "1" : "0");
975 return 0;
976 }
Hall Liud892bec2018-11-30 14:51:45 -0800977 }
978
979 return -1;
980 }
981
Jordan Liu0ccee222021-04-27 11:55:13 -0700982 private boolean subIsEsim(int subId) {
983 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
984 if (info != null) {
985 return info.isEmbedded();
986 }
987 return false;
988 }
989
990 private int handleEnablePhysicalSubscription(boolean enable) {
991 PrintWriter errPw = getErrPrintWriter();
992 int subId = 0;
993 try {
994 subId = Integer.parseInt(getNextArgRequired());
995 } catch (NumberFormatException e) {
996 errPw.println((enable ? "enable" : "disable")
997 + "-physical-subscription requires an integer as a subId.");
998 return -1;
999 }
1000 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1001 // non user build.
1002 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1003 errPw.println("cc: Permission denied.");
1004 return -1;
1005 }
1006 // Verify that the subId represents a physical sub
1007 if (subIsEsim(subId)) {
1008 errPw.println("SubId " + subId + " is not for a physical subscription");
1009 return -1;
1010 }
1011 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1012 + " physical subscription with subId=" + subId);
1013 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1014 return 0;
1015 }
1016
Jack Nudelman644b91a2021-03-12 14:09:48 -08001017 private int handleThermalMitigationCommand() {
1018 String arg = getNextArg();
1019 String packageName = getNextArg();
1020 if (arg == null || packageName == null) {
1021 onHelpThermalMitigation();
1022 return 0;
1023 }
1024
1025 if (!checkShellUid()) {
1026 return -1;
1027 }
1028
1029 switch (arg) {
1030 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1031 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1032 return 0;
1033 }
1034 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1035 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1036 mContext);
1037 return 0;
1038 }
1039 default:
1040 onHelpThermalMitigation();
1041 }
1042
1043 return -1;
1044
1045 }
1046
Tyler Gunn92479152021-01-20 16:30:10 -08001047 private int handleD2dCommand() {
1048 String arg = getNextArg();
1049 if (arg == null) {
1050 onHelpD2D();
1051 return 0;
1052 }
1053
1054 switch (arg) {
1055 case D2D_SEND: {
1056 return handleD2dSendCommand();
1057 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001058 case D2D_TRANSPORT: {
1059 return handleD2dTransportCommand();
1060 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001061 case D2D_SET_DEVICE_SUPPORT: {
1062 return handleD2dDeviceSupportedCommand();
1063 }
Tyler Gunn92479152021-01-20 16:30:10 -08001064 }
1065
1066 return -1;
1067 }
1068
1069 private int handleD2dSendCommand() {
1070 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001071 int messageType = -1;
1072 int messageValue = -1;
1073
Tyler Gunn92479152021-01-20 16:30:10 -08001074 String arg = getNextArg();
1075 if (arg == null) {
1076 onHelpD2D();
1077 return 0;
1078 }
1079 try {
1080 messageType = Integer.parseInt(arg);
1081 } catch (NumberFormatException e) {
1082 errPw.println("message type must be a valid integer");
1083 return -1;
1084 }
1085
1086 arg = getNextArg();
1087 if (arg == null) {
1088 onHelpD2D();
1089 return 0;
1090 }
1091 try {
1092 messageValue = Integer.parseInt(arg);
1093 } catch (NumberFormatException e) {
1094 errPw.println("message value must be a valid integer");
1095 return -1;
1096 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001097
Tyler Gunn92479152021-01-20 16:30:10 -08001098 try {
1099 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1100 } catch (RemoteException e) {
1101 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1102 errPw.println("Exception: " + e.getMessage());
1103 return -1;
1104 }
1105
1106 return 0;
1107 }
1108
Tyler Gunnbabbda02021-02-10 11:05:02 -08001109 private int handleD2dTransportCommand() {
1110 PrintWriter errPw = getErrPrintWriter();
1111
1112 String arg = getNextArg();
1113 if (arg == null) {
1114 onHelpD2D();
1115 return 0;
1116 }
1117
1118 try {
1119 mInterface.setActiveDeviceToDeviceTransport(arg);
1120 } catch (RemoteException e) {
1121 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1122 errPw.println("Exception: " + e.getMessage());
1123 return -1;
1124 }
1125 return 0;
1126 }
Nazanin014f41e2021-05-06 17:26:31 -07001127 private int handleBarringCommand() {
1128 String arg = getNextArg();
1129 if (arg == null) {
1130 onHelpBarring();
1131 return 0;
1132 }
1133
1134 switch (arg) {
1135 case BARRING_SEND_INFO: {
1136 return handleBarringSendCommand();
1137 }
1138 }
1139 return -1;
1140 }
1141
1142 private int handleBarringSendCommand() {
1143 PrintWriter errPw = getErrPrintWriter();
1144 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001145 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001146 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1147 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1148 boolean isConditionallyBarred = false;
1149 int conditionalBarringTimeSeconds = 0;
1150
1151 String opt;
1152 while ((opt = getNextOption()) != null) {
1153 switch (opt) {
1154 case "-s": {
1155 try {
1156 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001157 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001158 } catch (NumberFormatException e) {
1159 errPw.println("barring send requires an integer as a SLOT_ID.");
1160 return -1;
1161 }
1162 break;
1163 }
1164 case "-b": {
1165 try {
1166 barringType = Integer.parseInt(getNextArgRequired());
1167 if (barringType < -1 || barringType > 2) {
1168 throw new NumberFormatException();
1169 }
1170
1171 } catch (NumberFormatException e) {
1172 errPw.println("barring send requires an integer in range [-1,2] as "
1173 + "a BARRING_TYPE.");
1174 return -1;
1175 }
1176 break;
1177 }
1178 case "-c": {
1179 try {
1180 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1181 } catch (Exception e) {
1182 errPw.println("barring send requires a boolean after -c indicating"
1183 + " conditional barring");
1184 return -1;
1185 }
1186 break;
1187 }
1188 case "-t": {
1189 try {
1190 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1191 } catch (NumberFormatException e) {
1192 errPw.println("barring send requires an integer for time of barring"
1193 + " in seconds after -t for conditional barring");
1194 return -1;
1195 }
1196 break;
1197 }
1198 }
1199 }
1200 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1201 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1202 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1203 barringServiceInfos.append(0, bsi);
1204 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1205 try {
1206 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1207 } catch (Exception e) {
1208 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1209 errPw.println("Exception: " + e.getMessage());
1210 return -1;
1211 }
1212 return 0;
1213 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001214
Tyler Gunnd4575212021-05-03 14:46:49 -07001215 private int handleD2dDeviceSupportedCommand() {
1216 PrintWriter errPw = getErrPrintWriter();
1217
1218 String arg = getNextArg();
1219 if (arg == null) {
1220 onHelpD2D();
1221 return 0;
1222 }
1223
Jack Yua533d632022-09-30 13:53:46 -07001224 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001225 try {
1226 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1227 } catch (RemoteException e) {
1228 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1229 errPw.println("Exception: " + e.getMessage());
1230 return -1;
1231 }
1232 return 0;
1233 }
1234
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001235 // ims set-ims-service
1236 private int handleImsSetServiceCommand() {
1237 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001238 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001239 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001240 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001241
1242 String opt;
1243 while ((opt = getNextOption()) != null) {
1244 switch (opt) {
1245 case "-s": {
1246 try {
1247 slotId = Integer.parseInt(getNextArgRequired());
1248 } catch (NumberFormatException e) {
1249 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1250 return -1;
1251 }
1252 break;
1253 }
1254 case "-c": {
1255 isCarrierService = true;
1256 break;
1257 }
1258 case "-d": {
1259 isCarrierService = false;
1260 break;
1261 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001262 case "-f": {
1263 String featureString = getNextArgRequired();
1264 String[] features = featureString.split(",");
1265 for (int i = 0; i < features.length; i++) {
1266 try {
1267 Integer result = Integer.parseInt(features[i]);
1268 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1269 || result >= ImsFeature.FEATURE_MAX) {
1270 errPw.println("ims set-ims-service -f " + result
1271 + " is an invalid feature.");
1272 return -1;
1273 }
1274 featuresList.add(result);
1275 } catch (NumberFormatException e) {
1276 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1277 + " as an integer.");
1278 return -1;
1279 }
1280 }
1281 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001282 }
1283 }
1284 // Mandatory param, either -c or -d
1285 if (isCarrierService == null) {
1286 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1287 return -1;
1288 }
1289
1290 String packageName = getNextArg();
1291
1292 try {
1293 if (packageName == null) {
1294 packageName = "";
1295 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001296 int[] featureArray = new int[featuresList.size()];
1297 for (int i = 0; i < featuresList.size(); i++) {
1298 featureArray[i] = featuresList.get(i);
1299 }
1300 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1301 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001302 if (VDBG) {
1303 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001304 + (isCarrierService ? "-c " : "-d ")
1305 + "-f " + featuresList + " "
1306 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001307 }
1308 getOutPrintWriter().println(result);
1309 } catch (RemoteException e) {
1310 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001311 + (isCarrierService ? "-c " : "-d ")
1312 + "-f " + featuresList + " "
1313 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001314 errPw.println("Exception: " + e.getMessage());
1315 return -1;
1316 }
1317 return 0;
1318 }
1319
Brad Ebinger999d3302020-11-25 14:31:39 -08001320 // ims clear-ims-service-override
1321 private int handleImsClearCarrierServiceCommand() {
1322 PrintWriter errPw = getErrPrintWriter();
1323 int slotId = getDefaultSlot();
1324
1325 String opt;
1326 while ((opt = getNextOption()) != null) {
1327 switch (opt) {
1328 case "-s": {
1329 try {
1330 slotId = Integer.parseInt(getNextArgRequired());
1331 } catch (NumberFormatException e) {
1332 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1333 return -1;
1334 }
1335 break;
1336 }
1337 }
1338 }
1339
1340 try {
1341 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1342 if (VDBG) {
1343 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1344 + ", result=" + result);
1345 }
1346 getOutPrintWriter().println(result);
1347 } catch (RemoteException e) {
1348 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1349 + ", error" + e.getMessage());
1350 errPw.println("Exception: " + e.getMessage());
1351 return -1;
1352 }
1353 return 0;
1354 }
1355
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001356 // ims get-ims-service
1357 private int handleImsGetServiceCommand() {
1358 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001359 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001360 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001361 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001362
1363 String opt;
1364 while ((opt = getNextOption()) != null) {
1365 switch (opt) {
1366 case "-s": {
1367 try {
1368 slotId = Integer.parseInt(getNextArgRequired());
1369 } catch (NumberFormatException e) {
1370 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1371 return -1;
1372 }
1373 break;
1374 }
1375 case "-c": {
1376 isCarrierService = true;
1377 break;
1378 }
1379 case "-d": {
1380 isCarrierService = false;
1381 break;
1382 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001383 case "-f": {
1384 try {
1385 featureType = Integer.parseInt(getNextArg());
1386 } catch (NumberFormatException e) {
1387 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1388 return -1;
1389 }
1390 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1391 || featureType >= ImsFeature.FEATURE_MAX) {
1392 errPw.println("ims get-ims-service -f invalid feature.");
1393 return -1;
1394 }
1395 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001396 }
1397 }
1398 // Mandatory param, either -c or -d
1399 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001400 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001401 return -1;
1402 }
1403
1404 String result;
1405 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001406 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001407 } catch (RemoteException e) {
1408 return -1;
1409 }
1410 if (VDBG) {
1411 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001412 + (isCarrierService ? "-c " : "-d ")
1413 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1414 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001415 }
1416 getOutPrintWriter().println(result);
1417 return 0;
1418 }
1419
1420 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001421 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001422 String opt;
1423 while ((opt = getNextOption()) != null) {
1424 switch (opt) {
1425 case "-s": {
1426 try {
1427 slotId = Integer.parseInt(getNextArgRequired());
1428 } catch (NumberFormatException e) {
1429 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1430 return -1;
1431 }
1432 break;
1433 }
1434 }
1435 }
1436 try {
1437 mInterface.enableIms(slotId);
1438 } catch (RemoteException e) {
1439 return -1;
1440 }
1441 if (VDBG) {
1442 Log.v(LOG_TAG, "ims enable -s " + slotId);
1443 }
1444 return 0;
1445 }
1446
1447 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001448 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001449 String opt;
1450 while ((opt = getNextOption()) != null) {
1451 switch (opt) {
1452 case "-s": {
1453 try {
1454 slotId = Integer.parseInt(getNextArgRequired());
1455 } catch (NumberFormatException e) {
1456 getErrPrintWriter().println(
1457 "ims disable requires an integer as a SLOT_ID.");
1458 return -1;
1459 }
1460 break;
1461 }
1462 }
1463 }
1464 try {
1465 mInterface.disableIms(slotId);
1466 } catch (RemoteException e) {
1467 return -1;
1468 }
1469 if (VDBG) {
1470 Log.v(LOG_TAG, "ims disable -s " + slotId);
1471 }
1472 return 0;
1473 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001474
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001475 private int handleCepChange() {
1476 Log.i(LOG_TAG, "handleCepChange");
1477 String opt = getNextArg();
1478 if (opt == null) {
1479 return -1;
1480 }
1481 boolean isCepEnabled = opt.equals("enable");
1482
1483 try {
1484 mInterface.setCepEnabled(isCepEnabled);
1485 } catch (RemoteException e) {
1486 return -1;
1487 }
1488 return 0;
1489 }
1490
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001491 private int getDefaultSlot() {
1492 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1493 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1494 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1495 // If there is no default, default to slot 0.
1496 slotId = DEFAULT_PHONE_ID;
1497 }
1498 return slotId;
1499 }
sqian2fff4a32018-11-05 14:18:37 -08001500
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001501 // Parse options related to Carrier Config Commands.
1502 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001503 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001504 CcOptionParseResult result = new CcOptionParseResult();
1505 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1506 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001507
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001508 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001509 while ((opt = getNextOption()) != null) {
1510 switch (opt) {
1511 case "-s": {
1512 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001513 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1514 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1515 errPw.println(tag + "No valid subscription found.");
1516 return null;
1517 }
1518
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001519 } catch (IllegalArgumentException e) {
1520 // Missing slot id
1521 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001522 return null;
1523 }
1524 break;
1525 }
1526 case "-p": {
1527 if (allowOptionPersistent) {
1528 result.mPersistent = true;
1529 } else {
1530 errPw.println(tag + "Unexpected option " + opt);
1531 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001532 }
1533 break;
1534 }
1535 default: {
1536 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001537 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001538 }
1539 }
1540 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001541 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001542 }
1543
1544 private int slotStringToSubId(String tag, String slotString) {
1545 int slotId = -1;
1546 try {
1547 slotId = Integer.parseInt(slotString);
1548 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001549 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1550 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1551 }
1552
1553 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001554 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1555 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1556 }
1557
Qiong Liuf25799b2020-09-10 10:13:46 +08001558 Phone phone = PhoneFactory.getPhone(slotId);
1559 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001560 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1561 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1562 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001563 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001564 }
1565
Hall Liud892bec2018-11-30 14:51:45 -08001566 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001567 // adb can run as root or as shell, depending on whether the device is rooted.
1568 return Binder.getCallingUid() == Process.SHELL_UID
1569 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001570 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001571
1572 private int handleCcCommand() {
1573 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1574 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001575 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001576 getErrPrintWriter().println("cc: Permission denied.");
1577 return -1;
1578 }
1579
1580 String arg = getNextArg();
1581 if (arg == null) {
1582 onHelpCc();
1583 return 0;
1584 }
1585
1586 switch (arg) {
1587 case CC_GET_VALUE: {
1588 return handleCcGetValue();
1589 }
1590 case CC_SET_VALUE: {
1591 return handleCcSetValue();
1592 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001593 case CC_SET_VALUES_FROM_XML: {
1594 return handleCcSetValuesFromXml();
1595 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001596 case CC_CLEAR_VALUES: {
1597 return handleCcClearValues();
1598 }
1599 default: {
1600 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1601 }
1602 }
1603 return -1;
1604 }
1605
1606 // cc get-value
1607 private int handleCcGetValue() {
1608 PrintWriter errPw = getErrPrintWriter();
1609 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1610 String key = null;
1611
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001612 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001613 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001614 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001615 return -1;
1616 }
1617
1618 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001619 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001620 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001621 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001622 return -1;
1623 }
1624
1625 // Get the key.
1626 key = getNextArg();
1627 if (key != null) {
1628 // A key was provided. Verify if it is a valid key
1629 if (!bundle.containsKey(key)) {
1630 errPw.println(tag + key + " is not a valid key.");
1631 return -1;
1632 }
1633
1634 // Print the carrier config value for key.
1635 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1636 } else {
1637 // No key provided. Show all values.
1638 // Iterate over a sorted list of all carrier config keys and print them.
1639 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1640 for (String k : sortedSet) {
1641 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1642 }
1643 }
1644 return 0;
1645 }
1646
1647 // cc set-value
1648 private int handleCcSetValue() {
1649 PrintWriter errPw = getErrPrintWriter();
1650 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1651
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001652 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001653 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001654 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001655 return -1;
1656 }
1657
1658 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001659 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001660 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001661 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001662 return -1;
1663 }
1664
1665 // Get the key.
1666 String key = getNextArg();
1667 if (key == null || key.equals("")) {
1668 errPw.println(tag + "KEY is missing");
1669 return -1;
1670 }
1671
1672 // Verify if the key is valid
1673 if (!originalValues.containsKey(key)) {
1674 errPw.println(tag + key + " is not a valid key.");
1675 return -1;
1676 }
1677
1678 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1679 ArrayList<String> valueList = new ArrayList<String>();
1680 while (peekNextArg() != null) {
1681 valueList.add(getNextArg());
1682 }
1683
1684 // Find the type of the carrier config value
1685 CcType type = getType(tag, key, originalValues);
1686 if (type == CcType.UNKNOWN) {
1687 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1688 return -1;
1689 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001690 if (type == CcType.PERSISTABLE_BUNDLE) {
1691 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1692 + "Use set-values-from-xml instead.");
1693 return -1;
1694 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001695
1696 // Create an override bundle containing the key and value that should be overriden.
1697 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1698 if (overrideBundle == null) {
1699 return -1;
1700 }
1701
1702 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001703 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001704
1705 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001706 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001707 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001708 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001709 return -1;
1710 }
1711
1712 // Print the original and new value.
1713 String originalValueString = ccValueToString(key, type, originalValues);
1714 String newValueString = ccValueToString(key, type, newValues);
1715 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1716 getOutPrintWriter().println("New value: \n" + newValueString);
1717
1718 return 0;
1719 }
1720
Allen Xuee00f0e2022-03-14 21:04:49 +00001721 // cc set-values-from-xml
1722 private int handleCcSetValuesFromXml() {
1723 PrintWriter errPw = getErrPrintWriter();
1724 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1725
1726 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001727 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001728 if (options == null) {
1729 return -1;
1730 }
1731
1732 // Get bundle containing all current carrier configuration values.
1733 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1734 if (originalValues == null) {
1735 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1736 return -1;
1737 }
1738
1739 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1740 if (overrideBundle == null) {
1741 return -1;
1742 }
1743
1744 // Verify all values are valid types
1745 for (String key : overrideBundle.keySet()) {
1746 CcType type = getType(tag, key, originalValues);
1747 if (type == CcType.UNKNOWN) {
1748 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1749 return -1;
1750 }
1751 }
1752
1753 // Override the value
1754 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1755
1756 // Find bundle containing all new carrier configuration values after the override.
1757 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1758 if (newValues == null) {
1759 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1760 return -1;
1761 }
1762
1763 // Print the original and new values
1764 overrideBundle.keySet().forEach(key -> {
1765 CcType type = getType(tag, key, originalValues);
1766 String originalValueString = ccValueToString(key, type, originalValues);
1767 String newValueString = ccValueToString(key, type, newValues);
1768 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1769 getOutPrintWriter().println("New value: \n" + newValueString);
1770 });
1771
1772 return 0;
1773 }
1774
1775 private PersistableBundle readPersistableBundleFromXml(String tag) {
1776 PersistableBundle subIdBundles;
1777 try {
1778 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1779 } catch (IOException | RuntimeException e) {
1780 PrintWriter errPw = getErrPrintWriter();
1781 errPw.println(tag + e);
1782 return null;
1783 }
1784
1785 return subIdBundles;
1786 }
1787
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001788 // cc clear-values
1789 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001790 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1791
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001792 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001793 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001794 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001795 return -1;
1796 }
1797
1798 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001799 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001800 getOutPrintWriter()
1801 .println("All previously set carrier config override values has been cleared");
1802 return 0;
1803 }
1804
1805 private CcType getType(String tag, String key, PersistableBundle bundle) {
1806 // Find the type by checking the type of the current value stored in the bundle.
1807 Object value = bundle.get(key);
1808
1809 if (CC_TYPE_MAP.containsKey(key)) {
1810 return CC_TYPE_MAP.get(key);
1811 } else if (value != null) {
1812 if (value instanceof Boolean) {
1813 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001814 }
1815 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001816 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001817 }
1818 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001819 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001820 }
1821 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001822 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001823 }
1824 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001825 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001826 }
1827 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001828 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001829 }
1830 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001831 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001832 }
1833 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001834 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001835 }
1836 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001837 return CcType.STRING_ARRAY;
1838 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001839 if (value instanceof PersistableBundle) {
1840 return CcType.PERSISTABLE_BUNDLE;
1841 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001842 } else {
1843 // Current value was null and can therefore not be used in order to find the type.
1844 // Check the name of the key to infer the type. This check is not needed for primitive
1845 // data types (boolean, double, int and long), since they can not be null.
1846 if (key.endsWith("double_array")) {
1847 return CcType.DOUBLE_ARRAY;
1848 }
1849 if (key.endsWith("int_array")) {
1850 return CcType.INT_ARRAY;
1851 }
1852 if (key.endsWith("long_array")) {
1853 return CcType.LONG_ARRAY;
1854 }
1855 if (key.endsWith("string")) {
1856 return CcType.STRING;
1857 }
1858 if (key.endsWith("string_array") || key.endsWith("strings")) {
1859 return CcType.STRING_ARRAY;
1860 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001861 if (key.endsWith("bundle")) {
1862 return CcType.PERSISTABLE_BUNDLE;
1863 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001864 }
1865
1866 // Not possible to infer the type by looking at the current value or the key.
1867 PrintWriter errPw = getErrPrintWriter();
1868 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1869 return CcType.UNKNOWN;
1870 }
1871
1872 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1873 String result;
1874 StringBuilder valueString = new StringBuilder();
1875 String typeString = type.toString();
1876 Object value = bundle.get(key);
1877
1878 if (value == null) {
1879 valueString.append("null");
1880 } else {
1881 switch (type) {
1882 case DOUBLE_ARRAY: {
1883 // Format the string representation of the int array as value1 value2......
1884 double[] valueArray = (double[]) value;
1885 for (int i = 0; i < valueArray.length; i++) {
1886 if (i != 0) {
1887 valueString.append(" ");
1888 }
1889 valueString.append(valueArray[i]);
1890 }
1891 break;
1892 }
1893 case INT_ARRAY: {
1894 // Format the string representation of the int array as value1 value2......
1895 int[] valueArray = (int[]) value;
1896 for (int i = 0; i < valueArray.length; i++) {
1897 if (i != 0) {
1898 valueString.append(" ");
1899 }
1900 valueString.append(valueArray[i]);
1901 }
1902 break;
1903 }
1904 case LONG_ARRAY: {
1905 // Format the string representation of the int array as value1 value2......
1906 long[] valueArray = (long[]) value;
1907 for (int i = 0; i < valueArray.length; i++) {
1908 if (i != 0) {
1909 valueString.append(" ");
1910 }
1911 valueString.append(valueArray[i]);
1912 }
1913 break;
1914 }
1915 case STRING: {
1916 valueString.append("\"" + value.toString() + "\"");
1917 break;
1918 }
1919 case STRING_ARRAY: {
1920 // Format the string representation of the string array as "value1" "value2"....
1921 String[] valueArray = (String[]) value;
1922 for (int i = 0; i < valueArray.length; i++) {
1923 if (i != 0) {
1924 valueString.append(" ");
1925 }
1926 if (valueArray[i] != null) {
1927 valueString.append("\"" + valueArray[i] + "\"");
1928 } else {
1929 valueString.append("null");
1930 }
1931 }
1932 break;
1933 }
1934 default: {
1935 valueString.append(value.toString());
1936 }
1937 }
1938 }
1939 return String.format("%-70s %-15s %s", key, typeString, valueString);
1940 }
1941
1942 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1943 ArrayList<String> valueList) {
1944 PrintWriter errPw = getErrPrintWriter();
1945 PersistableBundle bundle = new PersistableBundle();
1946
1947 // First verify that a valid number of values has been provided for the type.
1948 switch (type) {
1949 case BOOLEAN:
1950 case DOUBLE:
1951 case INT:
1952 case LONG: {
1953 if (valueList.size() != 1) {
1954 errPw.println(tag + "Expected 1 value for type " + type
1955 + ". Found: " + valueList.size());
1956 return null;
1957 }
1958 break;
1959 }
1960 case STRING: {
1961 if (valueList.size() > 1) {
1962 errPw.println(tag + "Expected 0 or 1 values for type " + type
1963 + ". Found: " + valueList.size());
1964 return null;
1965 }
1966 break;
1967 }
1968 }
1969
1970 // Parse the value according to type and add it to the Bundle.
1971 switch (type) {
1972 case BOOLEAN: {
1973 if ("true".equalsIgnoreCase(valueList.get(0))) {
1974 bundle.putBoolean(key, true);
1975 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1976 bundle.putBoolean(key, false);
1977 } else {
1978 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1979 return null;
1980 }
1981 break;
1982 }
1983 case DOUBLE: {
1984 try {
1985 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1986 } catch (NumberFormatException nfe) {
1987 // Not a valid double
1988 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1989 return null;
1990 }
1991 break;
1992 }
1993 case DOUBLE_ARRAY: {
1994 double[] valueDoubleArray = null;
1995 if (valueList.size() > 0) {
1996 valueDoubleArray = new double[valueList.size()];
1997 for (int i = 0; i < valueList.size(); i++) {
1998 try {
1999 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2000 } catch (NumberFormatException nfe) {
2001 // Not a valid double
2002 errPw.println(
2003 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2004 return null;
2005 }
2006 }
2007 }
2008 bundle.putDoubleArray(key, valueDoubleArray);
2009 break;
2010 }
2011 case INT: {
2012 try {
2013 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2014 } catch (NumberFormatException nfe) {
2015 // Not a valid integer
2016 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2017 return null;
2018 }
2019 break;
2020 }
2021 case INT_ARRAY: {
2022 int[] valueIntArray = null;
2023 if (valueList.size() > 0) {
2024 valueIntArray = new int[valueList.size()];
2025 for (int i = 0; i < valueList.size(); i++) {
2026 try {
2027 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2028 } catch (NumberFormatException nfe) {
2029 // Not a valid integer
2030 errPw.println(tag
2031 + "Unable to parse " + valueList.get(i) + " as an integer.");
2032 return null;
2033 }
2034 }
2035 }
2036 bundle.putIntArray(key, valueIntArray);
2037 break;
2038 }
2039 case LONG: {
2040 try {
2041 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2042 } catch (NumberFormatException nfe) {
2043 // Not a valid long
2044 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2045 return null;
2046 }
2047 break;
2048 }
2049 case LONG_ARRAY: {
2050 long[] valueLongArray = null;
2051 if (valueList.size() > 0) {
2052 valueLongArray = new long[valueList.size()];
2053 for (int i = 0; i < valueList.size(); i++) {
2054 try {
2055 valueLongArray[i] = Long.parseLong(valueList.get(i));
2056 } catch (NumberFormatException nfe) {
2057 // Not a valid long
2058 errPw.println(
2059 tag + "Unable to parse " + valueList.get(i) + " as a long");
2060 return null;
2061 }
2062 }
2063 }
2064 bundle.putLongArray(key, valueLongArray);
2065 break;
2066 }
2067 case STRING: {
2068 String value = null;
2069 if (valueList.size() > 0) {
2070 value = valueList.get(0);
2071 }
2072 bundle.putString(key, value);
2073 break;
2074 }
2075 case STRING_ARRAY: {
2076 String[] valueStringArray = null;
2077 if (valueList.size() > 0) {
2078 valueStringArray = new String[valueList.size()];
2079 valueList.toArray(valueStringArray);
2080 }
2081 bundle.putStringArray(key, valueStringArray);
2082 break;
2083 }
2084 }
2085 return bundle;
2086 }
Shuo Qian489d9282020-07-09 11:30:03 -07002087
2088 private int handleEndBlockSuppressionCommand() {
2089 if (!checkShellUid()) {
2090 return -1;
2091 }
2092
2093 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2094 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2095 }
2096 return 0;
2097 }
Hui Wang641e81c2020-10-12 12:14:23 -07002098
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002099 private int handleEuiccCommand() {
2100 String arg = getNextArg();
2101 if (arg == null) {
2102 onHelpEuicc();
2103 return 0;
2104 }
2105
2106 switch (arg) {
2107 case EUICC_SET_UI_COMPONENT: {
2108 return handleEuiccServiceCommand();
2109 }
2110 }
2111 return -1;
2112 }
2113
2114 private int handleEuiccServiceCommand() {
2115 String uiComponent = getNextArg();
2116 String packageName = getNextArg();
2117 if (packageName == null || uiComponent == null) {
2118 return -1;
2119 }
2120 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2121 if (VDBG) {
2122 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2123 + packageName);
2124 }
2125 return 0;
2126 }
2127
Michele Berionne54af4632020-12-28 20:23:16 +00002128 private int handleRestartModemCommand() {
2129 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2130 // non user build.
2131 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2132 getErrPrintWriter().println("RestartModem: Permission denied.");
2133 return -1;
2134 }
2135
2136 boolean result = TelephonyManager.getDefault().rebootRadio();
2137 getOutPrintWriter().println(result);
2138
2139 return result ? 0 : -1;
2140 }
2141
Ling Ma4fbab492022-01-25 22:36:16 +00002142 private int handleGetImei() {
2143 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2144 // non user build.
2145 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2146 getErrPrintWriter().println("Device IMEI: Permission denied.");
2147 return -1;
2148 }
2149
2150 final long identity = Binder.clearCallingIdentity();
2151
2152 String imei = null;
2153 String arg = getNextArg();
2154 if (arg != null) {
2155 try {
2156 int specifiedSlotIndex = Integer.parseInt(arg);
2157 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2158 } catch (NumberFormatException exception) {
2159 PrintWriter errPw = getErrPrintWriter();
2160 errPw.println("-s requires an integer as slot index.");
2161 return -1;
2162 }
2163
2164 } else {
2165 imei = TelephonyManager.from(mContext).getImei();
2166 }
2167 getOutPrintWriter().println("Device IMEI: " + imei);
2168
2169 Binder.restoreCallingIdentity(identity);
2170 return 0;
2171 }
2172
Michele Berionne5e411512020-11-13 02:36:59 +00002173 private int handleUnattendedReboot() {
2174 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2175 // non user build.
2176 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2177 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2178 return -1;
2179 }
2180
2181 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2182 getOutPrintWriter().println("result: " + result);
2183
2184 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2185 }
2186
Aman Gupta07124872022-02-09 08:02:14 +00002187 private int handleGetSimSlotsMapping() {
2188 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2189 // non user build.
2190 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2191 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2192 return -1;
2193 }
2194 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2195 String result = telephonyManager.getSimSlotMapping().toString();
2196 getOutPrintWriter().println("simSlotsMapping: " + result);
2197
2198 return 0;
2199 }
2200
Hui Wang641e81c2020-10-12 12:14:23 -07002201 private int handleGbaCommand() {
2202 String arg = getNextArg();
2203 if (arg == null) {
2204 onHelpGba();
2205 return 0;
2206 }
2207
2208 switch (arg) {
2209 case GBA_SET_SERVICE: {
2210 return handleGbaSetServiceCommand();
2211 }
2212 case GBA_GET_SERVICE: {
2213 return handleGbaGetServiceCommand();
2214 }
2215 case GBA_SET_RELEASE_TIME: {
2216 return handleGbaSetReleaseCommand();
2217 }
2218 case GBA_GET_RELEASE_TIME: {
2219 return handleGbaGetReleaseCommand();
2220 }
2221 }
2222
2223 return -1;
2224 }
2225
2226 private int getSubId(String cmd) {
2227 int slotId = getDefaultSlot();
2228 String opt = getNextOption();
2229 if (opt != null && opt.equals("-s")) {
2230 try {
2231 slotId = Integer.parseInt(getNextArgRequired());
2232 } catch (NumberFormatException e) {
2233 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2234 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2235 }
2236 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002237 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002238 }
2239
2240 private int handleGbaSetServiceCommand() {
2241 int subId = getSubId("gba set-service");
2242 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2243 return -1;
2244 }
2245
2246 String packageName = getNextArg();
2247 try {
2248 if (packageName == null) {
2249 packageName = "";
2250 }
2251 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2252 if (VDBG) {
2253 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2254 + packageName + ", result=" + result);
2255 }
2256 getOutPrintWriter().println(result);
2257 } catch (RemoteException e) {
2258 Log.w(LOG_TAG, "gba set-service " + subId + " "
2259 + packageName + ", error" + e.getMessage());
2260 getErrPrintWriter().println("Exception: " + e.getMessage());
2261 return -1;
2262 }
2263 return 0;
2264 }
2265
2266 private int handleGbaGetServiceCommand() {
2267 String result;
2268
2269 int subId = getSubId("gba get-service");
2270 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2271 return -1;
2272 }
2273
2274 try {
2275 result = mInterface.getBoundGbaService(subId);
2276 } catch (RemoteException e) {
2277 return -1;
2278 }
2279 if (VDBG) {
2280 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2281 }
2282 getOutPrintWriter().println(result);
2283 return 0;
2284 }
2285
2286 private int handleGbaSetReleaseCommand() {
2287 //the release time value could be -1
2288 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2289 : SubscriptionManager.getDefaultSubscriptionId();
2290 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2291 return -1;
2292 }
2293
2294 String intervalStr = getNextArg();
2295 if (intervalStr == null) {
2296 return -1;
2297 }
2298
2299 try {
2300 int interval = Integer.parseInt(intervalStr);
2301 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2302 if (VDBG) {
2303 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2304 + intervalStr + ", result=" + result);
2305 }
2306 getOutPrintWriter().println(result);
2307 } catch (NumberFormatException | RemoteException e) {
2308 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2309 + intervalStr + ", error" + e.getMessage());
2310 getErrPrintWriter().println("Exception: " + e.getMessage());
2311 return -1;
2312 }
2313 return 0;
2314 }
2315
2316 private int handleGbaGetReleaseCommand() {
2317 int subId = getSubId("gba get-release");
2318 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2319 return -1;
2320 }
2321
2322 int result = 0;
2323 try {
2324 result = mInterface.getGbaReleaseTime(subId);
2325 } catch (RemoteException e) {
2326 return -1;
2327 }
2328 if (VDBG) {
2329 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2330 }
2331 getOutPrintWriter().println(result);
2332 return 0;
2333 }
Hui Wang761a6682020-10-31 05:12:53 +00002334
2335 private int handleSingleRegistrationConfigCommand() {
2336 String arg = getNextArg();
2337 if (arg == null) {
2338 onHelpSrc();
2339 return 0;
2340 }
2341
2342 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002343 case SRC_SET_TEST_ENABLED: {
2344 return handleSrcSetTestEnabledCommand();
2345 }
2346 case SRC_GET_TEST_ENABLED: {
2347 return handleSrcGetTestEnabledCommand();
2348 }
Hui Wang761a6682020-10-31 05:12:53 +00002349 case SRC_SET_DEVICE_ENABLED: {
2350 return handleSrcSetDeviceEnabledCommand();
2351 }
2352 case SRC_GET_DEVICE_ENABLED: {
2353 return handleSrcGetDeviceEnabledCommand();
2354 }
2355 case SRC_SET_CARRIER_ENABLED: {
2356 return handleSrcSetCarrierEnabledCommand();
2357 }
2358 case SRC_GET_CARRIER_ENABLED: {
2359 return handleSrcGetCarrierEnabledCommand();
2360 }
Hui Wangb647abe2021-02-26 09:33:38 -08002361 case SRC_SET_FEATURE_ENABLED: {
2362 return handleSrcSetFeatureValidationCommand();
2363 }
2364 case SRC_GET_FEATURE_ENABLED: {
2365 return handleSrcGetFeatureValidationCommand();
2366 }
Hui Wang761a6682020-10-31 05:12:53 +00002367 }
2368
2369 return -1;
2370 }
2371
James.cf Linbcdf8b32021-01-14 16:44:13 +08002372 private int handleRcsUceCommand() {
2373 String arg = getNextArg();
2374 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002375 onHelpUce();
2376 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002377 }
2378
2379 switch (arg) {
2380 case UCE_REMOVE_EAB_CONTACT:
2381 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002382 case UCE_GET_EAB_CONTACT:
2383 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002384 case UCE_GET_EAB_CAPABILITY:
2385 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002386 case UCE_GET_DEVICE_ENABLED:
2387 return handleUceGetDeviceEnabledCommand();
2388 case UCE_SET_DEVICE_ENABLED:
2389 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002390 case UCE_OVERRIDE_PUBLISH_CAPS:
2391 return handleUceOverridePublishCaps();
2392 case UCE_GET_LAST_PIDF_XML:
2393 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002394 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2395 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002396 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2397 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002398 }
2399 return -1;
2400 }
2401
2402 private int handleRemovingEabContactCommand() {
2403 int subId = getSubId("uce remove-eab-contact");
2404 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2405 return -1;
2406 }
2407
2408 String phoneNumber = getNextArgRequired();
2409 if (TextUtils.isEmpty(phoneNumber)) {
2410 return -1;
2411 }
2412 int result = 0;
2413 try {
2414 result = mInterface.removeContactFromEab(subId, phoneNumber);
2415 } catch (RemoteException e) {
2416 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2417 getErrPrintWriter().println("Exception: " + e.getMessage());
2418 return -1;
2419 }
2420
2421 if (VDBG) {
2422 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2423 }
calvinpan293ea1b2021-02-04 17:52:13 +08002424 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002425 }
2426
calvinpane4a8a1d2021-01-25 13:51:18 +08002427 private int handleGettingEabContactCommand() {
2428 String phoneNumber = getNextArgRequired();
2429 if (TextUtils.isEmpty(phoneNumber)) {
2430 return -1;
2431 }
2432 String result = "";
2433 try {
2434 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002435 } catch (RemoteException e) {
2436 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2437 getErrPrintWriter().println("Exception: " + e.getMessage());
2438 return -1;
2439 }
2440
2441 if (VDBG) {
2442 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2443 }
calvinpan293ea1b2021-02-04 17:52:13 +08002444 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002445 return 0;
2446 }
2447
Calvin Pana1434322021-07-01 19:27:01 +08002448 private int handleGettingEabCapabilityCommand() {
2449 String phoneNumber = getNextArgRequired();
2450 if (TextUtils.isEmpty(phoneNumber)) {
2451 return -1;
2452 }
2453 String result = "";
2454 try {
2455 result = mInterface.getCapabilityFromEab(phoneNumber);
2456 } catch (RemoteException e) {
2457 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2458 getErrPrintWriter().println("Exception: " + e.getMessage());
2459 return -1;
2460 }
2461
2462 if (VDBG) {
2463 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2464 }
2465 getOutPrintWriter().println(result);
2466 return 0;
2467 }
2468
James.cf Lin4b784aa2021-01-31 03:25:15 +08002469 private int handleUceGetDeviceEnabledCommand() {
2470 boolean result = false;
2471 try {
2472 result = mInterface.getDeviceUceEnabled();
2473 } catch (RemoteException e) {
2474 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2475 return -1;
2476 }
2477 if (VDBG) {
2478 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2479 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002480 getOutPrintWriter().println(result);
2481 return 0;
2482 }
2483
James.cf Lin4b784aa2021-01-31 03:25:15 +08002484 private int handleUceSetDeviceEnabledCommand() {
2485 String enabledStr = getNextArg();
2486 if (TextUtils.isEmpty(enabledStr)) {
2487 return -1;
2488 }
2489
2490 try {
2491 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2492 mInterface.setDeviceUceEnabled(isEnabled);
2493 if (VDBG) {
2494 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2495 }
2496 } catch (NumberFormatException | RemoteException e) {
2497 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2498 getErrPrintWriter().println("Exception: " + e.getMessage());
2499 return -1;
2500 }
2501 return 0;
2502 }
2503
James.cf Line8713a42021-04-29 16:04:26 +08002504 private int handleUceRemoveRequestDisallowedStatus() {
2505 int subId = getSubId("uce remove-request-disallowed-status");
2506 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2507 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2508 return -1;
2509 }
2510 boolean result;
2511 try {
2512 result = mInterface.removeUceRequestDisallowedStatus(subId);
2513 } catch (RemoteException e) {
2514 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2515 return -1;
2516 }
2517 if (VDBG) {
2518 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2519 }
2520 getOutPrintWriter().println(result);
2521 return 0;
2522 }
2523
James.cf Lin0fc71b02021-05-25 01:37:38 +08002524 private int handleUceSetCapRequestTimeout() {
2525 int subId = getSubId("uce set-capabilities-request-timeout");
2526 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2527 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2528 return -1;
2529 }
2530 long timeoutAfterMs = Long.valueOf(getNextArg());
2531 boolean result;
2532 try {
2533 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2534 } catch (RemoteException e) {
2535 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2536 return -1;
2537 }
2538 if (VDBG) {
2539 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2540 }
2541 getOutPrintWriter().println(result);
2542 return 0;
2543 }
2544
Hui Wangbaaee6a2021-02-19 20:45:36 -08002545 private int handleSrcSetTestEnabledCommand() {
2546 String enabledStr = getNextArg();
2547 if (enabledStr == null) {
2548 return -1;
2549 }
2550
2551 try {
2552 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2553 if (VDBG) {
2554 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2555 }
2556 getOutPrintWriter().println("Done");
2557 } catch (NumberFormatException | RemoteException e) {
2558 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2559 getErrPrintWriter().println("Exception: " + e.getMessage());
2560 return -1;
2561 }
2562 return 0;
2563 }
2564
2565 private int handleSrcGetTestEnabledCommand() {
2566 boolean result = false;
2567 try {
2568 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2569 } catch (RemoteException e) {
2570 return -1;
2571 }
2572 if (VDBG) {
2573 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2574 }
2575 getOutPrintWriter().println(result);
2576 return 0;
2577 }
2578
Brad Ebinger14d467f2021-02-12 06:18:28 +00002579 private int handleUceOverridePublishCaps() {
2580 int subId = getSubId("uce override-published-caps");
2581 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2582 return -1;
2583 }
2584 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2585 String operation = getNextArgRequired();
2586 String caps = getNextArg();
2587 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2588 && !"list".equals(operation)) {
2589 getErrPrintWriter().println("Invalid operation: " + operation);
2590 return -1;
2591 }
2592
2593 // add/remove requires capabilities to be specified.
2594 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2595 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2596 + "specified");
2597 return -1;
2598 }
2599
2600 ArraySet<String> capSet = new ArraySet<>();
2601 if (!TextUtils.isEmpty(caps)) {
2602 String[] capArray = caps.split(":");
2603 for (String cap : capArray) {
2604 // Allow unknown tags to be passed in as well.
2605 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2606 }
2607 }
2608
2609 RcsContactUceCapability result = null;
2610 try {
2611 switch (operation) {
2612 case "add":
2613 result = mInterface.addUceRegistrationOverrideShell(subId,
2614 new ArrayList<>(capSet));
2615 break;
2616 case "remove":
2617 result = mInterface.removeUceRegistrationOverrideShell(subId,
2618 new ArrayList<>(capSet));
2619 break;
2620 case "clear":
2621 result = mInterface.clearUceRegistrationOverrideShell(subId);
2622 break;
2623 case "list":
2624 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2625 break;
2626 }
2627 } catch (RemoteException e) {
2628 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2629 getErrPrintWriter().println("Exception: " + e.getMessage());
2630 return -1;
2631 } catch (ServiceSpecificException sse) {
2632 // Reconstruct ImsException
2633 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2634 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2635 getErrPrintWriter().println("Exception: " + imsException);
2636 return -1;
2637 }
2638 if (result == null) {
2639 getErrPrintWriter().println("Service not available");
2640 return -1;
2641 }
2642 getOutPrintWriter().println(result);
2643 return 0;
2644 }
2645
2646 private int handleUceGetPidfXml() {
2647 int subId = getSubId("uce get-last-publish-pidf");
2648 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2649 return -1;
2650 }
2651
2652 String result;
2653 try {
2654 result = mInterface.getLastUcePidfXmlShell(subId);
2655 } catch (RemoteException e) {
2656 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2657 getErrPrintWriter().println("Exception: " + e.getMessage());
2658 return -1;
2659 } catch (ServiceSpecificException sse) {
2660 // Reconstruct ImsException
2661 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2662 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2663 getErrPrintWriter().println("Exception: " + imsException);
2664 return -1;
2665 }
2666 if (result == null) {
2667 getErrPrintWriter().println("Service not available");
2668 return -1;
2669 }
2670 getOutPrintWriter().println(result);
2671 return 0;
2672 }
2673
Hui Wang761a6682020-10-31 05:12:53 +00002674 private int handleSrcSetDeviceEnabledCommand() {
2675 String enabledStr = getNextArg();
2676 if (enabledStr == null) {
2677 return -1;
2678 }
2679
2680 try {
2681 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2682 if (VDBG) {
2683 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2684 }
2685 getOutPrintWriter().println("Done");
2686 } catch (NumberFormatException | RemoteException e) {
2687 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2688 getErrPrintWriter().println("Exception: " + e.getMessage());
2689 return -1;
2690 }
2691 return 0;
2692 }
2693
2694 private int handleSrcGetDeviceEnabledCommand() {
2695 boolean result = false;
2696 try {
2697 result = mInterface.getDeviceSingleRegistrationEnabled();
2698 } catch (RemoteException e) {
2699 return -1;
2700 }
2701 if (VDBG) {
2702 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2703 }
2704 getOutPrintWriter().println(result);
2705 return 0;
2706 }
2707
2708 private int handleSrcSetCarrierEnabledCommand() {
2709 //the release time value could be -1
2710 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2711 : SubscriptionManager.getDefaultSubscriptionId();
2712 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2713 return -1;
2714 }
2715
2716 String enabledStr = getNextArg();
2717 if (enabledStr == null) {
2718 return -1;
2719 }
2720
2721 try {
2722 boolean result =
2723 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2724 if (VDBG) {
2725 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2726 + enabledStr + ", result=" + result);
2727 }
2728 getOutPrintWriter().println(result);
2729 } catch (NumberFormatException | RemoteException e) {
2730 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2731 + enabledStr + ", error" + e.getMessage());
2732 getErrPrintWriter().println("Exception: " + e.getMessage());
2733 return -1;
2734 }
2735 return 0;
2736 }
2737
2738 private int handleSrcGetCarrierEnabledCommand() {
2739 int subId = getSubId("src get-carrier-enabled");
2740 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2741 return -1;
2742 }
2743
2744 boolean result = false;
2745 try {
2746 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2747 } catch (RemoteException e) {
2748 return -1;
2749 }
2750 if (VDBG) {
2751 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2752 }
2753 getOutPrintWriter().println(result);
2754 return 0;
2755 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002756
Hui Wangb647abe2021-02-26 09:33:38 -08002757 private int handleSrcSetFeatureValidationCommand() {
2758 //the release time value could be -1
2759 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2760 : SubscriptionManager.getDefaultSubscriptionId();
2761 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2762 return -1;
2763 }
2764
2765 String enabledStr = getNextArg();
2766 if (enabledStr == null) {
2767 return -1;
2768 }
2769
2770 try {
2771 boolean result =
2772 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2773 if (VDBG) {
2774 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2775 + enabledStr + ", result=" + result);
2776 }
2777 getOutPrintWriter().println(result);
2778 } catch (NumberFormatException | RemoteException e) {
2779 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2780 + enabledStr + ", error" + e.getMessage());
2781 getErrPrintWriter().println("Exception: " + e.getMessage());
2782 return -1;
2783 }
2784 return 0;
2785 }
2786
2787 private int handleSrcGetFeatureValidationCommand() {
2788 int subId = getSubId("src get-feature-validation");
2789 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2790 return -1;
2791 }
2792
2793 Boolean result = false;
2794 try {
2795 result = mInterface.getImsFeatureValidationOverride(subId);
2796 } catch (RemoteException e) {
2797 return -1;
2798 }
2799 if (VDBG) {
2800 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2801 }
2802 getOutPrintWriter().println(result);
2803 return 0;
2804 }
2805
2806
Hall Liuaa4211e2021-01-20 15:43:39 -08002807 private void onHelpCallComposer() {
2808 PrintWriter pw = getOutPrintWriter();
2809 pw.println("Call composer commands");
2810 pw.println(" callcomposer test-mode enable|disable|query");
2811 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2812 pw.println(" upload/download from carrier servers is disabled, and operations are");
2813 pw.println(" performed using emulated local files instead.");
2814 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2815 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2816 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002817 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2818 pw.println(" Enables or disables the user setting for call composer, as set by");
2819 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002820 }
2821
2822 private int handleCallComposerCommand() {
2823 String arg = getNextArg();
2824 if (arg == null) {
2825 onHelpCallComposer();
2826 return 0;
2827 }
2828
2829 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2830 "MODIFY_PHONE_STATE required for call composer shell cmds");
2831 switch (arg) {
2832 case CALL_COMPOSER_TEST_MODE: {
2833 String enabledStr = getNextArg();
2834 if (ENABLE.equals(enabledStr)) {
2835 CallComposerPictureManager.sTestMode = true;
2836 } else if (DISABLE.equals(enabledStr)) {
2837 CallComposerPictureManager.sTestMode = false;
2838 } else if (QUERY.equals(enabledStr)) {
2839 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2840 } else {
2841 onHelpCallComposer();
2842 return 1;
2843 }
2844 break;
2845 }
2846 case CALL_COMPOSER_SIMULATE_CALL: {
2847 int subscriptionId = Integer.valueOf(getNextArg());
2848 String uuidString = getNextArg();
2849 UUID uuid = UUID.fromString(uuidString);
2850 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2851 Binder.withCleanCallingIdentity(() -> {
2852 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2853 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2854 });
2855 try {
2856 Uri uri = storageUriFuture.get();
2857 getOutPrintWriter().println(String.valueOf(uri));
2858 } catch (Exception e) {
2859 throw new RuntimeException(e);
2860 }
2861 break;
2862 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002863 case CALL_COMPOSER_USER_SETTING: {
2864 try {
2865 int subscriptionId = Integer.valueOf(getNextArg());
2866 String enabledStr = getNextArg();
2867 if (ENABLE.equals(enabledStr)) {
2868 mInterface.setCallComposerStatus(subscriptionId,
2869 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2870 } else if (DISABLE.equals(enabledStr)) {
2871 mInterface.setCallComposerStatus(subscriptionId,
2872 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2873 } else if (QUERY.equals(enabledStr)) {
2874 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2875 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2876 } else {
2877 onHelpCallComposer();
2878 return 1;
2879 }
2880 } catch (RemoteException e) {
2881 e.printStackTrace(getOutPrintWriter());
2882 return 1;
2883 }
2884 break;
2885 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002886 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002887 return 0;
2888 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002889
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002890 private int handleHasCarrierPrivilegesCommand() {
2891 String packageName = getNextArgRequired();
2892
2893 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002894 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002895 try {
2896 hasCarrierPrivileges =
2897 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2898 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2899 } catch (RemoteException e) {
2900 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2901 getErrPrintWriter().println("Exception: " + e.getMessage());
2902 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002903 } finally {
2904 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002905 }
2906
2907 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002908 return 0;
2909 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002910
2911 private int handleAllowedNetworkTypesCommand(String command) {
2912 if (!checkShellUid()) {
2913 return -1;
2914 }
2915
2916 PrintWriter errPw = getErrPrintWriter();
2917 String tag = command + ": ";
2918 String opt;
2919 int subId = -1;
2920 Log.v(LOG_TAG, command + " start");
2921
2922 while ((opt = getNextOption()) != null) {
2923 if (opt.equals("-s")) {
2924 try {
2925 subId = slotStringToSubId(tag, getNextArgRequired());
2926 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2927 errPw.println(tag + "No valid subscription found.");
2928 return -1;
2929 }
2930 } catch (IllegalArgumentException e) {
2931 // Missing slot id
2932 errPw.println(tag + "SLOT_ID expected after -s.");
2933 return -1;
2934 }
2935 } else {
2936 errPw.println(tag + "Unknown option " + opt);
2937 return -1;
2938 }
2939 }
2940
2941 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2942 return handleGetAllowedNetworkTypesCommand(subId);
2943 }
2944 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2945 return handleSetAllowedNetworkTypesCommand(subId);
2946 }
2947 return -1;
2948 }
2949
2950 private int handleGetAllowedNetworkTypesCommand(int subId) {
2951 PrintWriter errPw = getErrPrintWriter();
2952
2953 long result = -1;
2954 try {
2955 if (mInterface != null) {
2956 result = mInterface.getAllowedNetworkTypesForReason(subId,
2957 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2958 } else {
2959 throw new IllegalStateException("telephony service is null.");
2960 }
2961 } catch (RemoteException e) {
2962 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2963 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2964 return -1;
2965 }
2966
2967 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2968 return 0;
2969 }
2970
2971 private int handleSetAllowedNetworkTypesCommand(int subId) {
2972 PrintWriter errPw = getErrPrintWriter();
2973
2974 String bitmaskString = getNextArg();
2975 if (TextUtils.isEmpty(bitmaskString)) {
2976 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2977 return -1;
2978 }
2979 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2980 if (allowedNetworkTypes < 0) {
2981 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2982 return -1;
2983 }
2984 boolean result = false;
2985 try {
2986 if (mInterface != null) {
2987 result = mInterface.setAllowedNetworkTypesForReason(subId,
2988 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2989 } else {
2990 throw new IllegalStateException("telephony service is null.");
2991 }
2992 } catch (RemoteException e) {
2993 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2994 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2995 return -1;
2996 }
2997
2998 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2999 if (result) {
3000 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3001 }
3002 getOutPrintWriter().println(resultMessage);
3003 return 0;
3004 }
3005
3006 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3007 if (TextUtils.isEmpty(bitmaskString)) {
3008 return -1;
3009 }
3010 if (VDBG) {
3011 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3012 + ", length: " + bitmaskString.length());
3013 }
3014 try {
3015 return Long.parseLong(bitmaskString, 2);
3016 } catch (NumberFormatException e) {
3017 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3018 return -1;
3019 }
3020 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003021
jimsun3b9ccac2021-10-26 15:01:23 +08003022 private int handleRadioSetModemServiceCommand() {
3023 PrintWriter errPw = getErrPrintWriter();
3024 String serviceName = null;
3025
3026 String opt;
3027 while ((opt = getNextOption()) != null) {
3028 switch (opt) {
3029 case "-s": {
3030 serviceName = getNextArgRequired();
3031 break;
3032 }
3033 }
3034 }
3035
3036 try {
3037 boolean result = mInterface.setModemService(serviceName);
3038 if (VDBG) {
3039 Log.v(LOG_TAG,
3040 "RadioSetModemService " + serviceName + ", result = " + result);
3041 }
3042 getOutPrintWriter().println(result);
3043 } catch (RemoteException e) {
3044 Log.w(LOG_TAG,
3045 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3046 errPw.println("Exception: " + e.getMessage());
3047 return -1;
3048 }
3049 return 0;
3050 }
3051
3052 private int handleRadioGetModemServiceCommand() {
3053 PrintWriter errPw = getErrPrintWriter();
3054 String result;
3055
3056 try {
3057 result = mInterface.getModemService();
3058 getOutPrintWriter().println(result);
3059 } catch (RemoteException e) {
3060 errPw.println("Exception: " + e.getMessage());
3061 return -1;
3062 }
3063 if (VDBG) {
3064 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3065 }
3066 return 0;
3067 }
3068
3069 private int handleRadioCommand() {
3070 String arg = getNextArg();
3071 if (arg == null) {
3072 onHelpRadio();
3073 return 0;
3074 }
3075
3076 switch (arg) {
3077 case RADIO_SET_MODEM_SERVICE:
3078 return handleRadioSetModemServiceCommand();
3079
3080 case RADIO_GET_MODEM_SERVICE:
3081 return handleRadioGetModemServiceCommand();
3082 }
3083
3084 return -1;
3085 }
arunvoddud7401012022-12-15 16:08:12 +00003086
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003087 private int handleSetSatelliteServicePackageNameCommand() {
3088 PrintWriter errPw = getErrPrintWriter();
3089 String serviceName = null;
3090
3091 String opt;
3092 while ((opt = getNextOption()) != null) {
3093 switch (opt) {
3094 case "-s": {
3095 serviceName = getNextArgRequired();
3096 break;
3097 }
3098 }
3099 }
3100 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3101 + serviceName);
3102
3103 try {
3104 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3105 if (VDBG) {
3106 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3107 + ", result = " + result);
3108 }
3109 getOutPrintWriter().println(result);
3110 } catch (RemoteException e) {
3111 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3112 + ", error = " + e.getMessage());
3113 errPw.println("Exception: " + e.getMessage());
3114 return -1;
3115 }
3116 return 0;
3117 }
3118
arunvoddud7401012022-12-15 16:08:12 +00003119 private int handleCarrierRestrictionStatusCommand() {
3120 try {
3121 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3122 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3123 mInterface.getModemService()))) {
3124 Log.v(LOG_TAG,
3125 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3126 + " checkShellUid fails");
3127 return -1;
3128 }
3129 } catch (RemoteException ex) {
3130 ex.printStackTrace();
3131 }
3132 String callerInfo = getNextOption();
3133 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3134 if (TextUtils.isEmpty(callerInfo)) {
3135 // reset the Json content after testing
3136 allowListInfo.updateJsonForTest(null);
3137 return 0;
3138 }
3139 if (callerInfo.startsWith("--")) {
3140 callerInfo = callerInfo.replace("--", "");
3141 }
3142 String params[] = callerInfo.split(",");
3143 StringBuffer jsonStrBuffer = new StringBuffer();
3144 String tokens;
3145 for (int index = 0; index < params.length; index++) {
3146 tokens = convertToJsonString(index, params[index]);
3147 if (TextUtils.isEmpty(tokens)) {
3148 // received wrong format from CTS
3149 if (VDBG) {
3150 Log.v(LOG_TAG,
3151 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3152 }
3153 return -1;
3154 }
3155 jsonStrBuffer.append(tokens);
3156 }
3157 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3158 return result;
3159 }
3160
Benedict Wong66477622023-02-03 23:30:57 +00003161 // set-carrier-service-package-override
3162 private int setCarrierServicePackageOverride() {
3163 PrintWriter errPw = getErrPrintWriter();
3164 int subId = SubscriptionManager.getDefaultSubscriptionId();
3165
3166 String opt;
3167 while ((opt = getNextOption()) != null) {
3168 switch (opt) {
3169 case "-s":
3170 try {
3171 subId = Integer.parseInt(getNextArgRequired());
3172 } catch (NumberFormatException e) {
3173 errPw.println(
3174 "set-carrier-service-package-override requires an integer as a"
3175 + " subscription ID.");
3176 return -1;
3177 }
3178 break;
3179 }
3180 }
3181
3182 String packageName = getNextArg();
3183 if (packageName == null) {
3184 errPw.println("set-carrier-service-package-override requires a override package name.");
3185 return -1;
3186 }
3187
3188 try {
3189 mInterface.setCarrierServicePackageOverride(
3190 subId, packageName, mContext.getOpPackageName());
3191
3192 if (VDBG) {
3193 Log.v(
3194 LOG_TAG,
3195 "set-carrier-service-package-override -s " + subId + " " + packageName);
3196 }
3197 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3198 Log.w(
3199 LOG_TAG,
3200 "set-carrier-service-package-override -s "
3201 + subId
3202 + " "
3203 + packageName
3204 + ", error"
3205 + e.getMessage());
3206 errPw.println("Exception: " + e.getMessage());
3207 return -1;
3208 }
3209 return 0;
3210 }
3211
3212 // clear-carrier-service-package-override
3213 private int clearCarrierServicePackageOverride() {
3214 PrintWriter errPw = getErrPrintWriter();
3215 int subId = getDefaultSlot();
3216
3217 String opt;
3218 while ((opt = getNextOption()) != null) {
3219 switch (opt) {
3220 case "-s":
3221 try {
3222 subId = Integer.parseInt(getNextArgRequired());
3223 } catch (NumberFormatException e) {
3224 errPw.println(
3225 "clear-carrier-service-package-override requires an integer as a"
3226 + " subscription ID.");
3227 return -1;
3228 }
3229 break;
3230 }
3231 }
3232
3233 try {
3234 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3235
3236 if (VDBG) {
3237 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3238 }
3239 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3240 Log.w(
3241 LOG_TAG,
3242 "clear-carrier-service-package-override -s "
3243 + subId
3244 + ", error"
3245 + e.getMessage());
3246 errPw.println("Exception: " + e.getMessage());
3247 return -1;
3248 }
3249 return 0;
3250 }
arunvoddud7401012022-12-15 16:08:12 +00003251
3252 /**
3253 * Building the string that can be used to build the JsonObject which supports to stub the data
3254 * in CarrierAllowListInfo for CTS testing. sample format is like
3255 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3256 */
3257 private String convertToJsonString(int index, String param) {
3258
3259 String token[] = param.split(":");
3260 String jSonString;
3261 switch (index) {
3262 case 0:
3263 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3264 break;
3265 case 1:
3266 jSonString =
3267 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3268 break;
3269 case 2:
3270 jSonString =
3271 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3272 break;
3273 default:
3274 jSonString = null;
3275 }
3276 return jSonString;
3277 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003278}