blob: 80df0997dbb31c8fefe55cc646eef3a78468d8f1 [file] [log] [blame]
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.phone;
18
Tyler Gunn92479152021-01-20 16:30:10 -080019import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_AUDIO_CODEC;
20import static com.android.internal.telephony.d2d.Communicator.MESSAGE_CALL_RADIO_ACCESS_TYPE;
21import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_BATTERY_STATE;
22import static com.android.internal.telephony.d2d.Communicator.MESSAGE_DEVICE_NETWORK_COVERAGE;
23
Cole Faustc16d5292022-10-15 21:33:27 -070024import static java.util.Map.entry;
25
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010027import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080028import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010030import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080031import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070032import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000033import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070034import android.provider.BlockedNumberContract;
Nazanin014f41e2021-05-06 17:26:31 -070035import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010036import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070037import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070038import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000039import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070040import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080041import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000042import android.telephony.ims.ImsException;
43import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080044import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080045import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000046import android.util.ArrayMap;
47import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070049import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070050
Brad Ebinger14d467f2021-02-12 06:18:28 +000051import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070052import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080053import com.android.internal.telephony.Phone;
54import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080055import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080056import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080057import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080058import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080059import com.android.phone.callcomposer.CallComposerPictureManager;
Shivakumar Neginal9cd61892022-12-19 04:38:52 +000060import com.android.phone.euicc.EuiccUiDispatcherActivity;
arunvoddud7401012022-12-15 16:08:12 +000061import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070062
Allen Xuee00f0e2022-03-14 21:04:49 +000063import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070064import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080065import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000066import java.util.Arrays;
67import java.util.Collections;
Brad Ebinger24c29992019-12-05 13:03:21 -080068import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000069import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010070import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000071import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010072import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080073import java.util.UUID;
74import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070075
76/**
77 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
78 * permission checks have been done before onCommand was called. Make sure any commands processed
79 * here also contain the appropriate permissions checks.
80 */
81
Hall Liua1548bd2019-12-24 14:14:12 -080082public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070083
84 private static final String LOG_TAG = "TelephonyShellCommand";
85 // Don't commit with this true.
86 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070087 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070088
Hall Liuaa4211e2021-01-20 15:43:39 -080089 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070090 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080091 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080092 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080093 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070094 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000095 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000096 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010097 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080098 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080099 private static final String ENABLE = "enable";
100 private static final String DISABLE = "disable";
101 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000102 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
Benedict Wong66477622023-02-03 23:30:57 +0000103 private static final String SET_CARRIER_SERVICE_PACKAGE_OVERRIDE =
104 "set-carrier-service-package-override";
105 private static final String CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE =
106 "clear-carrier-service-package-override";
arunvoddud7401012022-12-15 16:08:12 +0000107 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800108
Hall Liu7135e502021-02-04 16:58:17 -0800109 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800110 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800111 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800112
Brad Ebinger999d3302020-11-25 14:31:39 -0800113 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
114 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
115 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700116 // Used to disable or enable processing of conference event package data from the network.
117 // This is handy for testing scenarios where CEP data does not exist on a network which does
118 // support CEP data.
119 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700120
Hall Liud892bec2018-11-30 14:51:45 -0800121 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800122 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800123
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100124 private static final String CC_GET_VALUE = "get-value";
125 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000126 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100127 private static final String CC_CLEAR_VALUES = "clear-values";
128
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000129 private static final String EUICC_SUBCOMMAND = "euicc";
130 private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
131
Hui Wang641e81c2020-10-12 12:14:23 -0700132 private static final String GBA_SUBCOMMAND = "gba";
133 private static final String GBA_SET_SERVICE = "set-service";
134 private static final String GBA_GET_SERVICE = "get-service";
135 private static final String GBA_SET_RELEASE_TIME = "set-release";
136 private static final String GBA_GET_RELEASE_TIME = "get-release";
137
Hui Wang761a6682020-10-31 05:12:53 +0000138 private static final String SINGLE_REGISTATION_CONFIG = "src";
139 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
140 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
141 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
142 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800143 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
144 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800145 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
146 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000147
Tyler Gunn92479152021-01-20 16:30:10 -0800148 private static final String D2D_SUBCOMMAND = "d2d";
149 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800150 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700151 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800152
Nazanin014f41e2021-05-06 17:26:31 -0700153 private static final String BARRING_SUBCOMMAND = "barring";
154 private static final String BARRING_SEND_INFO = "send";
155
James.cf Linbcdf8b32021-01-14 16:44:13 +0800156 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800157 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800158 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800159 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800160 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
161 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000162 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
163 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800164 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
165 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800166 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
167 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800168
jimsun3b9ccac2021-10-26 15:01:23 +0800169 private static final String RADIO_SUBCOMMAND = "radio";
170 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
171 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
172
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800173 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
174 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
175
Jordan Liu0ccee222021-04-27 11:55:13 -0700176 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
177 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
178
Jack Nudelman644b91a2021-03-12 14:09:48 -0800179 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
180 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
181 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700182 private static final String SET_SATELLITE_SERVICE_PACKAGE_NAME =
183 "set-satellite-service-package-name";
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700184 private static final String SET_SATELLITE_LISTENING_TIMEOUT_DURATION =
185 "set-satellite-listening-timeout-duration";
Jack Nudelman644b91a2021-03-12 14:09:48 -0800186
Grant Menke567d48f2022-08-18 20:19:10 +0000187 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
188 + "'*', '#' or '+') needs to be specified after -a in the command ";
189
190 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
191 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
192 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
193
SongFerngWang98dd5992021-05-13 17:50:00 +0800194 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
195 "get-allowed-network-types-for-users";
196 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
197 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000198 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000199 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700200 // Take advantage of existing methods that already contain permissions checks when possible.
201 private final ITelephony mInterface;
202
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100203 private SubscriptionManager mSubscriptionManager;
204 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700205 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700206 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100207
208 private enum CcType {
209 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000210 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100211 }
212
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100213 private class CcOptionParseResult {
214 public int mSubId;
215 public boolean mPersistent;
216 }
217
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100218 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
219 // keys by looking at the end of the string which usually tells the type.
220 // For instance: "xxxx_string", "xxxx_string_array", etc.
221 // The carrier config keys in this map does not follow this convention. It is therefore not
222 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700223 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
224 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
225 CcType.STRING),
226 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
227 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
228 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
229 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
230 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
231 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
232 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
233 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
234 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
235 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
236 CcType.STRING),
237 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
238 CcType.STRING_ARRAY),
239 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
240 CcType.STRING_ARRAY),
241 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
242 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
243 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
244 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
245 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
246 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
247 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
248 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100249
Brad Ebinger14d467f2021-02-12 06:18:28 +0000250 /**
251 * Map from a shorthand string to the feature tags required in registration required in order
252 * for the RCS feature to be considered "capable".
253 */
254 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
255 static {
256 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
257 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
258 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
259 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
260 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
261 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
262 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
263 FeatureTags.FEATURE_TAG_VIDEO)));
264 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
265 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
266 map.put("call_comp",
267 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
268 map.put("call_comp_mmtel",
269 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
270 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
271 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
272 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
273 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
274 // version
275 map.put("chatbot", new ArraySet<>(Arrays.asList(
276 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
277 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
278 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
279 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000280 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000281 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
282 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
283 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
284 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
285 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000286 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000287 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
288 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
289 }
290
291
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100292 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700293 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100294 mCarrierConfigManager =
295 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
296 mSubscriptionManager = (SubscriptionManager)
297 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700298 mTelephonyRegistryManager = (TelephonyRegistryManager)
299 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700300 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700301 }
302
303 @Override
304 public int onCommand(String cmd) {
305 if (cmd == null) {
306 return handleDefaultCommands(null);
307 }
308
309 switch (cmd) {
310 case IMS_SUBCOMMAND: {
311 return handleImsCommand();
312 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800313 case RCS_UCE_COMMAND:
314 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800315 case NUMBER_VERIFICATION_SUBCOMMAND:
316 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800317 case EMERGENCY_CALLBACK_MODE:
318 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800319 case EMERGENCY_NUMBER_TEST_MODE:
320 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100321 case CARRIER_CONFIG_SUBCOMMAND: {
322 return handleCcCommand();
323 }
Shuo Qianf5125122019-12-16 17:03:07 -0800324 case DATA_TEST_MODE:
325 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700326 case END_BLOCK_SUPPRESSION:
327 return handleEndBlockSuppressionCommand();
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000328 case EUICC_SUBCOMMAND:
329 return handleEuiccCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700330 case GBA_SUBCOMMAND:
331 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800332 case D2D_SUBCOMMAND:
333 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700334 case BARRING_SUBCOMMAND:
335 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000336 case SINGLE_REGISTATION_CONFIG:
337 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000338 case RESTART_MODEM:
339 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800340 case CALL_COMPOSER_SUBCOMMAND:
341 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000342 case UNATTENDED_REBOOT:
343 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800344 case HAS_CARRIER_PRIVILEGES_COMMAND:
345 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800346 case THERMAL_MITIGATION_COMMAND:
347 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700348 case DISABLE_PHYSICAL_SUBSCRIPTION:
349 return handleEnablePhysicalSubscription(false);
350 case ENABLE_PHYSICAL_SUBSCRIPTION:
351 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800352 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
353 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
354 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000355 case GET_IMEI:
356 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000357 case GET_SIM_SLOTS_MAPPING:
358 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800359 case RADIO_SUBCOMMAND:
360 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000361 case CARRIER_RESTRICTION_STATUS_TEST:
362 return handleCarrierRestrictionStatusCommand();
Benedict Wong66477622023-02-03 23:30:57 +0000363 case SET_CARRIER_SERVICE_PACKAGE_OVERRIDE:
364 return setCarrierServicePackageOverride();
365 case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
366 return clearCarrierServicePackageOverride();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700367 case SET_SATELLITE_SERVICE_PACKAGE_NAME:
368 return handleSetSatelliteServicePackageNameCommand();
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700369 case SET_SATELLITE_LISTENING_TIMEOUT_DURATION:
370 return handleSetSatelliteListeningTimeoutDuration();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700371 default: {
372 return handleDefaultCommands(cmd);
373 }
374 }
375 }
376
377 @Override
378 public void onHelp() {
379 PrintWriter pw = getOutPrintWriter();
380 pw.println("Telephony Commands:");
381 pw.println(" help");
382 pw.println(" Print this help text.");
383 pw.println(" ims");
384 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800385 pw.println(" uce");
386 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800387 pw.println(" emergency-number-test-mode");
388 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700389 pw.println(" end-block-suppression");
390 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800391 pw.println(" data");
392 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100393 pw.println(" cc");
394 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700395 pw.println(" gba");
396 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000397 pw.println(" src");
398 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000399 pw.println(" restart-modem");
400 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000401 pw.println(" unattended-reboot");
402 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800403 pw.println(" has-carrier-privileges [package]");
404 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800405 pw.println(" get-allowed-network-types-for-users");
406 pw.println(" Get the Allowed Network Types.");
407 pw.println(" set-allowed-network-types-for-users");
408 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800409 pw.println(" radio");
410 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700411 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800412 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800413 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700414 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800415 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100416 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700417 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000418 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800419 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700420 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800421 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800422 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000423 onHelpImei();
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700424 onHelpSatellite();
Tyler Gunn92479152021-01-20 16:30:10 -0800425 }
426
427 private void onHelpD2D() {
428 PrintWriter pw = getOutPrintWriter();
429 pw.println("D2D Comms Commands:");
430 pw.println(" d2d send TYPE VALUE");
431 pw.println(" Sends a D2D message of specified type and value.");
432 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
433 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
434 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
435 MESSAGE_CALL_AUDIO_CODEC));
436 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
437 + Communicator.messageToString(
438 MESSAGE_DEVICE_BATTERY_STATE));
439 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
440 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800441 pw.println(" d2d transport TYPE");
442 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
443 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700444 pw.println(" d2d set-device-support true/default");
445 pw.println(" true - forces device support to be enabled for D2D.");
446 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
447 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700448 }
449
Nazanin014f41e2021-05-06 17:26:31 -0700450 private void onHelpBarring() {
451 PrintWriter pw = getOutPrintWriter();
452 pw.println("Barring Commands:");
453 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
454 + " -t CONDITIONAL_BARRING_TIME_SECS");
455 pw.println(" Notifies of a barring info change for the specified slot id.");
456 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
457 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
458 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
459 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
460 }
461
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700462 private void onHelpIms() {
463 PrintWriter pw = getOutPrintWriter();
464 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800465 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700466 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
467 pw.println(" ImsService. Options are:");
468 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
469 pw.println(" is specified, it will choose the default voice SIM slot.");
470 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
471 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800472 pw.println(" -f: Set the feature that this override if for, if no option is");
473 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700474 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
475 pw.println(" Gets the package name of the currently defined ImsService.");
476 pw.println(" Options are:");
477 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
478 pw.println(" is specified, it will choose the default voice SIM slot.");
479 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000480 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800481 pw.println(" -f: The feature type that the query will be requested for. If none is");
482 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800483 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
484 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
485 pw.println(" configuration overrides. Options are:");
486 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
487 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700488 pw.println(" ims enable [-s SLOT_ID]");
489 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
490 pw.println(" if none is specified.");
491 pw.println(" ims disable [-s SLOT_ID]");
492 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
493 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700494 pw.println(" ims conference-event-package [enable/disable]");
495 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700496 }
497
James.cf Linbcdf8b32021-01-14 16:44:13 +0800498 private void onHelpUce() {
499 PrintWriter pw = getOutPrintWriter();
500 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800501 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
502 pw.println(" Get the EAB contacts from the EAB database.");
503 pw.println(" Options are:");
504 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
505 pw.println(" Expected output format :");
506 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800507 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
508 pw.println(" Remove the EAB contacts from the EAB database.");
509 pw.println(" Options are:");
510 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
511 pw.println(" is specified, it will choose the default voice SIM slot.");
512 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800513 pw.println(" uce get-device-enabled");
514 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
515 pw.println(" uce set-device-enabled true|false");
516 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
517 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000518 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
519 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
520 pw.println(" Options are:");
521 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
522 pw.println(" is specified, it will choose the default voice SIM slot.");
523 pw.println(" add [CAPABILITY]: add a new capability");
524 pw.println(" remove [CAPABILITY]: remove a capability");
525 pw.println(" clear: clear all capability overrides");
526 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
527 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
528 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
529 pw.println(" chatbot_sa, chatbot_role] as well as full length");
530 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
531 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
532 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
533 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800534 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
535 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800536 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
537 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800538 }
539
Hall Liud892bec2018-11-30 14:51:45 -0800540 private void onHelpNumberVerification() {
541 PrintWriter pw = getOutPrintWriter();
542 pw.println("Number verification commands");
543 pw.println(" numverify override-package PACKAGE_NAME;");
544 pw.println(" Set the authorized package for number verification.");
545 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800546 pw.println(" numverify fake-call NUMBER;");
547 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
548 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800549 }
550
Jack Nudelman644b91a2021-03-12 14:09:48 -0800551 private void onHelpThermalMitigation() {
552 PrintWriter pw = getOutPrintWriter();
553 pw.println("Thermal mitigation commands");
554 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
555 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
556 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
557 pw.println(" Remove the package from one of the authorized packages for thermal "
558 + "mitigation.");
559 }
560
Jordan Liu0ccee222021-04-27 11:55:13 -0700561 private void onHelpDisableOrEnablePhysicalSubscription() {
562 PrintWriter pw = getOutPrintWriter();
563 pw.println("Disable or enable a physical subscription");
564 pw.println(" disable-physical-subscription SUB_ID");
565 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
566 pw.println(" enable-physical-subscription SUB_ID");
567 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
568 }
569
Shuo Qianf5125122019-12-16 17:03:07 -0800570 private void onHelpDataTestMode() {
571 PrintWriter pw = getOutPrintWriter();
572 pw.println("Mobile Data Test Mode Commands:");
573 pw.println(" data enable: enable mobile data connectivity");
574 pw.println(" data disable: disable mobile data connectivity");
575 }
576
sqian9d4df8b2019-01-15 18:32:07 -0800577 private void onHelpEmergencyNumber() {
578 PrintWriter pw = getOutPrintWriter();
579 pw.println("Emergency Number Test Mode Commands:");
580 pw.println(" emergency-number-test-mode ");
581 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
582 + " the test mode");
583 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700584 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800585 pw.println(" -c: clear the emergency number list in the test mode.");
586 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700587 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800588 pw.println(" -p: get the full emergency number list in the test mode.");
589 }
590
Shuo Qian489d9282020-07-09 11:30:03 -0700591 private void onHelpEndBlockSupperssion() {
592 PrintWriter pw = getOutPrintWriter();
593 pw.println("End Block Suppression command:");
594 pw.println(" end-block-suppression: disable suppressing blocking by contact");
595 pw.println(" with emergency services.");
596 }
597
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100598 private void onHelpCc() {
599 PrintWriter pw = getOutPrintWriter();
600 pw.println("Carrier Config Commands:");
601 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
602 pw.println(" Print carrier config values.");
603 pw.println(" Options are:");
604 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
605 pw.println(" is specified, it will choose the default voice SIM slot.");
606 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
607 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100608 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100609 pw.println(" Set carrier config KEY to NEW_VALUE.");
610 pw.println(" Options are:");
611 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
612 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100613 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100614 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
615 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
616 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
617 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000618 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
619 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
620 pw.println(" provided through standard input and follow CarrierConfig XML format.");
621 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
622 pw.println(" Options are:");
623 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
624 pw.println(" is specified, it will choose the default voice SIM slot.");
625 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100626 pw.println(" cc clear-values [-s SLOT_ID]");
627 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000628 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100629 pw.println(" Options are:");
630 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
631 pw.println(" is specified, it will choose the default voice SIM slot.");
632 }
633
Shivakumar Neginal9cd61892022-12-19 04:38:52 +0000634 private void onHelpEuicc() {
635 PrintWriter pw = getOutPrintWriter();
636 pw.println("Euicc Commands:");
637 pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
638 pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
639 pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
640 pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
641 }
642
Hui Wang641e81c2020-10-12 12:14:23 -0700643 private void onHelpGba() {
644 PrintWriter pw = getOutPrintWriter();
645 pw.println("Gba Commands:");
646 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
647 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
648 pw.println(" Options are:");
649 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
650 pw.println(" is specified, it will choose the default voice SIM slot.");
651 pw.println(" gba get-service [-s SLOT_ID]");
652 pw.println(" Gets the package name of the currently defined GbaService.");
653 pw.println(" Options are:");
654 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
655 pw.println(" is specified, it will choose the default voice SIM slot.");
656 pw.println(" gba set-release [-s SLOT_ID] n");
657 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
658 pw.println(" Do not release/unbind if n is -1.");
659 pw.println(" Options are:");
660 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
661 pw.println(" is specified, it will choose the default voice SIM slot.");
662 pw.println(" gba get-release [-s SLOT_ID]");
663 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
664 pw.println(" Options are:");
665 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
666 pw.println(" is specified, it will choose the default voice SIM slot.");
667 }
668
Hui Wang761a6682020-10-31 05:12:53 +0000669 private void onHelpSrc() {
670 PrintWriter pw = getOutPrintWriter();
671 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800672 pw.println(" src set-test-enabled true|false");
673 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
674 pw.println(" The value could be true, false, or null(undefined).");
675 pw.println(" src get-test-enabled");
676 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000677 pw.println(" src set-device-enabled true|false|null");
678 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
679 pw.println(" The value could be true, false, or null(undefined).");
680 pw.println(" src get-device-enabled");
681 pw.println(" Gets the device config for RCS VoLTE single registration.");
682 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
683 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
684 pw.println(" The value could be true, false, or null(undefined).");
685 pw.println(" Options are:");
686 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
687 pw.println(" is specified, it will choose the default voice SIM slot.");
688 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
689 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
690 pw.println(" Options are:");
691 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
692 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800693 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
694 pw.println(" Sets ims feature validation result.");
695 pw.println(" The value could be true, false, or null(undefined).");
696 pw.println(" Options are:");
697 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
698 pw.println(" is specified, it will choose the default voice SIM slot.");
699 pw.println(" src get-feature-validation [-s SLOT_ID]");
700 pw.println(" Gets ims feature validation override value.");
701 pw.println(" Options are:");
702 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
703 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000704 }
705
SongFerngWang98dd5992021-05-13 17:50:00 +0800706 private void onHelpAllowedNetworkTypes() {
707 PrintWriter pw = getOutPrintWriter();
708 pw.println("Allowed Network Types Commands:");
709 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
710 pw.println(" Print allowed network types value.");
711 pw.println(" Options are:");
712 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
713 pw.println(" option is specified, it will choose the default voice SIM slot.");
714 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
715 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
716 pw.println(" Options are:");
717 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
718 pw.println(" option is specified, it will choose the default voice SIM slot.");
719 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
720 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
721 pw.println(" at TelephonyManager.java");
722 pw.println(" For example:");
723 pw.println(" NR only : 10000000000000000000");
724 pw.println(" NR|LTE : 11000001000000000000");
725 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
726 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
727 pw.println(" LTE only : 01000001000000000000");
728 }
729
jimsun3b9ccac2021-10-26 15:01:23 +0800730 private void onHelpRadio() {
731 PrintWriter pw = getOutPrintWriter();
732 pw.println("Radio Commands:");
733 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
734 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
735 pw.println(" to be the bound. Options are:");
736 pw.println(" -s: the service name that the modem service should be bound for.");
737 pw.println(" If no option is specified, it will bind to the default.");
738 pw.println(" radio get-modem-service");
739 pw.println(" Gets the service name of the currently defined modem service.");
740 pw.println(" If it is binding to default, 'default' returns.");
741 pw.println(" If it doesn't bind to any modem service for some reasons,");
742 pw.println(" the result would be 'unknown'.");
743 }
744
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700745 private void onHelpSatellite() {
746 PrintWriter pw = getOutPrintWriter();
747 pw.println("Satellite Commands:");
748 pw.println(" set-satellite-service-package-name [-s SERVICE_PACKAGE_NAME]");
749 pw.println(" Sets the package name of satellite service defined in");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700750 pw.println(" SERVICE_PACKAGE_NAME to be bound. Options are:");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700751 pw.println(" -s: the satellite service package name that Telephony will bind to.");
752 pw.println(" If no option is specified, it will bind to the default.");
Thomas Nguyenf9a533c2023-04-06 20:48:41 -0700753 pw.println(" set-satellite-listening-timeout-duration [-t TIMEOUT_MILLIS]");
754 pw.println(" Sets the timeout duration in millis that satellite will stay at listening");
755 pw.println(" mode. Options are:");
756 pw.println(" -t: the timeout duration in milliseconds.");
757 pw.println(" If no option is specified, it will use the default values.");
Thomas Nguyend34a5fc2023-03-23 21:07:03 -0700758 }
759
Ling Ma4fbab492022-01-25 22:36:16 +0000760 private void onHelpImei() {
761 PrintWriter pw = getOutPrintWriter();
762 pw.println("IMEI Commands:");
763 pw.println(" get-imei [-s SLOT_ID]");
764 pw.println(" Gets the device IMEI. Options are:");
765 pw.println(" -s: the slot ID to get the IMEI. If no option");
766 pw.println(" is specified, it will choose the default voice SIM slot.");
767 }
768
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700769 private int handleImsCommand() {
770 String arg = getNextArg();
771 if (arg == null) {
772 onHelpIms();
773 return 0;
774 }
775
776 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800777 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700778 return handleImsSetServiceCommand();
779 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800780 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700781 return handleImsGetServiceCommand();
782 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800783 case IMS_CLEAR_SERVICE_OVERRIDE: {
784 return handleImsClearCarrierServiceCommand();
785 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800786 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700787 return handleEnableIms();
788 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800789 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700790 return handleDisableIms();
791 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700792 case IMS_CEP: {
793 return handleCepChange();
794 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700795 }
796
797 return -1;
798 }
799
Shuo Qianf5125122019-12-16 17:03:07 -0800800 private int handleDataTestModeCommand() {
801 PrintWriter errPw = getErrPrintWriter();
802 String arg = getNextArgRequired();
803 if (arg == null) {
804 onHelpDataTestMode();
805 return 0;
806 }
807 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800808 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800809 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700810 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800811 } catch (RemoteException ex) {
812 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
813 errPw.println("Exception: " + ex.getMessage());
814 return -1;
815 }
816 break;
817 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800818 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800819 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700820 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800821 } catch (RemoteException ex) {
822 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
823 errPw.println("Exception: " + ex.getMessage());
824 return -1;
825 }
826 break;
827 }
828 default:
829 onHelpDataTestMode();
830 break;
831 }
832 return 0;
833 }
834
Shuo Qianccbaf742021-02-22 18:32:21 -0800835 private int handleEmergencyCallbackModeCommand() {
836 PrintWriter errPw = getErrPrintWriter();
837 try {
838 mInterface.startEmergencyCallbackMode();
839 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
840 } catch (RemoteException ex) {
841 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
842 errPw.println("Exception: " + ex.getMessage());
843 return -1;
844 }
845 return 0;
846 }
847
Grant Menke567d48f2022-08-18 20:19:10 +0000848 private void removeEmergencyNumberTestMode(String emergencyNumber) {
849 PrintWriter errPw = getErrPrintWriter();
850 for (int routingType : ROUTING_TYPES) {
851 try {
852 mInterface.updateEmergencyNumberListTestMode(
853 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
854 new EmergencyNumber(emergencyNumber, "", "",
855 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
856 new ArrayList<String>(),
857 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
858 routingType));
859 } catch (RemoteException ex) {
860 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
861 errPw.println("Exception: " + ex.getMessage());
862 }
863 }
864 }
865
sqian9d4df8b2019-01-15 18:32:07 -0800866 private int handleEmergencyNumberTestModeCommand() {
867 PrintWriter errPw = getErrPrintWriter();
868 String opt = getNextOption();
869 if (opt == null) {
870 onHelpEmergencyNumber();
871 return 0;
872 }
sqian9d4df8b2019-01-15 18:32:07 -0800873 switch (opt) {
874 case "-a": {
875 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000876 if (emergencyNumberCmd == null){
877 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800878 return -1;
879 }
Grant Menke567d48f2022-08-18 20:19:10 +0000880 String[] params = emergencyNumberCmd.split(":");
881 String emergencyNumber;
882 if (params[0] == null ||
883 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
884 errPw.println(INVALID_ENTRY_ERROR);
885 return -1;
886 } else {
887 emergencyNumber = params[0];
888 }
889 removeEmergencyNumberTestMode(emergencyNumber);
890 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
891 if (params.length > 1) {
892 switch (params[1].toLowerCase(Locale.ROOT)) {
893 case "emergency":
894 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
895 break;
896 case "normal":
897 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
898 break;
899 case "unknown":
900 break;
901 default:
902 errPw.println("\"" + params[1] + "\" is not a valid specification for "
903 + "emergency call routing. Please enter either \"normal\", "
904 + "\"unknown\", or \"emergency\" for call routing. "
905 + "(-a 1234:normal)");
906 return -1;
907 }
908 }
sqian9d4df8b2019-01-15 18:32:07 -0800909 try {
910 mInterface.updateEmergencyNumberListTestMode(
911 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000912 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800913 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
914 new ArrayList<String>(),
915 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000916 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800917 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000918 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800919 + ", error " + ex.getMessage());
920 errPw.println("Exception: " + ex.getMessage());
921 return -1;
922 }
923 break;
924 }
925 case "-c": {
926 try {
927 mInterface.updateEmergencyNumberListTestMode(
928 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
929 } catch (RemoteException ex) {
930 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
931 errPw.println("Exception: " + ex.getMessage());
932 return -1;
933 }
934 break;
935 }
936 case "-r": {
937 String emergencyNumberCmd = getNextArgRequired();
938 if (emergencyNumberCmd == null
939 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700940 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800941 + " to be specified after -r in the command ");
942 return -1;
943 }
Grant Menke567d48f2022-08-18 20:19:10 +0000944 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800945 break;
946 }
947 case "-p": {
948 try {
949 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
950 } catch (RemoteException ex) {
951 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
952 errPw.println("Exception: " + ex.getMessage());
953 return -1;
954 }
955 break;
956 }
957 default:
958 onHelpEmergencyNumber();
959 break;
960 }
961 return 0;
962 }
963
Hall Liud892bec2018-11-30 14:51:45 -0800964 private int handleNumberVerificationCommand() {
965 String arg = getNextArg();
966 if (arg == null) {
967 onHelpNumberVerification();
968 return 0;
969 }
970
Hall Liuca5af3a2018-12-04 16:58:23 -0800971 if (!checkShellUid()) {
972 return -1;
973 }
974
Hall Liud892bec2018-11-30 14:51:45 -0800975 switch (arg) {
976 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800977 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
978 return 0;
979 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800980 case NUMBER_VERIFICATION_FAKE_CALL: {
981 boolean val = NumberVerificationManager.getInstance()
982 .checkIncomingCall(getNextArg());
983 getOutPrintWriter().println(val ? "1" : "0");
984 return 0;
985 }
Hall Liud892bec2018-11-30 14:51:45 -0800986 }
987
988 return -1;
989 }
990
Jordan Liu0ccee222021-04-27 11:55:13 -0700991 private boolean subIsEsim(int subId) {
992 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
993 if (info != null) {
994 return info.isEmbedded();
995 }
996 return false;
997 }
998
999 private int handleEnablePhysicalSubscription(boolean enable) {
1000 PrintWriter errPw = getErrPrintWriter();
1001 int subId = 0;
1002 try {
1003 subId = Integer.parseInt(getNextArgRequired());
1004 } catch (NumberFormatException e) {
1005 errPw.println((enable ? "enable" : "disable")
1006 + "-physical-subscription requires an integer as a subId.");
1007 return -1;
1008 }
1009 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1010 // non user build.
1011 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1012 errPw.println("cc: Permission denied.");
1013 return -1;
1014 }
1015 // Verify that the subId represents a physical sub
1016 if (subIsEsim(subId)) {
1017 errPw.println("SubId " + subId + " is not for a physical subscription");
1018 return -1;
1019 }
1020 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
1021 + " physical subscription with subId=" + subId);
1022 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
1023 return 0;
1024 }
1025
Jack Nudelman644b91a2021-03-12 14:09:48 -08001026 private int handleThermalMitigationCommand() {
1027 String arg = getNextArg();
1028 String packageName = getNextArg();
1029 if (arg == null || packageName == null) {
1030 onHelpThermalMitigation();
1031 return 0;
1032 }
1033
1034 if (!checkShellUid()) {
1035 return -1;
1036 }
1037
1038 switch (arg) {
1039 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1040 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
1041 return 0;
1042 }
1043 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
1044 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
1045 mContext);
1046 return 0;
1047 }
1048 default:
1049 onHelpThermalMitigation();
1050 }
1051
1052 return -1;
1053
1054 }
1055
Tyler Gunn92479152021-01-20 16:30:10 -08001056 private int handleD2dCommand() {
1057 String arg = getNextArg();
1058 if (arg == null) {
1059 onHelpD2D();
1060 return 0;
1061 }
1062
1063 switch (arg) {
1064 case D2D_SEND: {
1065 return handleD2dSendCommand();
1066 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001067 case D2D_TRANSPORT: {
1068 return handleD2dTransportCommand();
1069 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001070 case D2D_SET_DEVICE_SUPPORT: {
1071 return handleD2dDeviceSupportedCommand();
1072 }
Tyler Gunn92479152021-01-20 16:30:10 -08001073 }
1074
1075 return -1;
1076 }
1077
1078 private int handleD2dSendCommand() {
1079 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001080 int messageType = -1;
1081 int messageValue = -1;
1082
Tyler Gunn92479152021-01-20 16:30:10 -08001083 String arg = getNextArg();
1084 if (arg == null) {
1085 onHelpD2D();
1086 return 0;
1087 }
1088 try {
1089 messageType = Integer.parseInt(arg);
1090 } catch (NumberFormatException e) {
1091 errPw.println("message type must be a valid integer");
1092 return -1;
1093 }
1094
1095 arg = getNextArg();
1096 if (arg == null) {
1097 onHelpD2D();
1098 return 0;
1099 }
1100 try {
1101 messageValue = Integer.parseInt(arg);
1102 } catch (NumberFormatException e) {
1103 errPw.println("message value must be a valid integer");
1104 return -1;
1105 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001106
Tyler Gunn92479152021-01-20 16:30:10 -08001107 try {
1108 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1109 } catch (RemoteException e) {
1110 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1111 errPw.println("Exception: " + e.getMessage());
1112 return -1;
1113 }
1114
1115 return 0;
1116 }
1117
Tyler Gunnbabbda02021-02-10 11:05:02 -08001118 private int handleD2dTransportCommand() {
1119 PrintWriter errPw = getErrPrintWriter();
1120
1121 String arg = getNextArg();
1122 if (arg == null) {
1123 onHelpD2D();
1124 return 0;
1125 }
1126
1127 try {
1128 mInterface.setActiveDeviceToDeviceTransport(arg);
1129 } catch (RemoteException e) {
1130 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1131 errPw.println("Exception: " + e.getMessage());
1132 return -1;
1133 }
1134 return 0;
1135 }
Nazanin014f41e2021-05-06 17:26:31 -07001136 private int handleBarringCommand() {
1137 String arg = getNextArg();
1138 if (arg == null) {
1139 onHelpBarring();
1140 return 0;
1141 }
1142
1143 switch (arg) {
1144 case BARRING_SEND_INFO: {
1145 return handleBarringSendCommand();
1146 }
1147 }
1148 return -1;
1149 }
1150
1151 private int handleBarringSendCommand() {
1152 PrintWriter errPw = getErrPrintWriter();
1153 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001154 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001155 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1156 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1157 boolean isConditionallyBarred = false;
1158 int conditionalBarringTimeSeconds = 0;
1159
1160 String opt;
1161 while ((opt = getNextOption()) != null) {
1162 switch (opt) {
1163 case "-s": {
1164 try {
1165 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001166 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001167 } catch (NumberFormatException e) {
1168 errPw.println("barring send requires an integer as a SLOT_ID.");
1169 return -1;
1170 }
1171 break;
1172 }
1173 case "-b": {
1174 try {
1175 barringType = Integer.parseInt(getNextArgRequired());
1176 if (barringType < -1 || barringType > 2) {
1177 throw new NumberFormatException();
1178 }
1179
1180 } catch (NumberFormatException e) {
1181 errPw.println("barring send requires an integer in range [-1,2] as "
1182 + "a BARRING_TYPE.");
1183 return -1;
1184 }
1185 break;
1186 }
1187 case "-c": {
1188 try {
1189 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1190 } catch (Exception e) {
1191 errPw.println("barring send requires a boolean after -c indicating"
1192 + " conditional barring");
1193 return -1;
1194 }
1195 break;
1196 }
1197 case "-t": {
1198 try {
1199 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1200 } catch (NumberFormatException e) {
1201 errPw.println("barring send requires an integer for time of barring"
1202 + " in seconds after -t for conditional barring");
1203 return -1;
1204 }
1205 break;
1206 }
1207 }
1208 }
1209 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1210 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1211 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1212 barringServiceInfos.append(0, bsi);
1213 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1214 try {
1215 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1216 } catch (Exception e) {
1217 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1218 errPw.println("Exception: " + e.getMessage());
1219 return -1;
1220 }
1221 return 0;
1222 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001223
Tyler Gunnd4575212021-05-03 14:46:49 -07001224 private int handleD2dDeviceSupportedCommand() {
1225 PrintWriter errPw = getErrPrintWriter();
1226
1227 String arg = getNextArg();
1228 if (arg == null) {
1229 onHelpD2D();
1230 return 0;
1231 }
1232
Jack Yua533d632022-09-30 13:53:46 -07001233 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001234 try {
1235 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1236 } catch (RemoteException e) {
1237 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1238 errPw.println("Exception: " + e.getMessage());
1239 return -1;
1240 }
1241 return 0;
1242 }
1243
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001244 // ims set-ims-service
1245 private int handleImsSetServiceCommand() {
1246 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001247 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001248 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001249 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001250
1251 String opt;
1252 while ((opt = getNextOption()) != null) {
1253 switch (opt) {
1254 case "-s": {
1255 try {
1256 slotId = Integer.parseInt(getNextArgRequired());
1257 } catch (NumberFormatException e) {
1258 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1259 return -1;
1260 }
1261 break;
1262 }
1263 case "-c": {
1264 isCarrierService = true;
1265 break;
1266 }
1267 case "-d": {
1268 isCarrierService = false;
1269 break;
1270 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001271 case "-f": {
1272 String featureString = getNextArgRequired();
1273 String[] features = featureString.split(",");
1274 for (int i = 0; i < features.length; i++) {
1275 try {
1276 Integer result = Integer.parseInt(features[i]);
1277 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1278 || result >= ImsFeature.FEATURE_MAX) {
1279 errPw.println("ims set-ims-service -f " + result
1280 + " is an invalid feature.");
1281 return -1;
1282 }
1283 featuresList.add(result);
1284 } catch (NumberFormatException e) {
1285 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1286 + " as an integer.");
1287 return -1;
1288 }
1289 }
1290 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001291 }
1292 }
1293 // Mandatory param, either -c or -d
1294 if (isCarrierService == null) {
1295 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1296 return -1;
1297 }
1298
1299 String packageName = getNextArg();
1300
1301 try {
1302 if (packageName == null) {
1303 packageName = "";
1304 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001305 int[] featureArray = new int[featuresList.size()];
1306 for (int i = 0; i < featuresList.size(); i++) {
1307 featureArray[i] = featuresList.get(i);
1308 }
1309 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1310 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001311 if (VDBG) {
1312 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001313 + (isCarrierService ? "-c " : "-d ")
1314 + "-f " + featuresList + " "
1315 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001316 }
1317 getOutPrintWriter().println(result);
1318 } catch (RemoteException e) {
1319 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001320 + (isCarrierService ? "-c " : "-d ")
1321 + "-f " + featuresList + " "
1322 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001323 errPw.println("Exception: " + e.getMessage());
1324 return -1;
1325 }
1326 return 0;
1327 }
1328
Brad Ebinger999d3302020-11-25 14:31:39 -08001329 // ims clear-ims-service-override
1330 private int handleImsClearCarrierServiceCommand() {
1331 PrintWriter errPw = getErrPrintWriter();
1332 int slotId = getDefaultSlot();
1333
1334 String opt;
1335 while ((opt = getNextOption()) != null) {
1336 switch (opt) {
1337 case "-s": {
1338 try {
1339 slotId = Integer.parseInt(getNextArgRequired());
1340 } catch (NumberFormatException e) {
1341 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1342 return -1;
1343 }
1344 break;
1345 }
1346 }
1347 }
1348
1349 try {
1350 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1351 if (VDBG) {
1352 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1353 + ", result=" + result);
1354 }
1355 getOutPrintWriter().println(result);
1356 } catch (RemoteException e) {
1357 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1358 + ", error" + e.getMessage());
1359 errPw.println("Exception: " + e.getMessage());
1360 return -1;
1361 }
1362 return 0;
1363 }
1364
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001365 // ims get-ims-service
1366 private int handleImsGetServiceCommand() {
1367 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001368 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001369 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001370 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001371
1372 String opt;
1373 while ((opt = getNextOption()) != null) {
1374 switch (opt) {
1375 case "-s": {
1376 try {
1377 slotId = Integer.parseInt(getNextArgRequired());
1378 } catch (NumberFormatException e) {
1379 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1380 return -1;
1381 }
1382 break;
1383 }
1384 case "-c": {
1385 isCarrierService = true;
1386 break;
1387 }
1388 case "-d": {
1389 isCarrierService = false;
1390 break;
1391 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001392 case "-f": {
1393 try {
1394 featureType = Integer.parseInt(getNextArg());
1395 } catch (NumberFormatException e) {
1396 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1397 return -1;
1398 }
1399 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1400 || featureType >= ImsFeature.FEATURE_MAX) {
1401 errPw.println("ims get-ims-service -f invalid feature.");
1402 return -1;
1403 }
1404 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001405 }
1406 }
1407 // Mandatory param, either -c or -d
1408 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001409 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001410 return -1;
1411 }
1412
1413 String result;
1414 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001415 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001416 } catch (RemoteException e) {
1417 return -1;
1418 }
1419 if (VDBG) {
1420 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001421 + (isCarrierService ? "-c " : "-d ")
1422 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1423 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001424 }
1425 getOutPrintWriter().println(result);
1426 return 0;
1427 }
1428
1429 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001430 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001431 String opt;
1432 while ((opt = getNextOption()) != null) {
1433 switch (opt) {
1434 case "-s": {
1435 try {
1436 slotId = Integer.parseInt(getNextArgRequired());
1437 } catch (NumberFormatException e) {
1438 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1439 return -1;
1440 }
1441 break;
1442 }
1443 }
1444 }
1445 try {
1446 mInterface.enableIms(slotId);
1447 } catch (RemoteException e) {
1448 return -1;
1449 }
1450 if (VDBG) {
1451 Log.v(LOG_TAG, "ims enable -s " + slotId);
1452 }
1453 return 0;
1454 }
1455
1456 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001457 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001458 String opt;
1459 while ((opt = getNextOption()) != null) {
1460 switch (opt) {
1461 case "-s": {
1462 try {
1463 slotId = Integer.parseInt(getNextArgRequired());
1464 } catch (NumberFormatException e) {
1465 getErrPrintWriter().println(
1466 "ims disable requires an integer as a SLOT_ID.");
1467 return -1;
1468 }
1469 break;
1470 }
1471 }
1472 }
1473 try {
1474 mInterface.disableIms(slotId);
1475 } catch (RemoteException e) {
1476 return -1;
1477 }
1478 if (VDBG) {
1479 Log.v(LOG_TAG, "ims disable -s " + slotId);
1480 }
1481 return 0;
1482 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001483
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001484 private int handleCepChange() {
1485 Log.i(LOG_TAG, "handleCepChange");
1486 String opt = getNextArg();
1487 if (opt == null) {
1488 return -1;
1489 }
1490 boolean isCepEnabled = opt.equals("enable");
1491
1492 try {
1493 mInterface.setCepEnabled(isCepEnabled);
1494 } catch (RemoteException e) {
1495 return -1;
1496 }
1497 return 0;
1498 }
1499
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001500 private int getDefaultSlot() {
1501 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1502 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1503 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1504 // If there is no default, default to slot 0.
1505 slotId = DEFAULT_PHONE_ID;
1506 }
1507 return slotId;
1508 }
sqian2fff4a32018-11-05 14:18:37 -08001509
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001510 // Parse options related to Carrier Config Commands.
1511 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001512 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001513 CcOptionParseResult result = new CcOptionParseResult();
1514 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1515 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001516
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001517 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001518 while ((opt = getNextOption()) != null) {
1519 switch (opt) {
1520 case "-s": {
1521 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001522 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1523 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1524 errPw.println(tag + "No valid subscription found.");
1525 return null;
1526 }
1527
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001528 } catch (IllegalArgumentException e) {
1529 // Missing slot id
1530 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001531 return null;
1532 }
1533 break;
1534 }
1535 case "-p": {
1536 if (allowOptionPersistent) {
1537 result.mPersistent = true;
1538 } else {
1539 errPw.println(tag + "Unexpected option " + opt);
1540 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001541 }
1542 break;
1543 }
1544 default: {
1545 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001546 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001547 }
1548 }
1549 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001550 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001551 }
1552
1553 private int slotStringToSubId(String tag, String slotString) {
1554 int slotId = -1;
1555 try {
1556 slotId = Integer.parseInt(slotString);
1557 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001558 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1559 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1560 }
1561
1562 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001563 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1564 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1565 }
1566
Qiong Liuf25799b2020-09-10 10:13:46 +08001567 Phone phone = PhoneFactory.getPhone(slotId);
1568 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001569 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1570 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1571 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001572 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001573 }
1574
Hall Liud892bec2018-11-30 14:51:45 -08001575 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001576 // adb can run as root or as shell, depending on whether the device is rooted.
1577 return Binder.getCallingUid() == Process.SHELL_UID
1578 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001579 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001580
1581 private int handleCcCommand() {
1582 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1583 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001584 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001585 getErrPrintWriter().println("cc: Permission denied.");
1586 return -1;
1587 }
1588
1589 String arg = getNextArg();
1590 if (arg == null) {
1591 onHelpCc();
1592 return 0;
1593 }
1594
1595 switch (arg) {
1596 case CC_GET_VALUE: {
1597 return handleCcGetValue();
1598 }
1599 case CC_SET_VALUE: {
1600 return handleCcSetValue();
1601 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001602 case CC_SET_VALUES_FROM_XML: {
1603 return handleCcSetValuesFromXml();
1604 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001605 case CC_CLEAR_VALUES: {
1606 return handleCcClearValues();
1607 }
1608 default: {
1609 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1610 }
1611 }
1612 return -1;
1613 }
1614
1615 // cc get-value
1616 private int handleCcGetValue() {
1617 PrintWriter errPw = getErrPrintWriter();
1618 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1619 String key = null;
1620
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001621 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001622 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001623 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001624 return -1;
1625 }
1626
1627 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001628 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001629 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001630 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001631 return -1;
1632 }
1633
1634 // Get the key.
1635 key = getNextArg();
1636 if (key != null) {
1637 // A key was provided. Verify if it is a valid key
1638 if (!bundle.containsKey(key)) {
1639 errPw.println(tag + key + " is not a valid key.");
1640 return -1;
1641 }
1642
1643 // Print the carrier config value for key.
1644 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1645 } else {
1646 // No key provided. Show all values.
1647 // Iterate over a sorted list of all carrier config keys and print them.
1648 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1649 for (String k : sortedSet) {
1650 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1651 }
1652 }
1653 return 0;
1654 }
1655
1656 // cc set-value
1657 private int handleCcSetValue() {
1658 PrintWriter errPw = getErrPrintWriter();
1659 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1660
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001661 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001662 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001663 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001664 return -1;
1665 }
1666
1667 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001668 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001669 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001670 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001671 return -1;
1672 }
1673
1674 // Get the key.
1675 String key = getNextArg();
1676 if (key == null || key.equals("")) {
1677 errPw.println(tag + "KEY is missing");
1678 return -1;
1679 }
1680
1681 // Verify if the key is valid
1682 if (!originalValues.containsKey(key)) {
1683 errPw.println(tag + key + " is not a valid key.");
1684 return -1;
1685 }
1686
1687 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1688 ArrayList<String> valueList = new ArrayList<String>();
1689 while (peekNextArg() != null) {
1690 valueList.add(getNextArg());
1691 }
1692
1693 // Find the type of the carrier config value
1694 CcType type = getType(tag, key, originalValues);
1695 if (type == CcType.UNKNOWN) {
1696 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1697 return -1;
1698 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001699 if (type == CcType.PERSISTABLE_BUNDLE) {
1700 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1701 + "Use set-values-from-xml instead.");
1702 return -1;
1703 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001704
1705 // Create an override bundle containing the key and value that should be overriden.
1706 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1707 if (overrideBundle == null) {
1708 return -1;
1709 }
1710
1711 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001712 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001713
1714 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001715 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001716 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001717 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001718 return -1;
1719 }
1720
1721 // Print the original and new value.
1722 String originalValueString = ccValueToString(key, type, originalValues);
1723 String newValueString = ccValueToString(key, type, newValues);
1724 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1725 getOutPrintWriter().println("New value: \n" + newValueString);
1726
1727 return 0;
1728 }
1729
Allen Xuee00f0e2022-03-14 21:04:49 +00001730 // cc set-values-from-xml
1731 private int handleCcSetValuesFromXml() {
1732 PrintWriter errPw = getErrPrintWriter();
1733 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1734
1735 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001736 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001737 if (options == null) {
1738 return -1;
1739 }
1740
1741 // Get bundle containing all current carrier configuration values.
1742 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1743 if (originalValues == null) {
1744 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1745 return -1;
1746 }
1747
1748 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1749 if (overrideBundle == null) {
1750 return -1;
1751 }
1752
1753 // Verify all values are valid types
1754 for (String key : overrideBundle.keySet()) {
1755 CcType type = getType(tag, key, originalValues);
1756 if (type == CcType.UNKNOWN) {
1757 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1758 return -1;
1759 }
1760 }
1761
1762 // Override the value
1763 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1764
1765 // Find bundle containing all new carrier configuration values after the override.
1766 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1767 if (newValues == null) {
1768 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1769 return -1;
1770 }
1771
1772 // Print the original and new values
1773 overrideBundle.keySet().forEach(key -> {
1774 CcType type = getType(tag, key, originalValues);
1775 String originalValueString = ccValueToString(key, type, originalValues);
1776 String newValueString = ccValueToString(key, type, newValues);
1777 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1778 getOutPrintWriter().println("New value: \n" + newValueString);
1779 });
1780
1781 return 0;
1782 }
1783
1784 private PersistableBundle readPersistableBundleFromXml(String tag) {
1785 PersistableBundle subIdBundles;
1786 try {
1787 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1788 } catch (IOException | RuntimeException e) {
1789 PrintWriter errPw = getErrPrintWriter();
1790 errPw.println(tag + e);
1791 return null;
1792 }
1793
1794 return subIdBundles;
1795 }
1796
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001797 // cc clear-values
1798 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001799 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1800
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001801 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001802 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001803 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001804 return -1;
1805 }
1806
1807 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001808 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001809 getOutPrintWriter()
1810 .println("All previously set carrier config override values has been cleared");
1811 return 0;
1812 }
1813
1814 private CcType getType(String tag, String key, PersistableBundle bundle) {
1815 // Find the type by checking the type of the current value stored in the bundle.
1816 Object value = bundle.get(key);
1817
1818 if (CC_TYPE_MAP.containsKey(key)) {
1819 return CC_TYPE_MAP.get(key);
1820 } else if (value != null) {
1821 if (value instanceof Boolean) {
1822 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001823 }
1824 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001825 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001826 }
1827 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001828 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001829 }
1830 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001831 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001832 }
1833 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001834 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001835 }
1836 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001837 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001838 }
1839 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001840 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001841 }
1842 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001843 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001844 }
1845 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001846 return CcType.STRING_ARRAY;
1847 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001848 if (value instanceof PersistableBundle) {
1849 return CcType.PERSISTABLE_BUNDLE;
1850 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001851 } else {
1852 // Current value was null and can therefore not be used in order to find the type.
1853 // Check the name of the key to infer the type. This check is not needed for primitive
1854 // data types (boolean, double, int and long), since they can not be null.
1855 if (key.endsWith("double_array")) {
1856 return CcType.DOUBLE_ARRAY;
1857 }
1858 if (key.endsWith("int_array")) {
1859 return CcType.INT_ARRAY;
1860 }
1861 if (key.endsWith("long_array")) {
1862 return CcType.LONG_ARRAY;
1863 }
1864 if (key.endsWith("string")) {
1865 return CcType.STRING;
1866 }
1867 if (key.endsWith("string_array") || key.endsWith("strings")) {
1868 return CcType.STRING_ARRAY;
1869 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001870 if (key.endsWith("bundle")) {
1871 return CcType.PERSISTABLE_BUNDLE;
1872 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001873 }
1874
1875 // Not possible to infer the type by looking at the current value or the key.
1876 PrintWriter errPw = getErrPrintWriter();
1877 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1878 return CcType.UNKNOWN;
1879 }
1880
1881 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1882 String result;
1883 StringBuilder valueString = new StringBuilder();
1884 String typeString = type.toString();
1885 Object value = bundle.get(key);
1886
1887 if (value == null) {
1888 valueString.append("null");
1889 } else {
1890 switch (type) {
1891 case DOUBLE_ARRAY: {
1892 // Format the string representation of the int array as value1 value2......
1893 double[] valueArray = (double[]) value;
1894 for (int i = 0; i < valueArray.length; i++) {
1895 if (i != 0) {
1896 valueString.append(" ");
1897 }
1898 valueString.append(valueArray[i]);
1899 }
1900 break;
1901 }
1902 case INT_ARRAY: {
1903 // Format the string representation of the int array as value1 value2......
1904 int[] valueArray = (int[]) value;
1905 for (int i = 0; i < valueArray.length; i++) {
1906 if (i != 0) {
1907 valueString.append(" ");
1908 }
1909 valueString.append(valueArray[i]);
1910 }
1911 break;
1912 }
1913 case LONG_ARRAY: {
1914 // Format the string representation of the int array as value1 value2......
1915 long[] valueArray = (long[]) value;
1916 for (int i = 0; i < valueArray.length; i++) {
1917 if (i != 0) {
1918 valueString.append(" ");
1919 }
1920 valueString.append(valueArray[i]);
1921 }
1922 break;
1923 }
1924 case STRING: {
1925 valueString.append("\"" + value.toString() + "\"");
1926 break;
1927 }
1928 case STRING_ARRAY: {
1929 // Format the string representation of the string array as "value1" "value2"....
1930 String[] valueArray = (String[]) value;
1931 for (int i = 0; i < valueArray.length; i++) {
1932 if (i != 0) {
1933 valueString.append(" ");
1934 }
1935 if (valueArray[i] != null) {
1936 valueString.append("\"" + valueArray[i] + "\"");
1937 } else {
1938 valueString.append("null");
1939 }
1940 }
1941 break;
1942 }
1943 default: {
1944 valueString.append(value.toString());
1945 }
1946 }
1947 }
1948 return String.format("%-70s %-15s %s", key, typeString, valueString);
1949 }
1950
1951 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1952 ArrayList<String> valueList) {
1953 PrintWriter errPw = getErrPrintWriter();
1954 PersistableBundle bundle = new PersistableBundle();
1955
1956 // First verify that a valid number of values has been provided for the type.
1957 switch (type) {
1958 case BOOLEAN:
1959 case DOUBLE:
1960 case INT:
1961 case LONG: {
1962 if (valueList.size() != 1) {
1963 errPw.println(tag + "Expected 1 value for type " + type
1964 + ". Found: " + valueList.size());
1965 return null;
1966 }
1967 break;
1968 }
1969 case STRING: {
1970 if (valueList.size() > 1) {
1971 errPw.println(tag + "Expected 0 or 1 values for type " + type
1972 + ". Found: " + valueList.size());
1973 return null;
1974 }
1975 break;
1976 }
1977 }
1978
1979 // Parse the value according to type and add it to the Bundle.
1980 switch (type) {
1981 case BOOLEAN: {
1982 if ("true".equalsIgnoreCase(valueList.get(0))) {
1983 bundle.putBoolean(key, true);
1984 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1985 bundle.putBoolean(key, false);
1986 } else {
1987 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1988 return null;
1989 }
1990 break;
1991 }
1992 case DOUBLE: {
1993 try {
1994 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1995 } catch (NumberFormatException nfe) {
1996 // Not a valid double
1997 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1998 return null;
1999 }
2000 break;
2001 }
2002 case DOUBLE_ARRAY: {
2003 double[] valueDoubleArray = null;
2004 if (valueList.size() > 0) {
2005 valueDoubleArray = new double[valueList.size()];
2006 for (int i = 0; i < valueList.size(); i++) {
2007 try {
2008 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
2009 } catch (NumberFormatException nfe) {
2010 // Not a valid double
2011 errPw.println(
2012 tag + "Unable to parse " + valueList.get(i) + " as a double.");
2013 return null;
2014 }
2015 }
2016 }
2017 bundle.putDoubleArray(key, valueDoubleArray);
2018 break;
2019 }
2020 case INT: {
2021 try {
2022 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
2023 } catch (NumberFormatException nfe) {
2024 // Not a valid integer
2025 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
2026 return null;
2027 }
2028 break;
2029 }
2030 case INT_ARRAY: {
2031 int[] valueIntArray = null;
2032 if (valueList.size() > 0) {
2033 valueIntArray = new int[valueList.size()];
2034 for (int i = 0; i < valueList.size(); i++) {
2035 try {
2036 valueIntArray[i] = Integer.parseInt(valueList.get(i));
2037 } catch (NumberFormatException nfe) {
2038 // Not a valid integer
2039 errPw.println(tag
2040 + "Unable to parse " + valueList.get(i) + " as an integer.");
2041 return null;
2042 }
2043 }
2044 }
2045 bundle.putIntArray(key, valueIntArray);
2046 break;
2047 }
2048 case LONG: {
2049 try {
2050 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2051 } catch (NumberFormatException nfe) {
2052 // Not a valid long
2053 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2054 return null;
2055 }
2056 break;
2057 }
2058 case LONG_ARRAY: {
2059 long[] valueLongArray = null;
2060 if (valueList.size() > 0) {
2061 valueLongArray = new long[valueList.size()];
2062 for (int i = 0; i < valueList.size(); i++) {
2063 try {
2064 valueLongArray[i] = Long.parseLong(valueList.get(i));
2065 } catch (NumberFormatException nfe) {
2066 // Not a valid long
2067 errPw.println(
2068 tag + "Unable to parse " + valueList.get(i) + " as a long");
2069 return null;
2070 }
2071 }
2072 }
2073 bundle.putLongArray(key, valueLongArray);
2074 break;
2075 }
2076 case STRING: {
2077 String value = null;
2078 if (valueList.size() > 0) {
2079 value = valueList.get(0);
2080 }
2081 bundle.putString(key, value);
2082 break;
2083 }
2084 case STRING_ARRAY: {
2085 String[] valueStringArray = null;
2086 if (valueList.size() > 0) {
2087 valueStringArray = new String[valueList.size()];
2088 valueList.toArray(valueStringArray);
2089 }
2090 bundle.putStringArray(key, valueStringArray);
2091 break;
2092 }
2093 }
2094 return bundle;
2095 }
Shuo Qian489d9282020-07-09 11:30:03 -07002096
2097 private int handleEndBlockSuppressionCommand() {
2098 if (!checkShellUid()) {
2099 return -1;
2100 }
2101
2102 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2103 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2104 }
2105 return 0;
2106 }
Hui Wang641e81c2020-10-12 12:14:23 -07002107
Shivakumar Neginal9cd61892022-12-19 04:38:52 +00002108 private int handleEuiccCommand() {
2109 String arg = getNextArg();
2110 if (arg == null) {
2111 onHelpEuicc();
2112 return 0;
2113 }
2114
2115 switch (arg) {
2116 case EUICC_SET_UI_COMPONENT: {
2117 return handleEuiccServiceCommand();
2118 }
2119 }
2120 return -1;
2121 }
2122
2123 private int handleEuiccServiceCommand() {
2124 String uiComponent = getNextArg();
2125 String packageName = getNextArg();
2126 if (packageName == null || uiComponent == null) {
2127 return -1;
2128 }
2129 EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
2130 if (VDBG) {
2131 Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
2132 + packageName);
2133 }
2134 return 0;
2135 }
2136
Michele Berionne54af4632020-12-28 20:23:16 +00002137 private int handleRestartModemCommand() {
2138 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2139 // non user build.
2140 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2141 getErrPrintWriter().println("RestartModem: Permission denied.");
2142 return -1;
2143 }
2144
2145 boolean result = TelephonyManager.getDefault().rebootRadio();
2146 getOutPrintWriter().println(result);
2147
2148 return result ? 0 : -1;
2149 }
2150
Ling Ma4fbab492022-01-25 22:36:16 +00002151 private int handleGetImei() {
2152 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2153 // non user build.
2154 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2155 getErrPrintWriter().println("Device IMEI: Permission denied.");
2156 return -1;
2157 }
2158
2159 final long identity = Binder.clearCallingIdentity();
2160
2161 String imei = null;
2162 String arg = getNextArg();
2163 if (arg != null) {
2164 try {
2165 int specifiedSlotIndex = Integer.parseInt(arg);
2166 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2167 } catch (NumberFormatException exception) {
2168 PrintWriter errPw = getErrPrintWriter();
2169 errPw.println("-s requires an integer as slot index.");
2170 return -1;
2171 }
2172
2173 } else {
2174 imei = TelephonyManager.from(mContext).getImei();
2175 }
2176 getOutPrintWriter().println("Device IMEI: " + imei);
2177
2178 Binder.restoreCallingIdentity(identity);
2179 return 0;
2180 }
2181
Michele Berionne5e411512020-11-13 02:36:59 +00002182 private int handleUnattendedReboot() {
2183 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2184 // non user build.
2185 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2186 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2187 return -1;
2188 }
2189
2190 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2191 getOutPrintWriter().println("result: " + result);
2192
2193 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2194 }
2195
Aman Gupta07124872022-02-09 08:02:14 +00002196 private int handleGetSimSlotsMapping() {
2197 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2198 // non user build.
2199 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2200 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2201 return -1;
2202 }
2203 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2204 String result = telephonyManager.getSimSlotMapping().toString();
2205 getOutPrintWriter().println("simSlotsMapping: " + result);
2206
2207 return 0;
2208 }
2209
Hui Wang641e81c2020-10-12 12:14:23 -07002210 private int handleGbaCommand() {
2211 String arg = getNextArg();
2212 if (arg == null) {
2213 onHelpGba();
2214 return 0;
2215 }
2216
2217 switch (arg) {
2218 case GBA_SET_SERVICE: {
2219 return handleGbaSetServiceCommand();
2220 }
2221 case GBA_GET_SERVICE: {
2222 return handleGbaGetServiceCommand();
2223 }
2224 case GBA_SET_RELEASE_TIME: {
2225 return handleGbaSetReleaseCommand();
2226 }
2227 case GBA_GET_RELEASE_TIME: {
2228 return handleGbaGetReleaseCommand();
2229 }
2230 }
2231
2232 return -1;
2233 }
2234
2235 private int getSubId(String cmd) {
2236 int slotId = getDefaultSlot();
2237 String opt = getNextOption();
2238 if (opt != null && opt.equals("-s")) {
2239 try {
2240 slotId = Integer.parseInt(getNextArgRequired());
2241 } catch (NumberFormatException e) {
2242 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2243 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2244 }
2245 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002246 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002247 }
2248
2249 private int handleGbaSetServiceCommand() {
2250 int subId = getSubId("gba set-service");
2251 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2252 return -1;
2253 }
2254
2255 String packageName = getNextArg();
2256 try {
2257 if (packageName == null) {
2258 packageName = "";
2259 }
2260 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2261 if (VDBG) {
2262 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2263 + packageName + ", result=" + result);
2264 }
2265 getOutPrintWriter().println(result);
2266 } catch (RemoteException e) {
2267 Log.w(LOG_TAG, "gba set-service " + subId + " "
2268 + packageName + ", error" + e.getMessage());
2269 getErrPrintWriter().println("Exception: " + e.getMessage());
2270 return -1;
2271 }
2272 return 0;
2273 }
2274
2275 private int handleGbaGetServiceCommand() {
2276 String result;
2277
2278 int subId = getSubId("gba get-service");
2279 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2280 return -1;
2281 }
2282
2283 try {
2284 result = mInterface.getBoundGbaService(subId);
2285 } catch (RemoteException e) {
2286 return -1;
2287 }
2288 if (VDBG) {
2289 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2290 }
2291 getOutPrintWriter().println(result);
2292 return 0;
2293 }
2294
2295 private int handleGbaSetReleaseCommand() {
2296 //the release time value could be -1
2297 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2298 : SubscriptionManager.getDefaultSubscriptionId();
2299 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2300 return -1;
2301 }
2302
2303 String intervalStr = getNextArg();
2304 if (intervalStr == null) {
2305 return -1;
2306 }
2307
2308 try {
2309 int interval = Integer.parseInt(intervalStr);
2310 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2311 if (VDBG) {
2312 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2313 + intervalStr + ", result=" + result);
2314 }
2315 getOutPrintWriter().println(result);
2316 } catch (NumberFormatException | RemoteException e) {
2317 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2318 + intervalStr + ", error" + e.getMessage());
2319 getErrPrintWriter().println("Exception: " + e.getMessage());
2320 return -1;
2321 }
2322 return 0;
2323 }
2324
2325 private int handleGbaGetReleaseCommand() {
2326 int subId = getSubId("gba get-release");
2327 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2328 return -1;
2329 }
2330
2331 int result = 0;
2332 try {
2333 result = mInterface.getGbaReleaseTime(subId);
2334 } catch (RemoteException e) {
2335 return -1;
2336 }
2337 if (VDBG) {
2338 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2339 }
2340 getOutPrintWriter().println(result);
2341 return 0;
2342 }
Hui Wang761a6682020-10-31 05:12:53 +00002343
2344 private int handleSingleRegistrationConfigCommand() {
2345 String arg = getNextArg();
2346 if (arg == null) {
2347 onHelpSrc();
2348 return 0;
2349 }
2350
2351 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002352 case SRC_SET_TEST_ENABLED: {
2353 return handleSrcSetTestEnabledCommand();
2354 }
2355 case SRC_GET_TEST_ENABLED: {
2356 return handleSrcGetTestEnabledCommand();
2357 }
Hui Wang761a6682020-10-31 05:12:53 +00002358 case SRC_SET_DEVICE_ENABLED: {
2359 return handleSrcSetDeviceEnabledCommand();
2360 }
2361 case SRC_GET_DEVICE_ENABLED: {
2362 return handleSrcGetDeviceEnabledCommand();
2363 }
2364 case SRC_SET_CARRIER_ENABLED: {
2365 return handleSrcSetCarrierEnabledCommand();
2366 }
2367 case SRC_GET_CARRIER_ENABLED: {
2368 return handleSrcGetCarrierEnabledCommand();
2369 }
Hui Wangb647abe2021-02-26 09:33:38 -08002370 case SRC_SET_FEATURE_ENABLED: {
2371 return handleSrcSetFeatureValidationCommand();
2372 }
2373 case SRC_GET_FEATURE_ENABLED: {
2374 return handleSrcGetFeatureValidationCommand();
2375 }
Hui Wang761a6682020-10-31 05:12:53 +00002376 }
2377
2378 return -1;
2379 }
2380
James.cf Linbcdf8b32021-01-14 16:44:13 +08002381 private int handleRcsUceCommand() {
2382 String arg = getNextArg();
2383 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002384 onHelpUce();
2385 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002386 }
2387
2388 switch (arg) {
2389 case UCE_REMOVE_EAB_CONTACT:
2390 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002391 case UCE_GET_EAB_CONTACT:
2392 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002393 case UCE_GET_EAB_CAPABILITY:
2394 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002395 case UCE_GET_DEVICE_ENABLED:
2396 return handleUceGetDeviceEnabledCommand();
2397 case UCE_SET_DEVICE_ENABLED:
2398 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002399 case UCE_OVERRIDE_PUBLISH_CAPS:
2400 return handleUceOverridePublishCaps();
2401 case UCE_GET_LAST_PIDF_XML:
2402 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002403 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2404 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002405 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2406 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002407 }
2408 return -1;
2409 }
2410
2411 private int handleRemovingEabContactCommand() {
2412 int subId = getSubId("uce remove-eab-contact");
2413 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2414 return -1;
2415 }
2416
2417 String phoneNumber = getNextArgRequired();
2418 if (TextUtils.isEmpty(phoneNumber)) {
2419 return -1;
2420 }
2421 int result = 0;
2422 try {
2423 result = mInterface.removeContactFromEab(subId, phoneNumber);
2424 } catch (RemoteException e) {
2425 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2426 getErrPrintWriter().println("Exception: " + e.getMessage());
2427 return -1;
2428 }
2429
2430 if (VDBG) {
2431 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2432 }
calvinpan293ea1b2021-02-04 17:52:13 +08002433 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002434 }
2435
calvinpane4a8a1d2021-01-25 13:51:18 +08002436 private int handleGettingEabContactCommand() {
2437 String phoneNumber = getNextArgRequired();
2438 if (TextUtils.isEmpty(phoneNumber)) {
2439 return -1;
2440 }
2441 String result = "";
2442 try {
2443 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002444 } catch (RemoteException e) {
2445 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2446 getErrPrintWriter().println("Exception: " + e.getMessage());
2447 return -1;
2448 }
2449
2450 if (VDBG) {
2451 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2452 }
calvinpan293ea1b2021-02-04 17:52:13 +08002453 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002454 return 0;
2455 }
2456
Calvin Pana1434322021-07-01 19:27:01 +08002457 private int handleGettingEabCapabilityCommand() {
2458 String phoneNumber = getNextArgRequired();
2459 if (TextUtils.isEmpty(phoneNumber)) {
2460 return -1;
2461 }
2462 String result = "";
2463 try {
2464 result = mInterface.getCapabilityFromEab(phoneNumber);
2465 } catch (RemoteException e) {
2466 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2467 getErrPrintWriter().println("Exception: " + e.getMessage());
2468 return -1;
2469 }
2470
2471 if (VDBG) {
2472 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2473 }
2474 getOutPrintWriter().println(result);
2475 return 0;
2476 }
2477
James.cf Lin4b784aa2021-01-31 03:25:15 +08002478 private int handleUceGetDeviceEnabledCommand() {
2479 boolean result = false;
2480 try {
2481 result = mInterface.getDeviceUceEnabled();
2482 } catch (RemoteException e) {
2483 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2484 return -1;
2485 }
2486 if (VDBG) {
2487 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2488 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002489 getOutPrintWriter().println(result);
2490 return 0;
2491 }
2492
James.cf Lin4b784aa2021-01-31 03:25:15 +08002493 private int handleUceSetDeviceEnabledCommand() {
2494 String enabledStr = getNextArg();
2495 if (TextUtils.isEmpty(enabledStr)) {
2496 return -1;
2497 }
2498
2499 try {
2500 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2501 mInterface.setDeviceUceEnabled(isEnabled);
2502 if (VDBG) {
2503 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2504 }
2505 } catch (NumberFormatException | RemoteException e) {
2506 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2507 getErrPrintWriter().println("Exception: " + e.getMessage());
2508 return -1;
2509 }
2510 return 0;
2511 }
2512
James.cf Line8713a42021-04-29 16:04:26 +08002513 private int handleUceRemoveRequestDisallowedStatus() {
2514 int subId = getSubId("uce remove-request-disallowed-status");
2515 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2516 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2517 return -1;
2518 }
2519 boolean result;
2520 try {
2521 result = mInterface.removeUceRequestDisallowedStatus(subId);
2522 } catch (RemoteException e) {
2523 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2524 return -1;
2525 }
2526 if (VDBG) {
2527 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2528 }
2529 getOutPrintWriter().println(result);
2530 return 0;
2531 }
2532
James.cf Lin0fc71b02021-05-25 01:37:38 +08002533 private int handleUceSetCapRequestTimeout() {
2534 int subId = getSubId("uce set-capabilities-request-timeout");
2535 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2536 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2537 return -1;
2538 }
2539 long timeoutAfterMs = Long.valueOf(getNextArg());
2540 boolean result;
2541 try {
2542 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2543 } catch (RemoteException e) {
2544 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2545 return -1;
2546 }
2547 if (VDBG) {
2548 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2549 }
2550 getOutPrintWriter().println(result);
2551 return 0;
2552 }
2553
Hui Wangbaaee6a2021-02-19 20:45:36 -08002554 private int handleSrcSetTestEnabledCommand() {
2555 String enabledStr = getNextArg();
2556 if (enabledStr == null) {
2557 return -1;
2558 }
2559
2560 try {
2561 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2562 if (VDBG) {
2563 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2564 }
2565 getOutPrintWriter().println("Done");
2566 } catch (NumberFormatException | RemoteException e) {
2567 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2568 getErrPrintWriter().println("Exception: " + e.getMessage());
2569 return -1;
2570 }
2571 return 0;
2572 }
2573
2574 private int handleSrcGetTestEnabledCommand() {
2575 boolean result = false;
2576 try {
2577 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2578 } catch (RemoteException e) {
2579 return -1;
2580 }
2581 if (VDBG) {
2582 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2583 }
2584 getOutPrintWriter().println(result);
2585 return 0;
2586 }
2587
Brad Ebinger14d467f2021-02-12 06:18:28 +00002588 private int handleUceOverridePublishCaps() {
2589 int subId = getSubId("uce override-published-caps");
2590 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2591 return -1;
2592 }
2593 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2594 String operation = getNextArgRequired();
2595 String caps = getNextArg();
2596 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2597 && !"list".equals(operation)) {
2598 getErrPrintWriter().println("Invalid operation: " + operation);
2599 return -1;
2600 }
2601
2602 // add/remove requires capabilities to be specified.
2603 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2604 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2605 + "specified");
2606 return -1;
2607 }
2608
2609 ArraySet<String> capSet = new ArraySet<>();
2610 if (!TextUtils.isEmpty(caps)) {
2611 String[] capArray = caps.split(":");
2612 for (String cap : capArray) {
2613 // Allow unknown tags to be passed in as well.
2614 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2615 }
2616 }
2617
2618 RcsContactUceCapability result = null;
2619 try {
2620 switch (operation) {
2621 case "add":
2622 result = mInterface.addUceRegistrationOverrideShell(subId,
2623 new ArrayList<>(capSet));
2624 break;
2625 case "remove":
2626 result = mInterface.removeUceRegistrationOverrideShell(subId,
2627 new ArrayList<>(capSet));
2628 break;
2629 case "clear":
2630 result = mInterface.clearUceRegistrationOverrideShell(subId);
2631 break;
2632 case "list":
2633 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2634 break;
2635 }
2636 } catch (RemoteException e) {
2637 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2638 getErrPrintWriter().println("Exception: " + e.getMessage());
2639 return -1;
2640 } catch (ServiceSpecificException sse) {
2641 // Reconstruct ImsException
2642 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2643 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2644 getErrPrintWriter().println("Exception: " + imsException);
2645 return -1;
2646 }
2647 if (result == null) {
2648 getErrPrintWriter().println("Service not available");
2649 return -1;
2650 }
2651 getOutPrintWriter().println(result);
2652 return 0;
2653 }
2654
2655 private int handleUceGetPidfXml() {
2656 int subId = getSubId("uce get-last-publish-pidf");
2657 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2658 return -1;
2659 }
2660
2661 String result;
2662 try {
2663 result = mInterface.getLastUcePidfXmlShell(subId);
2664 } catch (RemoteException e) {
2665 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2666 getErrPrintWriter().println("Exception: " + e.getMessage());
2667 return -1;
2668 } catch (ServiceSpecificException sse) {
2669 // Reconstruct ImsException
2670 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2671 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2672 getErrPrintWriter().println("Exception: " + imsException);
2673 return -1;
2674 }
2675 if (result == null) {
2676 getErrPrintWriter().println("Service not available");
2677 return -1;
2678 }
2679 getOutPrintWriter().println(result);
2680 return 0;
2681 }
2682
Hui Wang761a6682020-10-31 05:12:53 +00002683 private int handleSrcSetDeviceEnabledCommand() {
2684 String enabledStr = getNextArg();
2685 if (enabledStr == null) {
2686 return -1;
2687 }
2688
2689 try {
2690 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2691 if (VDBG) {
2692 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2693 }
2694 getOutPrintWriter().println("Done");
2695 } catch (NumberFormatException | RemoteException e) {
2696 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2697 getErrPrintWriter().println("Exception: " + e.getMessage());
2698 return -1;
2699 }
2700 return 0;
2701 }
2702
2703 private int handleSrcGetDeviceEnabledCommand() {
2704 boolean result = false;
2705 try {
2706 result = mInterface.getDeviceSingleRegistrationEnabled();
2707 } catch (RemoteException e) {
2708 return -1;
2709 }
2710 if (VDBG) {
2711 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2712 }
2713 getOutPrintWriter().println(result);
2714 return 0;
2715 }
2716
2717 private int handleSrcSetCarrierEnabledCommand() {
2718 //the release time value could be -1
2719 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2720 : SubscriptionManager.getDefaultSubscriptionId();
2721 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2722 return -1;
2723 }
2724
2725 String enabledStr = getNextArg();
2726 if (enabledStr == null) {
2727 return -1;
2728 }
2729
2730 try {
2731 boolean result =
2732 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2733 if (VDBG) {
2734 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2735 + enabledStr + ", result=" + result);
2736 }
2737 getOutPrintWriter().println(result);
2738 } catch (NumberFormatException | RemoteException e) {
2739 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2740 + enabledStr + ", error" + e.getMessage());
2741 getErrPrintWriter().println("Exception: " + e.getMessage());
2742 return -1;
2743 }
2744 return 0;
2745 }
2746
2747 private int handleSrcGetCarrierEnabledCommand() {
2748 int subId = getSubId("src get-carrier-enabled");
2749 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2750 return -1;
2751 }
2752
2753 boolean result = false;
2754 try {
2755 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2756 } catch (RemoteException e) {
2757 return -1;
2758 }
2759 if (VDBG) {
2760 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2761 }
2762 getOutPrintWriter().println(result);
2763 return 0;
2764 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002765
Hui Wangb647abe2021-02-26 09:33:38 -08002766 private int handleSrcSetFeatureValidationCommand() {
2767 //the release time value could be -1
2768 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2769 : SubscriptionManager.getDefaultSubscriptionId();
2770 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2771 return -1;
2772 }
2773
2774 String enabledStr = getNextArg();
2775 if (enabledStr == null) {
2776 return -1;
2777 }
2778
2779 try {
2780 boolean result =
2781 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2782 if (VDBG) {
2783 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2784 + enabledStr + ", result=" + result);
2785 }
2786 getOutPrintWriter().println(result);
2787 } catch (NumberFormatException | RemoteException e) {
2788 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2789 + enabledStr + ", error" + e.getMessage());
2790 getErrPrintWriter().println("Exception: " + e.getMessage());
2791 return -1;
2792 }
2793 return 0;
2794 }
2795
2796 private int handleSrcGetFeatureValidationCommand() {
2797 int subId = getSubId("src get-feature-validation");
2798 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2799 return -1;
2800 }
2801
2802 Boolean result = false;
2803 try {
2804 result = mInterface.getImsFeatureValidationOverride(subId);
2805 } catch (RemoteException e) {
2806 return -1;
2807 }
2808 if (VDBG) {
2809 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2810 }
2811 getOutPrintWriter().println(result);
2812 return 0;
2813 }
2814
2815
Hall Liuaa4211e2021-01-20 15:43:39 -08002816 private void onHelpCallComposer() {
2817 PrintWriter pw = getOutPrintWriter();
2818 pw.println("Call composer commands");
2819 pw.println(" callcomposer test-mode enable|disable|query");
2820 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2821 pw.println(" upload/download from carrier servers is disabled, and operations are");
2822 pw.println(" performed using emulated local files instead.");
2823 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2824 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2825 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002826 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2827 pw.println(" Enables or disables the user setting for call composer, as set by");
2828 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002829 }
2830
2831 private int handleCallComposerCommand() {
2832 String arg = getNextArg();
2833 if (arg == null) {
2834 onHelpCallComposer();
2835 return 0;
2836 }
2837
2838 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2839 "MODIFY_PHONE_STATE required for call composer shell cmds");
2840 switch (arg) {
2841 case CALL_COMPOSER_TEST_MODE: {
2842 String enabledStr = getNextArg();
2843 if (ENABLE.equals(enabledStr)) {
2844 CallComposerPictureManager.sTestMode = true;
2845 } else if (DISABLE.equals(enabledStr)) {
2846 CallComposerPictureManager.sTestMode = false;
2847 } else if (QUERY.equals(enabledStr)) {
2848 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2849 } else {
2850 onHelpCallComposer();
2851 return 1;
2852 }
2853 break;
2854 }
2855 case CALL_COMPOSER_SIMULATE_CALL: {
2856 int subscriptionId = Integer.valueOf(getNextArg());
2857 String uuidString = getNextArg();
2858 UUID uuid = UUID.fromString(uuidString);
2859 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2860 Binder.withCleanCallingIdentity(() -> {
2861 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2862 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2863 });
2864 try {
2865 Uri uri = storageUriFuture.get();
2866 getOutPrintWriter().println(String.valueOf(uri));
2867 } catch (Exception e) {
2868 throw new RuntimeException(e);
2869 }
2870 break;
2871 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002872 case CALL_COMPOSER_USER_SETTING: {
2873 try {
2874 int subscriptionId = Integer.valueOf(getNextArg());
2875 String enabledStr = getNextArg();
2876 if (ENABLE.equals(enabledStr)) {
2877 mInterface.setCallComposerStatus(subscriptionId,
2878 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2879 } else if (DISABLE.equals(enabledStr)) {
2880 mInterface.setCallComposerStatus(subscriptionId,
2881 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2882 } else if (QUERY.equals(enabledStr)) {
2883 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2884 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2885 } else {
2886 onHelpCallComposer();
2887 return 1;
2888 }
2889 } catch (RemoteException e) {
2890 e.printStackTrace(getOutPrintWriter());
2891 return 1;
2892 }
2893 break;
2894 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002895 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002896 return 0;
2897 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002898
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002899 private int handleHasCarrierPrivilegesCommand() {
2900 String packageName = getNextArgRequired();
2901
2902 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002903 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002904 try {
2905 hasCarrierPrivileges =
2906 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2907 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2908 } catch (RemoteException e) {
2909 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2910 getErrPrintWriter().println("Exception: " + e.getMessage());
2911 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002912 } finally {
2913 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002914 }
2915
2916 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002917 return 0;
2918 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002919
2920 private int handleAllowedNetworkTypesCommand(String command) {
2921 if (!checkShellUid()) {
2922 return -1;
2923 }
2924
2925 PrintWriter errPw = getErrPrintWriter();
2926 String tag = command + ": ";
2927 String opt;
2928 int subId = -1;
2929 Log.v(LOG_TAG, command + " start");
2930
2931 while ((opt = getNextOption()) != null) {
2932 if (opt.equals("-s")) {
2933 try {
2934 subId = slotStringToSubId(tag, getNextArgRequired());
2935 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2936 errPw.println(tag + "No valid subscription found.");
2937 return -1;
2938 }
2939 } catch (IllegalArgumentException e) {
2940 // Missing slot id
2941 errPw.println(tag + "SLOT_ID expected after -s.");
2942 return -1;
2943 }
2944 } else {
2945 errPw.println(tag + "Unknown option " + opt);
2946 return -1;
2947 }
2948 }
2949
2950 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2951 return handleGetAllowedNetworkTypesCommand(subId);
2952 }
2953 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2954 return handleSetAllowedNetworkTypesCommand(subId);
2955 }
2956 return -1;
2957 }
2958
2959 private int handleGetAllowedNetworkTypesCommand(int subId) {
2960 PrintWriter errPw = getErrPrintWriter();
2961
2962 long result = -1;
2963 try {
2964 if (mInterface != null) {
2965 result = mInterface.getAllowedNetworkTypesForReason(subId,
2966 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2967 } else {
2968 throw new IllegalStateException("telephony service is null.");
2969 }
2970 } catch (RemoteException e) {
2971 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2972 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2973 return -1;
2974 }
2975
2976 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2977 return 0;
2978 }
2979
2980 private int handleSetAllowedNetworkTypesCommand(int subId) {
2981 PrintWriter errPw = getErrPrintWriter();
2982
2983 String bitmaskString = getNextArg();
2984 if (TextUtils.isEmpty(bitmaskString)) {
2985 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2986 return -1;
2987 }
2988 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2989 if (allowedNetworkTypes < 0) {
2990 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2991 return -1;
2992 }
2993 boolean result = false;
2994 try {
2995 if (mInterface != null) {
2996 result = mInterface.setAllowedNetworkTypesForReason(subId,
2997 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2998 } else {
2999 throw new IllegalStateException("telephony service is null.");
3000 }
3001 } catch (RemoteException e) {
3002 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
3003 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
3004 return -1;
3005 }
3006
3007 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
3008 if (result) {
3009 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
3010 }
3011 getOutPrintWriter().println(resultMessage);
3012 return 0;
3013 }
3014
3015 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
3016 if (TextUtils.isEmpty(bitmaskString)) {
3017 return -1;
3018 }
3019 if (VDBG) {
3020 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
3021 + ", length: " + bitmaskString.length());
3022 }
3023 try {
3024 return Long.parseLong(bitmaskString, 2);
3025 } catch (NumberFormatException e) {
3026 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
3027 return -1;
3028 }
3029 }
Jack Yu4c0a5502021-12-03 23:58:26 -08003030
jimsun3b9ccac2021-10-26 15:01:23 +08003031 private int handleRadioSetModemServiceCommand() {
3032 PrintWriter errPw = getErrPrintWriter();
3033 String serviceName = null;
3034
3035 String opt;
3036 while ((opt = getNextOption()) != null) {
3037 switch (opt) {
3038 case "-s": {
3039 serviceName = getNextArgRequired();
3040 break;
3041 }
3042 }
3043 }
3044
3045 try {
3046 boolean result = mInterface.setModemService(serviceName);
3047 if (VDBG) {
3048 Log.v(LOG_TAG,
3049 "RadioSetModemService " + serviceName + ", result = " + result);
3050 }
3051 getOutPrintWriter().println(result);
3052 } catch (RemoteException e) {
3053 Log.w(LOG_TAG,
3054 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
3055 errPw.println("Exception: " + e.getMessage());
3056 return -1;
3057 }
3058 return 0;
3059 }
3060
3061 private int handleRadioGetModemServiceCommand() {
3062 PrintWriter errPw = getErrPrintWriter();
3063 String result;
3064
3065 try {
3066 result = mInterface.getModemService();
3067 getOutPrintWriter().println(result);
3068 } catch (RemoteException e) {
3069 errPw.println("Exception: " + e.getMessage());
3070 return -1;
3071 }
3072 if (VDBG) {
3073 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
3074 }
3075 return 0;
3076 }
3077
3078 private int handleRadioCommand() {
3079 String arg = getNextArg();
3080 if (arg == null) {
3081 onHelpRadio();
3082 return 0;
3083 }
3084
3085 switch (arg) {
3086 case RADIO_SET_MODEM_SERVICE:
3087 return handleRadioSetModemServiceCommand();
3088
3089 case RADIO_GET_MODEM_SERVICE:
3090 return handleRadioGetModemServiceCommand();
3091 }
3092
3093 return -1;
3094 }
arunvoddud7401012022-12-15 16:08:12 +00003095
Thomas Nguyend34a5fc2023-03-23 21:07:03 -07003096 private int handleSetSatelliteServicePackageNameCommand() {
3097 PrintWriter errPw = getErrPrintWriter();
3098 String serviceName = null;
3099
3100 String opt;
3101 while ((opt = getNextOption()) != null) {
3102 switch (opt) {
3103 case "-s": {
3104 serviceName = getNextArgRequired();
3105 break;
3106 }
3107 }
3108 }
3109 Log.d(LOG_TAG, "handleSetSatelliteServicePackageNameCommand: serviceName="
3110 + serviceName);
3111
3112 try {
3113 boolean result = mInterface.setSatelliteServicePackageName(serviceName);
3114 if (VDBG) {
3115 Log.v(LOG_TAG, "SetSatelliteServicePackageName " + serviceName
3116 + ", result = " + result);
3117 }
3118 getOutPrintWriter().println(result);
3119 } catch (RemoteException e) {
3120 Log.w(LOG_TAG, "SetSatelliteServicePackageName: " + serviceName
3121 + ", error = " + e.getMessage());
3122 errPw.println("Exception: " + e.getMessage());
3123 return -1;
3124 }
3125 return 0;
3126 }
3127
Thomas Nguyenf9a533c2023-04-06 20:48:41 -07003128 private int handleSetSatelliteListeningTimeoutDuration() {
3129 PrintWriter errPw = getErrPrintWriter();
3130 long timeoutMillis = 0;
3131
3132 String opt;
3133 while ((opt = getNextOption()) != null) {
3134 switch (opt) {
3135 case "-t": {
3136 timeoutMillis = Long.parseLong(getNextArgRequired());
3137 break;
3138 }
3139 }
3140 }
3141 Log.d(LOG_TAG, "handleSetSatelliteListeningTimeoutDuration: timeoutMillis="
3142 + timeoutMillis);
3143
3144 try {
3145 boolean result = mInterface.setSatelliteListeningTimeoutDuration(timeoutMillis);
3146 if (VDBG) {
3147 Log.v(LOG_TAG, "setSatelliteListeningTimeoutDuration " + timeoutMillis
3148 + ", result = " + result);
3149 }
3150 getOutPrintWriter().println(result);
3151 } catch (RemoteException e) {
3152 Log.w(LOG_TAG, "setSatelliteListeningTimeoutDuration: " + timeoutMillis
3153 + ", error = " + e.getMessage());
3154 errPw.println("Exception: " + e.getMessage());
3155 return -1;
3156 }
3157 return 0;
3158 }
3159
arunvoddud7401012022-12-15 16:08:12 +00003160 private int handleCarrierRestrictionStatusCommand() {
3161 try {
3162 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3163 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3164 mInterface.getModemService()))) {
3165 Log.v(LOG_TAG,
3166 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3167 + " checkShellUid fails");
3168 return -1;
3169 }
3170 } catch (RemoteException ex) {
3171 ex.printStackTrace();
3172 }
3173 String callerInfo = getNextOption();
3174 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3175 if (TextUtils.isEmpty(callerInfo)) {
3176 // reset the Json content after testing
3177 allowListInfo.updateJsonForTest(null);
3178 return 0;
3179 }
3180 if (callerInfo.startsWith("--")) {
3181 callerInfo = callerInfo.replace("--", "");
3182 }
3183 String params[] = callerInfo.split(",");
3184 StringBuffer jsonStrBuffer = new StringBuffer();
3185 String tokens;
3186 for (int index = 0; index < params.length; index++) {
3187 tokens = convertToJsonString(index, params[index]);
3188 if (TextUtils.isEmpty(tokens)) {
3189 // received wrong format from CTS
3190 if (VDBG) {
3191 Log.v(LOG_TAG,
3192 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3193 }
3194 return -1;
3195 }
3196 jsonStrBuffer.append(tokens);
3197 }
3198 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3199 return result;
3200 }
3201
Benedict Wong66477622023-02-03 23:30:57 +00003202 // set-carrier-service-package-override
3203 private int setCarrierServicePackageOverride() {
3204 PrintWriter errPw = getErrPrintWriter();
3205 int subId = SubscriptionManager.getDefaultSubscriptionId();
3206
3207 String opt;
3208 while ((opt = getNextOption()) != null) {
3209 switch (opt) {
3210 case "-s":
3211 try {
3212 subId = Integer.parseInt(getNextArgRequired());
3213 } catch (NumberFormatException e) {
3214 errPw.println(
3215 "set-carrier-service-package-override requires an integer as a"
3216 + " subscription ID.");
3217 return -1;
3218 }
3219 break;
3220 }
3221 }
3222
3223 String packageName = getNextArg();
3224 if (packageName == null) {
3225 errPw.println("set-carrier-service-package-override requires a override package name.");
3226 return -1;
3227 }
3228
3229 try {
3230 mInterface.setCarrierServicePackageOverride(
3231 subId, packageName, mContext.getOpPackageName());
3232
3233 if (VDBG) {
3234 Log.v(
3235 LOG_TAG,
3236 "set-carrier-service-package-override -s " + subId + " " + packageName);
3237 }
3238 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3239 Log.w(
3240 LOG_TAG,
3241 "set-carrier-service-package-override -s "
3242 + subId
3243 + " "
3244 + packageName
3245 + ", error"
3246 + e.getMessage());
3247 errPw.println("Exception: " + e.getMessage());
3248 return -1;
3249 }
3250 return 0;
3251 }
3252
3253 // clear-carrier-service-package-override
3254 private int clearCarrierServicePackageOverride() {
3255 PrintWriter errPw = getErrPrintWriter();
3256 int subId = getDefaultSlot();
3257
3258 String opt;
3259 while ((opt = getNextOption()) != null) {
3260 switch (opt) {
3261 case "-s":
3262 try {
3263 subId = Integer.parseInt(getNextArgRequired());
3264 } catch (NumberFormatException e) {
3265 errPw.println(
3266 "clear-carrier-service-package-override requires an integer as a"
3267 + " subscription ID.");
3268 return -1;
3269 }
3270 break;
3271 }
3272 }
3273
3274 try {
3275 mInterface.setCarrierServicePackageOverride(subId, null, mContext.getOpPackageName());
3276
3277 if (VDBG) {
3278 Log.v(LOG_TAG, "clear-carrier-service-package-override -s " + subId);
3279 }
3280 } catch (RemoteException | IllegalArgumentException | IllegalStateException e) {
3281 Log.w(
3282 LOG_TAG,
3283 "clear-carrier-service-package-override -s "
3284 + subId
3285 + ", error"
3286 + e.getMessage());
3287 errPw.println("Exception: " + e.getMessage());
3288 return -1;
3289 }
3290 return 0;
3291 }
arunvoddud7401012022-12-15 16:08:12 +00003292
3293 /**
3294 * Building the string that can be used to build the JsonObject which supports to stub the data
3295 * in CarrierAllowListInfo for CTS testing. sample format is like
3296 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3297 */
3298 private String convertToJsonString(int index, String param) {
3299
3300 String token[] = param.split(":");
3301 String jSonString;
3302 switch (index) {
3303 case 0:
3304 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3305 break;
3306 case 1:
3307 jSonString =
3308 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3309 break;
3310 case 2:
3311 jSonString =
3312 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3313 break;
3314 default:
3315 jSonString = null;
3316 }
3317 return jSonString;
3318 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003319}