blob: f002e25d275b30f0833d0ce8790b268e1f5a457b [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;
arunvoddud7401012022-12-15 16:08:12 +000060import com.android.phone.utils.CarrierAllowListInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070061
Allen Xuee00f0e2022-03-14 21:04:49 +000062import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070063import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080064import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000065import java.util.Arrays;
66import java.util.Collections;
Brad Ebinger24c29992019-12-05 13:03:21 -080067import java.util.List;
Grant Menke567d48f2022-08-18 20:19:10 +000068import java.util.Locale;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010069import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000070import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010071import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080072import java.util.UUID;
73import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070074
75/**
76 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
77 * permission checks have been done before onCommand was called. Make sure any commands processed
78 * here also contain the appropriate permissions checks.
79 */
80
Hall Liua1548bd2019-12-24 14:14:12 -080081public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070082
83 private static final String LOG_TAG = "TelephonyShellCommand";
84 // Don't commit with this true.
85 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070086 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070087
Hall Liuaa4211e2021-01-20 15:43:39 -080088 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070089 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080090 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080091 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080092 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070093 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000094 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000095 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010096 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080097 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080098 private static final String ENABLE = "enable";
99 private static final String DISABLE = "disable";
100 private static final String QUERY = "query";
arunvoddud7401012022-12-15 16:08:12 +0000101 private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
102 private final String QUOTES = "\"";
Hall Liuaa4211e2021-01-20 15:43:39 -0800103
Hall Liu7135e502021-02-04 16:58:17 -0800104 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800105 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800106 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800107
Brad Ebinger999d3302020-11-25 14:31:39 -0800108 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
109 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
110 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700111 // Used to disable or enable processing of conference event package data from the network.
112 // This is handy for testing scenarios where CEP data does not exist on a network which does
113 // support CEP data.
114 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700115
Hall Liud892bec2018-11-30 14:51:45 -0800116 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800117 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800118
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100119 private static final String CC_GET_VALUE = "get-value";
120 private static final String CC_SET_VALUE = "set-value";
Allen Xuee00f0e2022-03-14 21:04:49 +0000121 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100122 private static final String CC_CLEAR_VALUES = "clear-values";
123
Hui Wang641e81c2020-10-12 12:14:23 -0700124 private static final String GBA_SUBCOMMAND = "gba";
125 private static final String GBA_SET_SERVICE = "set-service";
126 private static final String GBA_GET_SERVICE = "get-service";
127 private static final String GBA_SET_RELEASE_TIME = "set-release";
128 private static final String GBA_GET_RELEASE_TIME = "get-release";
129
Hui Wang761a6682020-10-31 05:12:53 +0000130 private static final String SINGLE_REGISTATION_CONFIG = "src";
131 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
132 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
133 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
134 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800135 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
136 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800137 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
138 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000139
Tyler Gunn92479152021-01-20 16:30:10 -0800140 private static final String D2D_SUBCOMMAND = "d2d";
141 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800142 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700143 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800144
Nazanin014f41e2021-05-06 17:26:31 -0700145 private static final String BARRING_SUBCOMMAND = "barring";
146 private static final String BARRING_SEND_INFO = "send";
147
James.cf Linbcdf8b32021-01-14 16:44:13 +0800148 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800149 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800150 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800151 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800152 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
153 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000154 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
155 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800156 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
157 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800158 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
159 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800160
jimsun3b9ccac2021-10-26 15:01:23 +0800161 private static final String RADIO_SUBCOMMAND = "radio";
162 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
163 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
164
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800165 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
166 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
167
Jordan Liu0ccee222021-04-27 11:55:13 -0700168 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
169 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
170
Jack Nudelman644b91a2021-03-12 14:09:48 -0800171 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
172 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
173 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
174
Grant Menke567d48f2022-08-18 20:19:10 +0000175 private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
176 + "'*', '#' or '+') needs to be specified after -a in the command ";
177
178 private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
179 EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
180 EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
181
SongFerngWang98dd5992021-05-13 17:50:00 +0800182 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
183 "get-allowed-network-types-for-users";
184 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
185 "set-allowed-network-types-for-users";
Ling Ma4fbab492022-01-25 22:36:16 +0000186 private static final String GET_IMEI = "get-imei";
Aman Gupta07124872022-02-09 08:02:14 +0000187 private static final String GET_SIM_SLOTS_MAPPING = "get-sim-slots-mapping";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700188 // Take advantage of existing methods that already contain permissions checks when possible.
189 private final ITelephony mInterface;
190
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100191 private SubscriptionManager mSubscriptionManager;
192 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700193 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700194 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100195
196 private enum CcType {
197 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xuee00f0e2022-03-14 21:04:49 +0000198 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100199 }
200
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100201 private class CcOptionParseResult {
202 public int mSubId;
203 public boolean mPersistent;
204 }
205
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100206 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
207 // keys by looking at the end of the string which usually tells the type.
208 // For instance: "xxxx_string", "xxxx_string_array", etc.
209 // The carrier config keys in this map does not follow this convention. It is therefore not
210 // possible to infer the type for these keys by looking at the string.
Cole Faustc16d5292022-10-15 21:33:27 -0700211 private static final Map<String, CcType> CC_TYPE_MAP = Map.ofEntries(
212 entry(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING,
213 CcType.STRING),
214 entry(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING),
215 entry(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING),
216 entry(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING),
217 entry(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING),
218 entry(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING),
219 entry(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING),
220 entry(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING),
221 entry(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING),
222 entry(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING),
223 entry(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
224 CcType.STRING),
225 entry(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
226 CcType.STRING_ARRAY),
227 entry(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
228 CcType.STRING_ARRAY),
229 entry(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING),
230 entry(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING),
231 entry(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING),
232 entry(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING),
233 entry(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING),
234 entry(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING),
235 entry(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING),
236 entry(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY));
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100237
Brad Ebinger14d467f2021-02-12 06:18:28 +0000238 /**
239 * Map from a shorthand string to the feature tags required in registration required in order
240 * for the RCS feature to be considered "capable".
241 */
242 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
243 static {
244 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
245 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
246 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
247 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
248 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
249 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
250 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
251 FeatureTags.FEATURE_TAG_VIDEO)));
252 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
253 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
254 map.put("call_comp",
255 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
256 map.put("call_comp_mmtel",
257 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
258 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
259 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
260 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
261 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
262 // version
263 map.put("chatbot", new ArraySet<>(Arrays.asList(
264 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
265 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
266 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
267 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunho38970ab2022-01-11 12:44:19 +0000268 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000269 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
270 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
271 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
272 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
273 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunho38970ab2022-01-11 12:44:19 +0000274 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000275 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
276 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
277 }
278
279
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100280 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700281 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100282 mCarrierConfigManager =
283 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
284 mSubscriptionManager = (SubscriptionManager)
285 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700286 mTelephonyRegistryManager = (TelephonyRegistryManager)
287 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700288 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700289 }
290
291 @Override
292 public int onCommand(String cmd) {
293 if (cmd == null) {
294 return handleDefaultCommands(null);
295 }
296
297 switch (cmd) {
298 case IMS_SUBCOMMAND: {
299 return handleImsCommand();
300 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800301 case RCS_UCE_COMMAND:
302 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800303 case NUMBER_VERIFICATION_SUBCOMMAND:
304 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800305 case EMERGENCY_CALLBACK_MODE:
306 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800307 case EMERGENCY_NUMBER_TEST_MODE:
308 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100309 case CARRIER_CONFIG_SUBCOMMAND: {
310 return handleCcCommand();
311 }
Shuo Qianf5125122019-12-16 17:03:07 -0800312 case DATA_TEST_MODE:
313 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700314 case END_BLOCK_SUPPRESSION:
315 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700316 case GBA_SUBCOMMAND:
317 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800318 case D2D_SUBCOMMAND:
319 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700320 case BARRING_SUBCOMMAND:
321 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000322 case SINGLE_REGISTATION_CONFIG:
323 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000324 case RESTART_MODEM:
325 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800326 case CALL_COMPOSER_SUBCOMMAND:
327 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000328 case UNATTENDED_REBOOT:
329 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800330 case HAS_CARRIER_PRIVILEGES_COMMAND:
331 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800332 case THERMAL_MITIGATION_COMMAND:
333 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700334 case DISABLE_PHYSICAL_SUBSCRIPTION:
335 return handleEnablePhysicalSubscription(false);
336 case ENABLE_PHYSICAL_SUBSCRIPTION:
337 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800338 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
339 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
340 return handleAllowedNetworkTypesCommand(cmd);
Ling Ma4fbab492022-01-25 22:36:16 +0000341 case GET_IMEI:
342 return handleGetImei();
Aman Gupta07124872022-02-09 08:02:14 +0000343 case GET_SIM_SLOTS_MAPPING:
344 return handleGetSimSlotsMapping();
jimsun3b9ccac2021-10-26 15:01:23 +0800345 case RADIO_SUBCOMMAND:
346 return handleRadioCommand();
arunvoddud7401012022-12-15 16:08:12 +0000347 case CARRIER_RESTRICTION_STATUS_TEST:
348 return handleCarrierRestrictionStatusCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700349 default: {
350 return handleDefaultCommands(cmd);
351 }
352 }
353 }
354
355 @Override
356 public void onHelp() {
357 PrintWriter pw = getOutPrintWriter();
358 pw.println("Telephony Commands:");
359 pw.println(" help");
360 pw.println(" Print this help text.");
361 pw.println(" ims");
362 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800363 pw.println(" uce");
364 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800365 pw.println(" emergency-number-test-mode");
366 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700367 pw.println(" end-block-suppression");
368 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800369 pw.println(" data");
370 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100371 pw.println(" cc");
372 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700373 pw.println(" gba");
374 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000375 pw.println(" src");
376 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000377 pw.println(" restart-modem");
378 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000379 pw.println(" unattended-reboot");
380 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800381 pw.println(" has-carrier-privileges [package]");
382 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800383 pw.println(" get-allowed-network-types-for-users");
384 pw.println(" Get the Allowed Network Types.");
385 pw.println(" set-allowed-network-types-for-users");
386 pw.println(" Set the Allowed Network Types.");
jimsun3b9ccac2021-10-26 15:01:23 +0800387 pw.println(" radio");
388 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700389 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800390 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800391 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700392 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800393 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100394 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700395 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000396 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800397 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700398 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800399 onHelpAllowedNetworkTypes();
jimsun3b9ccac2021-10-26 15:01:23 +0800400 onHelpRadio();
Ling Ma4fbab492022-01-25 22:36:16 +0000401 onHelpImei();
Tyler Gunn92479152021-01-20 16:30:10 -0800402 }
403
404 private void onHelpD2D() {
405 PrintWriter pw = getOutPrintWriter();
406 pw.println("D2D Comms Commands:");
407 pw.println(" d2d send TYPE VALUE");
408 pw.println(" Sends a D2D message of specified type and value.");
409 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
410 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
411 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
412 MESSAGE_CALL_AUDIO_CODEC));
413 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
414 + Communicator.messageToString(
415 MESSAGE_DEVICE_BATTERY_STATE));
416 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
417 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800418 pw.println(" d2d transport TYPE");
419 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
420 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700421 pw.println(" d2d set-device-support true/default");
422 pw.println(" true - forces device support to be enabled for D2D.");
423 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
424 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700425 }
426
Nazanin014f41e2021-05-06 17:26:31 -0700427 private void onHelpBarring() {
428 PrintWriter pw = getOutPrintWriter();
429 pw.println("Barring Commands:");
430 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
431 + " -t CONDITIONAL_BARRING_TIME_SECS");
432 pw.println(" Notifies of a barring info change for the specified slot id.");
433 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
434 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
435 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
436 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
437 }
438
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700439 private void onHelpIms() {
440 PrintWriter pw = getOutPrintWriter();
441 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800442 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700443 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
444 pw.println(" ImsService. Options are:");
445 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
446 pw.println(" is specified, it will choose the default voice SIM slot.");
447 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
448 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800449 pw.println(" -f: Set the feature that this override if for, if no option is");
450 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700451 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
452 pw.println(" Gets the package name of the currently defined ImsService.");
453 pw.println(" Options are:");
454 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
455 pw.println(" is specified, it will choose the default voice SIM slot.");
456 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000457 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800458 pw.println(" -f: The feature type that the query will be requested for. If none is");
459 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800460 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
461 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
462 pw.println(" configuration overrides. Options are:");
463 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
464 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700465 pw.println(" ims enable [-s SLOT_ID]");
466 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
467 pw.println(" if none is specified.");
468 pw.println(" ims disable [-s SLOT_ID]");
469 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
470 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700471 pw.println(" ims conference-event-package [enable/disable]");
472 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700473 }
474
James.cf Linbcdf8b32021-01-14 16:44:13 +0800475 private void onHelpUce() {
476 PrintWriter pw = getOutPrintWriter();
477 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800478 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
479 pw.println(" Get the EAB contacts from the EAB database.");
480 pw.println(" Options are:");
481 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
482 pw.println(" Expected output format :");
483 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800484 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
485 pw.println(" Remove the EAB contacts from the EAB database.");
486 pw.println(" Options are:");
487 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
488 pw.println(" is specified, it will choose the default voice SIM slot.");
489 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800490 pw.println(" uce get-device-enabled");
491 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
492 pw.println(" uce set-device-enabled true|false");
493 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
494 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000495 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
496 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
497 pw.println(" Options are:");
498 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
499 pw.println(" is specified, it will choose the default voice SIM slot.");
500 pw.println(" add [CAPABILITY]: add a new capability");
501 pw.println(" remove [CAPABILITY]: remove a capability");
502 pw.println(" clear: clear all capability overrides");
503 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
504 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
505 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
506 pw.println(" chatbot_sa, chatbot_role] as well as full length");
507 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
508 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
509 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
510 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800511 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
512 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800513 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
514 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800515 }
516
Hall Liud892bec2018-11-30 14:51:45 -0800517 private void onHelpNumberVerification() {
518 PrintWriter pw = getOutPrintWriter();
519 pw.println("Number verification commands");
520 pw.println(" numverify override-package PACKAGE_NAME;");
521 pw.println(" Set the authorized package for number verification.");
522 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800523 pw.println(" numverify fake-call NUMBER;");
524 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
525 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800526 }
527
Jack Nudelman644b91a2021-03-12 14:09:48 -0800528 private void onHelpThermalMitigation() {
529 PrintWriter pw = getOutPrintWriter();
530 pw.println("Thermal mitigation commands");
531 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
532 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
533 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
534 pw.println(" Remove the package from one of the authorized packages for thermal "
535 + "mitigation.");
536 }
537
Jordan Liu0ccee222021-04-27 11:55:13 -0700538 private void onHelpDisableOrEnablePhysicalSubscription() {
539 PrintWriter pw = getOutPrintWriter();
540 pw.println("Disable or enable a physical subscription");
541 pw.println(" disable-physical-subscription SUB_ID");
542 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
543 pw.println(" enable-physical-subscription SUB_ID");
544 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
545 }
546
Shuo Qianf5125122019-12-16 17:03:07 -0800547 private void onHelpDataTestMode() {
548 PrintWriter pw = getOutPrintWriter();
549 pw.println("Mobile Data Test Mode Commands:");
550 pw.println(" data enable: enable mobile data connectivity");
551 pw.println(" data disable: disable mobile data connectivity");
552 }
553
sqian9d4df8b2019-01-15 18:32:07 -0800554 private void onHelpEmergencyNumber() {
555 PrintWriter pw = getOutPrintWriter();
556 pw.println("Emergency Number Test Mode Commands:");
557 pw.println(" emergency-number-test-mode ");
558 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
559 + " the test mode");
560 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700561 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800562 pw.println(" -c: clear the emergency number list in the test mode.");
563 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700564 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800565 pw.println(" -p: get the full emergency number list in the test mode.");
566 }
567
Shuo Qian489d9282020-07-09 11:30:03 -0700568 private void onHelpEndBlockSupperssion() {
569 PrintWriter pw = getOutPrintWriter();
570 pw.println("End Block Suppression command:");
571 pw.println(" end-block-suppression: disable suppressing blocking by contact");
572 pw.println(" with emergency services.");
573 }
574
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100575 private void onHelpCc() {
576 PrintWriter pw = getOutPrintWriter();
577 pw.println("Carrier Config Commands:");
578 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
579 pw.println(" Print carrier config values.");
580 pw.println(" Options are:");
581 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
582 pw.println(" is specified, it will choose the default voice SIM slot.");
583 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
584 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100585 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100586 pw.println(" Set carrier config KEY to NEW_VALUE.");
587 pw.println(" Options are:");
588 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
589 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100590 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100591 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
592 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
593 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
594 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xuee00f0e2022-03-14 21:04:49 +0000595 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
596 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
597 pw.println(" provided through standard input and follow CarrierConfig XML format.");
598 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
599 pw.println(" Options are:");
600 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
601 pw.println(" is specified, it will choose the default voice SIM slot.");
602 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100603 pw.println(" cc clear-values [-s SLOT_ID]");
604 pw.println(" Clear all carrier override values that has previously been set");
Allen Xuee00f0e2022-03-14 21:04:49 +0000605 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100606 pw.println(" Options are:");
607 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
608 pw.println(" is specified, it will choose the default voice SIM slot.");
609 }
610
Hui Wang641e81c2020-10-12 12:14:23 -0700611 private void onHelpGba() {
612 PrintWriter pw = getOutPrintWriter();
613 pw.println("Gba Commands:");
614 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
615 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
616 pw.println(" Options are:");
617 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
618 pw.println(" is specified, it will choose the default voice SIM slot.");
619 pw.println(" gba get-service [-s SLOT_ID]");
620 pw.println(" Gets the package name of the currently defined GbaService.");
621 pw.println(" Options are:");
622 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
623 pw.println(" is specified, it will choose the default voice SIM slot.");
624 pw.println(" gba set-release [-s SLOT_ID] n");
625 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
626 pw.println(" Do not release/unbind if n is -1.");
627 pw.println(" Options are:");
628 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
629 pw.println(" is specified, it will choose the default voice SIM slot.");
630 pw.println(" gba get-release [-s SLOT_ID]");
631 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
632 pw.println(" Options are:");
633 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
634 pw.println(" is specified, it will choose the default voice SIM slot.");
635 }
636
Hui Wang761a6682020-10-31 05:12:53 +0000637 private void onHelpSrc() {
638 PrintWriter pw = getOutPrintWriter();
639 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800640 pw.println(" src set-test-enabled true|false");
641 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
642 pw.println(" The value could be true, false, or null(undefined).");
643 pw.println(" src get-test-enabled");
644 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000645 pw.println(" src set-device-enabled true|false|null");
646 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
647 pw.println(" The value could be true, false, or null(undefined).");
648 pw.println(" src get-device-enabled");
649 pw.println(" Gets the device config for RCS VoLTE single registration.");
650 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
651 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
652 pw.println(" The value could be true, false, or null(undefined).");
653 pw.println(" Options are:");
654 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
655 pw.println(" is specified, it will choose the default voice SIM slot.");
656 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
657 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
658 pw.println(" Options are:");
659 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
660 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800661 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
662 pw.println(" Sets ims feature validation result.");
663 pw.println(" The value could be true, false, or null(undefined).");
664 pw.println(" Options are:");
665 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
666 pw.println(" is specified, it will choose the default voice SIM slot.");
667 pw.println(" src get-feature-validation [-s SLOT_ID]");
668 pw.println(" Gets ims feature validation override value.");
669 pw.println(" Options are:");
670 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
671 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000672 }
673
SongFerngWang98dd5992021-05-13 17:50:00 +0800674 private void onHelpAllowedNetworkTypes() {
675 PrintWriter pw = getOutPrintWriter();
676 pw.println("Allowed Network Types Commands:");
677 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
678 pw.println(" Print allowed network types value.");
679 pw.println(" Options are:");
680 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
681 pw.println(" option is specified, it will choose the default voice SIM slot.");
682 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
683 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
684 pw.println(" Options are:");
685 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
686 pw.println(" option is specified, it will choose the default voice SIM slot.");
687 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
688 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
689 pw.println(" at TelephonyManager.java");
690 pw.println(" For example:");
691 pw.println(" NR only : 10000000000000000000");
692 pw.println(" NR|LTE : 11000001000000000000");
693 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
694 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
695 pw.println(" LTE only : 01000001000000000000");
696 }
697
jimsun3b9ccac2021-10-26 15:01:23 +0800698 private void onHelpRadio() {
699 PrintWriter pw = getOutPrintWriter();
700 pw.println("Radio Commands:");
701 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
702 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
703 pw.println(" to be the bound. Options are:");
704 pw.println(" -s: the service name that the modem service should be bound for.");
705 pw.println(" If no option is specified, it will bind to the default.");
706 pw.println(" radio get-modem-service");
707 pw.println(" Gets the service name of the currently defined modem service.");
708 pw.println(" If it is binding to default, 'default' returns.");
709 pw.println(" If it doesn't bind to any modem service for some reasons,");
710 pw.println(" the result would be 'unknown'.");
711 }
712
Ling Ma4fbab492022-01-25 22:36:16 +0000713 private void onHelpImei() {
714 PrintWriter pw = getOutPrintWriter();
715 pw.println("IMEI Commands:");
716 pw.println(" get-imei [-s SLOT_ID]");
717 pw.println(" Gets the device IMEI. Options are:");
718 pw.println(" -s: the slot ID to get the IMEI. If no option");
719 pw.println(" is specified, it will choose the default voice SIM slot.");
720 }
721
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700722 private int handleImsCommand() {
723 String arg = getNextArg();
724 if (arg == null) {
725 onHelpIms();
726 return 0;
727 }
728
729 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800730 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700731 return handleImsSetServiceCommand();
732 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800733 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700734 return handleImsGetServiceCommand();
735 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800736 case IMS_CLEAR_SERVICE_OVERRIDE: {
737 return handleImsClearCarrierServiceCommand();
738 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800739 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700740 return handleEnableIms();
741 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800742 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700743 return handleDisableIms();
744 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700745 case IMS_CEP: {
746 return handleCepChange();
747 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700748 }
749
750 return -1;
751 }
752
Shuo Qianf5125122019-12-16 17:03:07 -0800753 private int handleDataTestModeCommand() {
754 PrintWriter errPw = getErrPrintWriter();
755 String arg = getNextArgRequired();
756 if (arg == null) {
757 onHelpDataTestMode();
758 return 0;
759 }
760 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800761 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800762 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700763 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800764 } catch (RemoteException ex) {
765 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
766 errPw.println("Exception: " + ex.getMessage());
767 return -1;
768 }
769 break;
770 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800771 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800772 try {
Sarah Chinecc78c42022-03-31 21:16:48 -0700773 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800774 } catch (RemoteException ex) {
775 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
776 errPw.println("Exception: " + ex.getMessage());
777 return -1;
778 }
779 break;
780 }
781 default:
782 onHelpDataTestMode();
783 break;
784 }
785 return 0;
786 }
787
Shuo Qianccbaf742021-02-22 18:32:21 -0800788 private int handleEmergencyCallbackModeCommand() {
789 PrintWriter errPw = getErrPrintWriter();
790 try {
791 mInterface.startEmergencyCallbackMode();
792 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
793 } catch (RemoteException ex) {
794 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
795 errPw.println("Exception: " + ex.getMessage());
796 return -1;
797 }
798 return 0;
799 }
800
Grant Menke567d48f2022-08-18 20:19:10 +0000801 private void removeEmergencyNumberTestMode(String emergencyNumber) {
802 PrintWriter errPw = getErrPrintWriter();
803 for (int routingType : ROUTING_TYPES) {
804 try {
805 mInterface.updateEmergencyNumberListTestMode(
806 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
807 new EmergencyNumber(emergencyNumber, "", "",
808 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
809 new ArrayList<String>(),
810 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
811 routingType));
812 } catch (RemoteException ex) {
813 Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
814 errPw.println("Exception: " + ex.getMessage());
815 }
816 }
817 }
818
sqian9d4df8b2019-01-15 18:32:07 -0800819 private int handleEmergencyNumberTestModeCommand() {
820 PrintWriter errPw = getErrPrintWriter();
821 String opt = getNextOption();
822 if (opt == null) {
823 onHelpEmergencyNumber();
824 return 0;
825 }
sqian9d4df8b2019-01-15 18:32:07 -0800826 switch (opt) {
827 case "-a": {
828 String emergencyNumberCmd = getNextArgRequired();
Grant Menke567d48f2022-08-18 20:19:10 +0000829 if (emergencyNumberCmd == null){
830 errPw.println(INVALID_ENTRY_ERROR);
sqian9d4df8b2019-01-15 18:32:07 -0800831 return -1;
832 }
Grant Menke567d48f2022-08-18 20:19:10 +0000833 String[] params = emergencyNumberCmd.split(":");
834 String emergencyNumber;
835 if (params[0] == null ||
836 !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
837 errPw.println(INVALID_ENTRY_ERROR);
838 return -1;
839 } else {
840 emergencyNumber = params[0];
841 }
842 removeEmergencyNumberTestMode(emergencyNumber);
843 int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
844 if (params.length > 1) {
845 switch (params[1].toLowerCase(Locale.ROOT)) {
846 case "emergency":
847 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
848 break;
849 case "normal":
850 emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
851 break;
852 case "unknown":
853 break;
854 default:
855 errPw.println("\"" + params[1] + "\" is not a valid specification for "
856 + "emergency call routing. Please enter either \"normal\", "
857 + "\"unknown\", or \"emergency\" for call routing. "
858 + "(-a 1234:normal)");
859 return -1;
860 }
861 }
sqian9d4df8b2019-01-15 18:32:07 -0800862 try {
863 mInterface.updateEmergencyNumberListTestMode(
864 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
Grant Menke567d48f2022-08-18 20:19:10 +0000865 new EmergencyNumber(emergencyNumber, "", "",
sqian9d4df8b2019-01-15 18:32:07 -0800866 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
867 new ArrayList<String>(),
868 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
Grant Menke567d48f2022-08-18 20:19:10 +0000869 emergencyCallRouting));
sqian9d4df8b2019-01-15 18:32:07 -0800870 } catch (RemoteException ex) {
Grant Menke567d48f2022-08-18 20:19:10 +0000871 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
sqian9d4df8b2019-01-15 18:32:07 -0800872 + ", error " + ex.getMessage());
873 errPw.println("Exception: " + ex.getMessage());
874 return -1;
875 }
876 break;
877 }
878 case "-c": {
879 try {
880 mInterface.updateEmergencyNumberListTestMode(
881 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
882 } catch (RemoteException ex) {
883 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
884 errPw.println("Exception: " + ex.getMessage());
885 return -1;
886 }
887 break;
888 }
889 case "-r": {
890 String emergencyNumberCmd = getNextArgRequired();
891 if (emergencyNumberCmd == null
892 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700893 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800894 + " to be specified after -r in the command ");
895 return -1;
896 }
Grant Menke567d48f2022-08-18 20:19:10 +0000897 removeEmergencyNumberTestMode(emergencyNumberCmd);
sqian9d4df8b2019-01-15 18:32:07 -0800898 break;
899 }
900 case "-p": {
901 try {
902 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
903 } catch (RemoteException ex) {
904 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
905 errPw.println("Exception: " + ex.getMessage());
906 return -1;
907 }
908 break;
909 }
910 default:
911 onHelpEmergencyNumber();
912 break;
913 }
914 return 0;
915 }
916
Hall Liud892bec2018-11-30 14:51:45 -0800917 private int handleNumberVerificationCommand() {
918 String arg = getNextArg();
919 if (arg == null) {
920 onHelpNumberVerification();
921 return 0;
922 }
923
Hall Liuca5af3a2018-12-04 16:58:23 -0800924 if (!checkShellUid()) {
925 return -1;
926 }
927
Hall Liud892bec2018-11-30 14:51:45 -0800928 switch (arg) {
929 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800930 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
931 return 0;
932 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800933 case NUMBER_VERIFICATION_FAKE_CALL: {
934 boolean val = NumberVerificationManager.getInstance()
935 .checkIncomingCall(getNextArg());
936 getOutPrintWriter().println(val ? "1" : "0");
937 return 0;
938 }
Hall Liud892bec2018-11-30 14:51:45 -0800939 }
940
941 return -1;
942 }
943
Jordan Liu0ccee222021-04-27 11:55:13 -0700944 private boolean subIsEsim(int subId) {
945 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
946 if (info != null) {
947 return info.isEmbedded();
948 }
949 return false;
950 }
951
952 private int handleEnablePhysicalSubscription(boolean enable) {
953 PrintWriter errPw = getErrPrintWriter();
954 int subId = 0;
955 try {
956 subId = Integer.parseInt(getNextArgRequired());
957 } catch (NumberFormatException e) {
958 errPw.println((enable ? "enable" : "disable")
959 + "-physical-subscription requires an integer as a subId.");
960 return -1;
961 }
962 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
963 // non user build.
964 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
965 errPw.println("cc: Permission denied.");
966 return -1;
967 }
968 // Verify that the subId represents a physical sub
969 if (subIsEsim(subId)) {
970 errPw.println("SubId " + subId + " is not for a physical subscription");
971 return -1;
972 }
973 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
974 + " physical subscription with subId=" + subId);
975 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
976 return 0;
977 }
978
Jack Nudelman644b91a2021-03-12 14:09:48 -0800979 private int handleThermalMitigationCommand() {
980 String arg = getNextArg();
981 String packageName = getNextArg();
982 if (arg == null || packageName == null) {
983 onHelpThermalMitigation();
984 return 0;
985 }
986
987 if (!checkShellUid()) {
988 return -1;
989 }
990
991 switch (arg) {
992 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
993 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
994 return 0;
995 }
996 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
997 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
998 mContext);
999 return 0;
1000 }
1001 default:
1002 onHelpThermalMitigation();
1003 }
1004
1005 return -1;
1006
1007 }
1008
Tyler Gunn92479152021-01-20 16:30:10 -08001009 private int handleD2dCommand() {
1010 String arg = getNextArg();
1011 if (arg == null) {
1012 onHelpD2D();
1013 return 0;
1014 }
1015
1016 switch (arg) {
1017 case D2D_SEND: {
1018 return handleD2dSendCommand();
1019 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001020 case D2D_TRANSPORT: {
1021 return handleD2dTransportCommand();
1022 }
Tyler Gunnd4575212021-05-03 14:46:49 -07001023 case D2D_SET_DEVICE_SUPPORT: {
1024 return handleD2dDeviceSupportedCommand();
1025 }
Tyler Gunn92479152021-01-20 16:30:10 -08001026 }
1027
1028 return -1;
1029 }
1030
1031 private int handleD2dSendCommand() {
1032 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -08001033 int messageType = -1;
1034 int messageValue = -1;
1035
Tyler Gunn92479152021-01-20 16:30:10 -08001036 String arg = getNextArg();
1037 if (arg == null) {
1038 onHelpD2D();
1039 return 0;
1040 }
1041 try {
1042 messageType = Integer.parseInt(arg);
1043 } catch (NumberFormatException e) {
1044 errPw.println("message type must be a valid integer");
1045 return -1;
1046 }
1047
1048 arg = getNextArg();
1049 if (arg == null) {
1050 onHelpD2D();
1051 return 0;
1052 }
1053 try {
1054 messageValue = Integer.parseInt(arg);
1055 } catch (NumberFormatException e) {
1056 errPw.println("message value must be a valid integer");
1057 return -1;
1058 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001059
Tyler Gunn92479152021-01-20 16:30:10 -08001060 try {
1061 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1062 } catch (RemoteException e) {
1063 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1064 errPw.println("Exception: " + e.getMessage());
1065 return -1;
1066 }
1067
1068 return 0;
1069 }
1070
Tyler Gunnbabbda02021-02-10 11:05:02 -08001071 private int handleD2dTransportCommand() {
1072 PrintWriter errPw = getErrPrintWriter();
1073
1074 String arg = getNextArg();
1075 if (arg == null) {
1076 onHelpD2D();
1077 return 0;
1078 }
1079
1080 try {
1081 mInterface.setActiveDeviceToDeviceTransport(arg);
1082 } catch (RemoteException e) {
1083 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1084 errPw.println("Exception: " + e.getMessage());
1085 return -1;
1086 }
1087 return 0;
1088 }
Nazanin014f41e2021-05-06 17:26:31 -07001089 private int handleBarringCommand() {
1090 String arg = getNextArg();
1091 if (arg == null) {
1092 onHelpBarring();
1093 return 0;
1094 }
1095
1096 switch (arg) {
1097 case BARRING_SEND_INFO: {
1098 return handleBarringSendCommand();
1099 }
1100 }
1101 return -1;
1102 }
1103
1104 private int handleBarringSendCommand() {
1105 PrintWriter errPw = getErrPrintWriter();
1106 int slotId = getDefaultSlot();
Jack Yu00ece8c2022-11-19 22:29:12 -08001107 int subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001108 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1109 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1110 boolean isConditionallyBarred = false;
1111 int conditionalBarringTimeSeconds = 0;
1112
1113 String opt;
1114 while ((opt = getNextOption()) != null) {
1115 switch (opt) {
1116 case "-s": {
1117 try {
1118 slotId = Integer.parseInt(getNextArgRequired());
Jack Yu00ece8c2022-11-19 22:29:12 -08001119 subId = SubscriptionManager.getSubscriptionId(slotId);
Nazanin014f41e2021-05-06 17:26:31 -07001120 } catch (NumberFormatException e) {
1121 errPw.println("barring send requires an integer as a SLOT_ID.");
1122 return -1;
1123 }
1124 break;
1125 }
1126 case "-b": {
1127 try {
1128 barringType = Integer.parseInt(getNextArgRequired());
1129 if (barringType < -1 || barringType > 2) {
1130 throw new NumberFormatException();
1131 }
1132
1133 } catch (NumberFormatException e) {
1134 errPw.println("barring send requires an integer in range [-1,2] as "
1135 + "a BARRING_TYPE.");
1136 return -1;
1137 }
1138 break;
1139 }
1140 case "-c": {
1141 try {
1142 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1143 } catch (Exception e) {
1144 errPw.println("barring send requires a boolean after -c indicating"
1145 + " conditional barring");
1146 return -1;
1147 }
1148 break;
1149 }
1150 case "-t": {
1151 try {
1152 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1153 } catch (NumberFormatException e) {
1154 errPw.println("barring send requires an integer for time of barring"
1155 + " in seconds after -t for conditional barring");
1156 return -1;
1157 }
1158 break;
1159 }
1160 }
1161 }
1162 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1163 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1164 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1165 barringServiceInfos.append(0, bsi);
1166 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1167 try {
1168 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1169 } catch (Exception e) {
1170 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1171 errPw.println("Exception: " + e.getMessage());
1172 return -1;
1173 }
1174 return 0;
1175 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001176
Tyler Gunnd4575212021-05-03 14:46:49 -07001177 private int handleD2dDeviceSupportedCommand() {
1178 PrintWriter errPw = getErrPrintWriter();
1179
1180 String arg = getNextArg();
1181 if (arg == null) {
1182 onHelpD2D();
1183 return 0;
1184 }
1185
Jack Yua533d632022-09-30 13:53:46 -07001186 boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
Tyler Gunnd4575212021-05-03 14:46:49 -07001187 try {
1188 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1189 } catch (RemoteException e) {
1190 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1191 errPw.println("Exception: " + e.getMessage());
1192 return -1;
1193 }
1194 return 0;
1195 }
1196
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001197 // ims set-ims-service
1198 private int handleImsSetServiceCommand() {
1199 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001200 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001201 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001202 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001203
1204 String opt;
1205 while ((opt = getNextOption()) != null) {
1206 switch (opt) {
1207 case "-s": {
1208 try {
1209 slotId = Integer.parseInt(getNextArgRequired());
1210 } catch (NumberFormatException e) {
1211 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1212 return -1;
1213 }
1214 break;
1215 }
1216 case "-c": {
1217 isCarrierService = true;
1218 break;
1219 }
1220 case "-d": {
1221 isCarrierService = false;
1222 break;
1223 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001224 case "-f": {
1225 String featureString = getNextArgRequired();
1226 String[] features = featureString.split(",");
1227 for (int i = 0; i < features.length; i++) {
1228 try {
1229 Integer result = Integer.parseInt(features[i]);
1230 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1231 || result >= ImsFeature.FEATURE_MAX) {
1232 errPw.println("ims set-ims-service -f " + result
1233 + " is an invalid feature.");
1234 return -1;
1235 }
1236 featuresList.add(result);
1237 } catch (NumberFormatException e) {
1238 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1239 + " as an integer.");
1240 return -1;
1241 }
1242 }
1243 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001244 }
1245 }
1246 // Mandatory param, either -c or -d
1247 if (isCarrierService == null) {
1248 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1249 return -1;
1250 }
1251
1252 String packageName = getNextArg();
1253
1254 try {
1255 if (packageName == null) {
1256 packageName = "";
1257 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001258 int[] featureArray = new int[featuresList.size()];
1259 for (int i = 0; i < featuresList.size(); i++) {
1260 featureArray[i] = featuresList.get(i);
1261 }
1262 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1263 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001264 if (VDBG) {
1265 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001266 + (isCarrierService ? "-c " : "-d ")
1267 + "-f " + featuresList + " "
1268 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001269 }
1270 getOutPrintWriter().println(result);
1271 } catch (RemoteException e) {
1272 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001273 + (isCarrierService ? "-c " : "-d ")
1274 + "-f " + featuresList + " "
1275 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001276 errPw.println("Exception: " + e.getMessage());
1277 return -1;
1278 }
1279 return 0;
1280 }
1281
Brad Ebinger999d3302020-11-25 14:31:39 -08001282 // ims clear-ims-service-override
1283 private int handleImsClearCarrierServiceCommand() {
1284 PrintWriter errPw = getErrPrintWriter();
1285 int slotId = getDefaultSlot();
1286
1287 String opt;
1288 while ((opt = getNextOption()) != null) {
1289 switch (opt) {
1290 case "-s": {
1291 try {
1292 slotId = Integer.parseInt(getNextArgRequired());
1293 } catch (NumberFormatException e) {
1294 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1295 return -1;
1296 }
1297 break;
1298 }
1299 }
1300 }
1301
1302 try {
1303 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1304 if (VDBG) {
1305 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1306 + ", result=" + result);
1307 }
1308 getOutPrintWriter().println(result);
1309 } catch (RemoteException e) {
1310 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1311 + ", error" + e.getMessage());
1312 errPw.println("Exception: " + e.getMessage());
1313 return -1;
1314 }
1315 return 0;
1316 }
1317
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001318 // ims get-ims-service
1319 private int handleImsGetServiceCommand() {
1320 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001321 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001322 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001323 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001324
1325 String opt;
1326 while ((opt = getNextOption()) != null) {
1327 switch (opt) {
1328 case "-s": {
1329 try {
1330 slotId = Integer.parseInt(getNextArgRequired());
1331 } catch (NumberFormatException e) {
1332 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1333 return -1;
1334 }
1335 break;
1336 }
1337 case "-c": {
1338 isCarrierService = true;
1339 break;
1340 }
1341 case "-d": {
1342 isCarrierService = false;
1343 break;
1344 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001345 case "-f": {
1346 try {
1347 featureType = Integer.parseInt(getNextArg());
1348 } catch (NumberFormatException e) {
1349 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1350 return -1;
1351 }
1352 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1353 || featureType >= ImsFeature.FEATURE_MAX) {
1354 errPw.println("ims get-ims-service -f invalid feature.");
1355 return -1;
1356 }
1357 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001358 }
1359 }
1360 // Mandatory param, either -c or -d
1361 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001362 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001363 return -1;
1364 }
1365
1366 String result;
1367 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001368 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001369 } catch (RemoteException e) {
1370 return -1;
1371 }
1372 if (VDBG) {
1373 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001374 + (isCarrierService ? "-c " : "-d ")
1375 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1376 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001377 }
1378 getOutPrintWriter().println(result);
1379 return 0;
1380 }
1381
1382 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001383 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001384 String opt;
1385 while ((opt = getNextOption()) != null) {
1386 switch (opt) {
1387 case "-s": {
1388 try {
1389 slotId = Integer.parseInt(getNextArgRequired());
1390 } catch (NumberFormatException e) {
1391 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1392 return -1;
1393 }
1394 break;
1395 }
1396 }
1397 }
1398 try {
1399 mInterface.enableIms(slotId);
1400 } catch (RemoteException e) {
1401 return -1;
1402 }
1403 if (VDBG) {
1404 Log.v(LOG_TAG, "ims enable -s " + slotId);
1405 }
1406 return 0;
1407 }
1408
1409 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001410 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001411 String opt;
1412 while ((opt = getNextOption()) != null) {
1413 switch (opt) {
1414 case "-s": {
1415 try {
1416 slotId = Integer.parseInt(getNextArgRequired());
1417 } catch (NumberFormatException e) {
1418 getErrPrintWriter().println(
1419 "ims disable requires an integer as a SLOT_ID.");
1420 return -1;
1421 }
1422 break;
1423 }
1424 }
1425 }
1426 try {
1427 mInterface.disableIms(slotId);
1428 } catch (RemoteException e) {
1429 return -1;
1430 }
1431 if (VDBG) {
1432 Log.v(LOG_TAG, "ims disable -s " + slotId);
1433 }
1434 return 0;
1435 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001436
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001437 private int handleCepChange() {
1438 Log.i(LOG_TAG, "handleCepChange");
1439 String opt = getNextArg();
1440 if (opt == null) {
1441 return -1;
1442 }
1443 boolean isCepEnabled = opt.equals("enable");
1444
1445 try {
1446 mInterface.setCepEnabled(isCepEnabled);
1447 } catch (RemoteException e) {
1448 return -1;
1449 }
1450 return 0;
1451 }
1452
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001453 private int getDefaultSlot() {
1454 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1455 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1456 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1457 // If there is no default, default to slot 0.
1458 slotId = DEFAULT_PHONE_ID;
1459 }
1460 return slotId;
1461 }
sqian2fff4a32018-11-05 14:18:37 -08001462
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001463 // Parse options related to Carrier Config Commands.
1464 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001465 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001466 CcOptionParseResult result = new CcOptionParseResult();
1467 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1468 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001469
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001470 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001471 while ((opt = getNextOption()) != null) {
1472 switch (opt) {
1473 case "-s": {
1474 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001475 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1476 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1477 errPw.println(tag + "No valid subscription found.");
1478 return null;
1479 }
1480
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001481 } catch (IllegalArgumentException e) {
1482 // Missing slot id
1483 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001484 return null;
1485 }
1486 break;
1487 }
1488 case "-p": {
1489 if (allowOptionPersistent) {
1490 result.mPersistent = true;
1491 } else {
1492 errPw.println(tag + "Unexpected option " + opt);
1493 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001494 }
1495 break;
1496 }
1497 default: {
1498 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001499 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001500 }
1501 }
1502 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001503 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001504 }
1505
1506 private int slotStringToSubId(String tag, String slotString) {
1507 int slotId = -1;
1508 try {
1509 slotId = Integer.parseInt(slotString);
1510 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001511 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1512 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1513 }
1514
1515 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001516 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1517 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1518 }
1519
Qiong Liuf25799b2020-09-10 10:13:46 +08001520 Phone phone = PhoneFactory.getPhone(slotId);
1521 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001522 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1523 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1524 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001525 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001526 }
1527
Hall Liud892bec2018-11-30 14:51:45 -08001528 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001529 // adb can run as root or as shell, depending on whether the device is rooted.
1530 return Binder.getCallingUid() == Process.SHELL_UID
1531 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001532 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001533
1534 private int handleCcCommand() {
1535 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1536 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001537 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001538 getErrPrintWriter().println("cc: Permission denied.");
1539 return -1;
1540 }
1541
1542 String arg = getNextArg();
1543 if (arg == null) {
1544 onHelpCc();
1545 return 0;
1546 }
1547
1548 switch (arg) {
1549 case CC_GET_VALUE: {
1550 return handleCcGetValue();
1551 }
1552 case CC_SET_VALUE: {
1553 return handleCcSetValue();
1554 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001555 case CC_SET_VALUES_FROM_XML: {
1556 return handleCcSetValuesFromXml();
1557 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001558 case CC_CLEAR_VALUES: {
1559 return handleCcClearValues();
1560 }
1561 default: {
1562 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1563 }
1564 }
1565 return -1;
1566 }
1567
1568 // cc get-value
1569 private int handleCcGetValue() {
1570 PrintWriter errPw = getErrPrintWriter();
1571 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1572 String key = null;
1573
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001574 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001575 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001576 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001577 return -1;
1578 }
1579
1580 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001581 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001582 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001583 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001584 return -1;
1585 }
1586
1587 // Get the key.
1588 key = getNextArg();
1589 if (key != null) {
1590 // A key was provided. Verify if it is a valid key
1591 if (!bundle.containsKey(key)) {
1592 errPw.println(tag + key + " is not a valid key.");
1593 return -1;
1594 }
1595
1596 // Print the carrier config value for key.
1597 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1598 } else {
1599 // No key provided. Show all values.
1600 // Iterate over a sorted list of all carrier config keys and print them.
1601 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1602 for (String k : sortedSet) {
1603 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1604 }
1605 }
1606 return 0;
1607 }
1608
1609 // cc set-value
1610 private int handleCcSetValue() {
1611 PrintWriter errPw = getErrPrintWriter();
1612 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1613
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001614 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001615 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001616 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001617 return -1;
1618 }
1619
1620 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001621 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001622 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001623 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001624 return -1;
1625 }
1626
1627 // Get the key.
1628 String key = getNextArg();
1629 if (key == null || key.equals("")) {
1630 errPw.println(tag + "KEY is missing");
1631 return -1;
1632 }
1633
1634 // Verify if the key is valid
1635 if (!originalValues.containsKey(key)) {
1636 errPw.println(tag + key + " is not a valid key.");
1637 return -1;
1638 }
1639
1640 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1641 ArrayList<String> valueList = new ArrayList<String>();
1642 while (peekNextArg() != null) {
1643 valueList.add(getNextArg());
1644 }
1645
1646 // Find the type of the carrier config value
1647 CcType type = getType(tag, key, originalValues);
1648 if (type == CcType.UNKNOWN) {
1649 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1650 return -1;
1651 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001652 if (type == CcType.PERSISTABLE_BUNDLE) {
1653 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1654 + "Use set-values-from-xml instead.");
1655 return -1;
1656 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001657
1658 // Create an override bundle containing the key and value that should be overriden.
1659 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1660 if (overrideBundle == null) {
1661 return -1;
1662 }
1663
1664 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001665 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001666
1667 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001668 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001669 if (newValues == 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 // Print the original and new value.
1675 String originalValueString = ccValueToString(key, type, originalValues);
1676 String newValueString = ccValueToString(key, type, newValues);
1677 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1678 getOutPrintWriter().println("New value: \n" + newValueString);
1679
1680 return 0;
1681 }
1682
Allen Xuee00f0e2022-03-14 21:04:49 +00001683 // cc set-values-from-xml
1684 private int handleCcSetValuesFromXml() {
1685 PrintWriter errPw = getErrPrintWriter();
1686 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1687
1688 // Parse all options
Allen Xuaafea2e2022-05-20 22:26:42 +00001689 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xuee00f0e2022-03-14 21:04:49 +00001690 if (options == null) {
1691 return -1;
1692 }
1693
1694 // Get bundle containing all current carrier configuration values.
1695 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1696 if (originalValues == null) {
1697 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1698 return -1;
1699 }
1700
1701 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1702 if (overrideBundle == null) {
1703 return -1;
1704 }
1705
1706 // Verify all values are valid types
1707 for (String key : overrideBundle.keySet()) {
1708 CcType type = getType(tag, key, originalValues);
1709 if (type == CcType.UNKNOWN) {
1710 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1711 return -1;
1712 }
1713 }
1714
1715 // Override the value
1716 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1717
1718 // Find bundle containing all new carrier configuration values after the override.
1719 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1720 if (newValues == null) {
1721 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1722 return -1;
1723 }
1724
1725 // Print the original and new values
1726 overrideBundle.keySet().forEach(key -> {
1727 CcType type = getType(tag, key, originalValues);
1728 String originalValueString = ccValueToString(key, type, originalValues);
1729 String newValueString = ccValueToString(key, type, newValues);
1730 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1731 getOutPrintWriter().println("New value: \n" + newValueString);
1732 });
1733
1734 return 0;
1735 }
1736
1737 private PersistableBundle readPersistableBundleFromXml(String tag) {
1738 PersistableBundle subIdBundles;
1739 try {
1740 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1741 } catch (IOException | RuntimeException e) {
1742 PrintWriter errPw = getErrPrintWriter();
1743 errPw.println(tag + e);
1744 return null;
1745 }
1746
1747 return subIdBundles;
1748 }
1749
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001750 // cc clear-values
1751 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001752 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1753
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001754 // Parse all options
Allen Xuee00f0e2022-03-14 21:04:49 +00001755 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001756 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001757 return -1;
1758 }
1759
1760 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001761 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001762 getOutPrintWriter()
1763 .println("All previously set carrier config override values has been cleared");
1764 return 0;
1765 }
1766
1767 private CcType getType(String tag, String key, PersistableBundle bundle) {
1768 // Find the type by checking the type of the current value stored in the bundle.
1769 Object value = bundle.get(key);
1770
1771 if (CC_TYPE_MAP.containsKey(key)) {
1772 return CC_TYPE_MAP.get(key);
1773 } else if (value != null) {
1774 if (value instanceof Boolean) {
1775 return CcType.BOOLEAN;
Allen Xuee00f0e2022-03-14 21:04:49 +00001776 }
1777 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001778 return CcType.DOUBLE;
Allen Xuee00f0e2022-03-14 21:04:49 +00001779 }
1780 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001781 return CcType.DOUBLE_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001782 }
1783 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001784 return CcType.INT;
Allen Xuee00f0e2022-03-14 21:04:49 +00001785 }
1786 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001787 return CcType.INT_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001788 }
1789 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001790 return CcType.LONG;
Allen Xuee00f0e2022-03-14 21:04:49 +00001791 }
1792 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001793 return CcType.LONG_ARRAY;
Allen Xuee00f0e2022-03-14 21:04:49 +00001794 }
1795 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001796 return CcType.STRING;
Allen Xuee00f0e2022-03-14 21:04:49 +00001797 }
1798 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001799 return CcType.STRING_ARRAY;
1800 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001801 if (value instanceof PersistableBundle) {
1802 return CcType.PERSISTABLE_BUNDLE;
1803 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001804 } else {
1805 // Current value was null and can therefore not be used in order to find the type.
1806 // Check the name of the key to infer the type. This check is not needed for primitive
1807 // data types (boolean, double, int and long), since they can not be null.
1808 if (key.endsWith("double_array")) {
1809 return CcType.DOUBLE_ARRAY;
1810 }
1811 if (key.endsWith("int_array")) {
1812 return CcType.INT_ARRAY;
1813 }
1814 if (key.endsWith("long_array")) {
1815 return CcType.LONG_ARRAY;
1816 }
1817 if (key.endsWith("string")) {
1818 return CcType.STRING;
1819 }
1820 if (key.endsWith("string_array") || key.endsWith("strings")) {
1821 return CcType.STRING_ARRAY;
1822 }
Allen Xuee00f0e2022-03-14 21:04:49 +00001823 if (key.endsWith("bundle")) {
1824 return CcType.PERSISTABLE_BUNDLE;
1825 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001826 }
1827
1828 // Not possible to infer the type by looking at the current value or the key.
1829 PrintWriter errPw = getErrPrintWriter();
1830 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1831 return CcType.UNKNOWN;
1832 }
1833
1834 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1835 String result;
1836 StringBuilder valueString = new StringBuilder();
1837 String typeString = type.toString();
1838 Object value = bundle.get(key);
1839
1840 if (value == null) {
1841 valueString.append("null");
1842 } else {
1843 switch (type) {
1844 case DOUBLE_ARRAY: {
1845 // Format the string representation of the int array as value1 value2......
1846 double[] valueArray = (double[]) value;
1847 for (int i = 0; i < valueArray.length; i++) {
1848 if (i != 0) {
1849 valueString.append(" ");
1850 }
1851 valueString.append(valueArray[i]);
1852 }
1853 break;
1854 }
1855 case INT_ARRAY: {
1856 // Format the string representation of the int array as value1 value2......
1857 int[] valueArray = (int[]) value;
1858 for (int i = 0; i < valueArray.length; i++) {
1859 if (i != 0) {
1860 valueString.append(" ");
1861 }
1862 valueString.append(valueArray[i]);
1863 }
1864 break;
1865 }
1866 case LONG_ARRAY: {
1867 // Format the string representation of the int array as value1 value2......
1868 long[] valueArray = (long[]) value;
1869 for (int i = 0; i < valueArray.length; i++) {
1870 if (i != 0) {
1871 valueString.append(" ");
1872 }
1873 valueString.append(valueArray[i]);
1874 }
1875 break;
1876 }
1877 case STRING: {
1878 valueString.append("\"" + value.toString() + "\"");
1879 break;
1880 }
1881 case STRING_ARRAY: {
1882 // Format the string representation of the string array as "value1" "value2"....
1883 String[] valueArray = (String[]) value;
1884 for (int i = 0; i < valueArray.length; i++) {
1885 if (i != 0) {
1886 valueString.append(" ");
1887 }
1888 if (valueArray[i] != null) {
1889 valueString.append("\"" + valueArray[i] + "\"");
1890 } else {
1891 valueString.append("null");
1892 }
1893 }
1894 break;
1895 }
1896 default: {
1897 valueString.append(value.toString());
1898 }
1899 }
1900 }
1901 return String.format("%-70s %-15s %s", key, typeString, valueString);
1902 }
1903
1904 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1905 ArrayList<String> valueList) {
1906 PrintWriter errPw = getErrPrintWriter();
1907 PersistableBundle bundle = new PersistableBundle();
1908
1909 // First verify that a valid number of values has been provided for the type.
1910 switch (type) {
1911 case BOOLEAN:
1912 case DOUBLE:
1913 case INT:
1914 case LONG: {
1915 if (valueList.size() != 1) {
1916 errPw.println(tag + "Expected 1 value for type " + type
1917 + ". Found: " + valueList.size());
1918 return null;
1919 }
1920 break;
1921 }
1922 case STRING: {
1923 if (valueList.size() > 1) {
1924 errPw.println(tag + "Expected 0 or 1 values for type " + type
1925 + ". Found: " + valueList.size());
1926 return null;
1927 }
1928 break;
1929 }
1930 }
1931
1932 // Parse the value according to type and add it to the Bundle.
1933 switch (type) {
1934 case BOOLEAN: {
1935 if ("true".equalsIgnoreCase(valueList.get(0))) {
1936 bundle.putBoolean(key, true);
1937 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1938 bundle.putBoolean(key, false);
1939 } else {
1940 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1941 return null;
1942 }
1943 break;
1944 }
1945 case DOUBLE: {
1946 try {
1947 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1948 } catch (NumberFormatException nfe) {
1949 // Not a valid double
1950 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1951 return null;
1952 }
1953 break;
1954 }
1955 case DOUBLE_ARRAY: {
1956 double[] valueDoubleArray = null;
1957 if (valueList.size() > 0) {
1958 valueDoubleArray = new double[valueList.size()];
1959 for (int i = 0; i < valueList.size(); i++) {
1960 try {
1961 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1962 } catch (NumberFormatException nfe) {
1963 // Not a valid double
1964 errPw.println(
1965 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1966 return null;
1967 }
1968 }
1969 }
1970 bundle.putDoubleArray(key, valueDoubleArray);
1971 break;
1972 }
1973 case INT: {
1974 try {
1975 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1976 } catch (NumberFormatException nfe) {
1977 // Not a valid integer
1978 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1979 return null;
1980 }
1981 break;
1982 }
1983 case INT_ARRAY: {
1984 int[] valueIntArray = null;
1985 if (valueList.size() > 0) {
1986 valueIntArray = new int[valueList.size()];
1987 for (int i = 0; i < valueList.size(); i++) {
1988 try {
1989 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1990 } catch (NumberFormatException nfe) {
1991 // Not a valid integer
1992 errPw.println(tag
1993 + "Unable to parse " + valueList.get(i) + " as an integer.");
1994 return null;
1995 }
1996 }
1997 }
1998 bundle.putIntArray(key, valueIntArray);
1999 break;
2000 }
2001 case LONG: {
2002 try {
2003 bundle.putLong(key, Long.parseLong(valueList.get(0)));
2004 } catch (NumberFormatException nfe) {
2005 // Not a valid long
2006 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
2007 return null;
2008 }
2009 break;
2010 }
2011 case LONG_ARRAY: {
2012 long[] valueLongArray = null;
2013 if (valueList.size() > 0) {
2014 valueLongArray = new long[valueList.size()];
2015 for (int i = 0; i < valueList.size(); i++) {
2016 try {
2017 valueLongArray[i] = Long.parseLong(valueList.get(i));
2018 } catch (NumberFormatException nfe) {
2019 // Not a valid long
2020 errPw.println(
2021 tag + "Unable to parse " + valueList.get(i) + " as a long");
2022 return null;
2023 }
2024 }
2025 }
2026 bundle.putLongArray(key, valueLongArray);
2027 break;
2028 }
2029 case STRING: {
2030 String value = null;
2031 if (valueList.size() > 0) {
2032 value = valueList.get(0);
2033 }
2034 bundle.putString(key, value);
2035 break;
2036 }
2037 case STRING_ARRAY: {
2038 String[] valueStringArray = null;
2039 if (valueList.size() > 0) {
2040 valueStringArray = new String[valueList.size()];
2041 valueList.toArray(valueStringArray);
2042 }
2043 bundle.putStringArray(key, valueStringArray);
2044 break;
2045 }
2046 }
2047 return bundle;
2048 }
Shuo Qian489d9282020-07-09 11:30:03 -07002049
2050 private int handleEndBlockSuppressionCommand() {
2051 if (!checkShellUid()) {
2052 return -1;
2053 }
2054
2055 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
2056 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2057 }
2058 return 0;
2059 }
Hui Wang641e81c2020-10-12 12:14:23 -07002060
Michele Berionne54af4632020-12-28 20:23:16 +00002061 private int handleRestartModemCommand() {
2062 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2063 // non user build.
2064 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2065 getErrPrintWriter().println("RestartModem: Permission denied.");
2066 return -1;
2067 }
2068
2069 boolean result = TelephonyManager.getDefault().rebootRadio();
2070 getOutPrintWriter().println(result);
2071
2072 return result ? 0 : -1;
2073 }
2074
Ling Ma4fbab492022-01-25 22:36:16 +00002075 private int handleGetImei() {
2076 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2077 // non user build.
2078 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2079 getErrPrintWriter().println("Device IMEI: Permission denied.");
2080 return -1;
2081 }
2082
2083 final long identity = Binder.clearCallingIdentity();
2084
2085 String imei = null;
2086 String arg = getNextArg();
2087 if (arg != null) {
2088 try {
2089 int specifiedSlotIndex = Integer.parseInt(arg);
2090 imei = TelephonyManager.from(mContext).getImei(specifiedSlotIndex);
2091 } catch (NumberFormatException exception) {
2092 PrintWriter errPw = getErrPrintWriter();
2093 errPw.println("-s requires an integer as slot index.");
2094 return -1;
2095 }
2096
2097 } else {
2098 imei = TelephonyManager.from(mContext).getImei();
2099 }
2100 getOutPrintWriter().println("Device IMEI: " + imei);
2101
2102 Binder.restoreCallingIdentity(identity);
2103 return 0;
2104 }
2105
Michele Berionne5e411512020-11-13 02:36:59 +00002106 private int handleUnattendedReboot() {
2107 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2108 // non user build.
2109 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2110 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2111 return -1;
2112 }
2113
2114 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2115 getOutPrintWriter().println("result: " + result);
2116
2117 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2118 }
2119
Aman Gupta07124872022-02-09 08:02:14 +00002120 private int handleGetSimSlotsMapping() {
2121 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2122 // non user build.
2123 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2124 getErrPrintWriter().println("GetSimSlotsMapping: Permission denied.");
2125 return -1;
2126 }
2127 TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
2128 String result = telephonyManager.getSimSlotMapping().toString();
2129 getOutPrintWriter().println("simSlotsMapping: " + result);
2130
2131 return 0;
2132 }
2133
Hui Wang641e81c2020-10-12 12:14:23 -07002134 private int handleGbaCommand() {
2135 String arg = getNextArg();
2136 if (arg == null) {
2137 onHelpGba();
2138 return 0;
2139 }
2140
2141 switch (arg) {
2142 case GBA_SET_SERVICE: {
2143 return handleGbaSetServiceCommand();
2144 }
2145 case GBA_GET_SERVICE: {
2146 return handleGbaGetServiceCommand();
2147 }
2148 case GBA_SET_RELEASE_TIME: {
2149 return handleGbaSetReleaseCommand();
2150 }
2151 case GBA_GET_RELEASE_TIME: {
2152 return handleGbaGetReleaseCommand();
2153 }
2154 }
2155
2156 return -1;
2157 }
2158
2159 private int getSubId(String cmd) {
2160 int slotId = getDefaultSlot();
2161 String opt = getNextOption();
2162 if (opt != null && opt.equals("-s")) {
2163 try {
2164 slotId = Integer.parseInt(getNextArgRequired());
2165 } catch (NumberFormatException e) {
2166 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2167 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2168 }
2169 }
Jack Yu00ece8c2022-11-19 22:29:12 -08002170 return SubscriptionManager.getSubscriptionId(slotId);
Hui Wang641e81c2020-10-12 12:14:23 -07002171 }
2172
2173 private int handleGbaSetServiceCommand() {
2174 int subId = getSubId("gba set-service");
2175 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2176 return -1;
2177 }
2178
2179 String packageName = getNextArg();
2180 try {
2181 if (packageName == null) {
2182 packageName = "";
2183 }
2184 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2185 if (VDBG) {
2186 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2187 + packageName + ", result=" + result);
2188 }
2189 getOutPrintWriter().println(result);
2190 } catch (RemoteException e) {
2191 Log.w(LOG_TAG, "gba set-service " + subId + " "
2192 + packageName + ", error" + e.getMessage());
2193 getErrPrintWriter().println("Exception: " + e.getMessage());
2194 return -1;
2195 }
2196 return 0;
2197 }
2198
2199 private int handleGbaGetServiceCommand() {
2200 String result;
2201
2202 int subId = getSubId("gba get-service");
2203 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2204 return -1;
2205 }
2206
2207 try {
2208 result = mInterface.getBoundGbaService(subId);
2209 } catch (RemoteException e) {
2210 return -1;
2211 }
2212 if (VDBG) {
2213 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2214 }
2215 getOutPrintWriter().println(result);
2216 return 0;
2217 }
2218
2219 private int handleGbaSetReleaseCommand() {
2220 //the release time value could be -1
2221 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2222 : SubscriptionManager.getDefaultSubscriptionId();
2223 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2224 return -1;
2225 }
2226
2227 String intervalStr = getNextArg();
2228 if (intervalStr == null) {
2229 return -1;
2230 }
2231
2232 try {
2233 int interval = Integer.parseInt(intervalStr);
2234 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2235 if (VDBG) {
2236 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2237 + intervalStr + ", result=" + result);
2238 }
2239 getOutPrintWriter().println(result);
2240 } catch (NumberFormatException | RemoteException e) {
2241 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2242 + intervalStr + ", error" + e.getMessage());
2243 getErrPrintWriter().println("Exception: " + e.getMessage());
2244 return -1;
2245 }
2246 return 0;
2247 }
2248
2249 private int handleGbaGetReleaseCommand() {
2250 int subId = getSubId("gba get-release");
2251 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2252 return -1;
2253 }
2254
2255 int result = 0;
2256 try {
2257 result = mInterface.getGbaReleaseTime(subId);
2258 } catch (RemoteException e) {
2259 return -1;
2260 }
2261 if (VDBG) {
2262 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2263 }
2264 getOutPrintWriter().println(result);
2265 return 0;
2266 }
Hui Wang761a6682020-10-31 05:12:53 +00002267
2268 private int handleSingleRegistrationConfigCommand() {
2269 String arg = getNextArg();
2270 if (arg == null) {
2271 onHelpSrc();
2272 return 0;
2273 }
2274
2275 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002276 case SRC_SET_TEST_ENABLED: {
2277 return handleSrcSetTestEnabledCommand();
2278 }
2279 case SRC_GET_TEST_ENABLED: {
2280 return handleSrcGetTestEnabledCommand();
2281 }
Hui Wang761a6682020-10-31 05:12:53 +00002282 case SRC_SET_DEVICE_ENABLED: {
2283 return handleSrcSetDeviceEnabledCommand();
2284 }
2285 case SRC_GET_DEVICE_ENABLED: {
2286 return handleSrcGetDeviceEnabledCommand();
2287 }
2288 case SRC_SET_CARRIER_ENABLED: {
2289 return handleSrcSetCarrierEnabledCommand();
2290 }
2291 case SRC_GET_CARRIER_ENABLED: {
2292 return handleSrcGetCarrierEnabledCommand();
2293 }
Hui Wangb647abe2021-02-26 09:33:38 -08002294 case SRC_SET_FEATURE_ENABLED: {
2295 return handleSrcSetFeatureValidationCommand();
2296 }
2297 case SRC_GET_FEATURE_ENABLED: {
2298 return handleSrcGetFeatureValidationCommand();
2299 }
Hui Wang761a6682020-10-31 05:12:53 +00002300 }
2301
2302 return -1;
2303 }
2304
James.cf Linbcdf8b32021-01-14 16:44:13 +08002305 private int handleRcsUceCommand() {
2306 String arg = getNextArg();
2307 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002308 onHelpUce();
2309 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002310 }
2311
2312 switch (arg) {
2313 case UCE_REMOVE_EAB_CONTACT:
2314 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002315 case UCE_GET_EAB_CONTACT:
2316 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002317 case UCE_GET_EAB_CAPABILITY:
2318 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002319 case UCE_GET_DEVICE_ENABLED:
2320 return handleUceGetDeviceEnabledCommand();
2321 case UCE_SET_DEVICE_ENABLED:
2322 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002323 case UCE_OVERRIDE_PUBLISH_CAPS:
2324 return handleUceOverridePublishCaps();
2325 case UCE_GET_LAST_PIDF_XML:
2326 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002327 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2328 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002329 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2330 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002331 }
2332 return -1;
2333 }
2334
2335 private int handleRemovingEabContactCommand() {
2336 int subId = getSubId("uce remove-eab-contact");
2337 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2338 return -1;
2339 }
2340
2341 String phoneNumber = getNextArgRequired();
2342 if (TextUtils.isEmpty(phoneNumber)) {
2343 return -1;
2344 }
2345 int result = 0;
2346 try {
2347 result = mInterface.removeContactFromEab(subId, phoneNumber);
2348 } catch (RemoteException e) {
2349 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2350 getErrPrintWriter().println("Exception: " + e.getMessage());
2351 return -1;
2352 }
2353
2354 if (VDBG) {
2355 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2356 }
calvinpan293ea1b2021-02-04 17:52:13 +08002357 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002358 }
2359
calvinpane4a8a1d2021-01-25 13:51:18 +08002360 private int handleGettingEabContactCommand() {
2361 String phoneNumber = getNextArgRequired();
2362 if (TextUtils.isEmpty(phoneNumber)) {
2363 return -1;
2364 }
2365 String result = "";
2366 try {
2367 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002368 } catch (RemoteException e) {
2369 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2370 getErrPrintWriter().println("Exception: " + e.getMessage());
2371 return -1;
2372 }
2373
2374 if (VDBG) {
2375 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2376 }
calvinpan293ea1b2021-02-04 17:52:13 +08002377 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002378 return 0;
2379 }
2380
Calvin Pana1434322021-07-01 19:27:01 +08002381 private int handleGettingEabCapabilityCommand() {
2382 String phoneNumber = getNextArgRequired();
2383 if (TextUtils.isEmpty(phoneNumber)) {
2384 return -1;
2385 }
2386 String result = "";
2387 try {
2388 result = mInterface.getCapabilityFromEab(phoneNumber);
2389 } catch (RemoteException e) {
2390 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2391 getErrPrintWriter().println("Exception: " + e.getMessage());
2392 return -1;
2393 }
2394
2395 if (VDBG) {
2396 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2397 }
2398 getOutPrintWriter().println(result);
2399 return 0;
2400 }
2401
James.cf Lin4b784aa2021-01-31 03:25:15 +08002402 private int handleUceGetDeviceEnabledCommand() {
2403 boolean result = false;
2404 try {
2405 result = mInterface.getDeviceUceEnabled();
2406 } catch (RemoteException e) {
2407 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2408 return -1;
2409 }
2410 if (VDBG) {
2411 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2412 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002413 getOutPrintWriter().println(result);
2414 return 0;
2415 }
2416
James.cf Lin4b784aa2021-01-31 03:25:15 +08002417 private int handleUceSetDeviceEnabledCommand() {
2418 String enabledStr = getNextArg();
2419 if (TextUtils.isEmpty(enabledStr)) {
2420 return -1;
2421 }
2422
2423 try {
2424 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2425 mInterface.setDeviceUceEnabled(isEnabled);
2426 if (VDBG) {
2427 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2428 }
2429 } catch (NumberFormatException | RemoteException e) {
2430 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2431 getErrPrintWriter().println("Exception: " + e.getMessage());
2432 return -1;
2433 }
2434 return 0;
2435 }
2436
James.cf Line8713a42021-04-29 16:04:26 +08002437 private int handleUceRemoveRequestDisallowedStatus() {
2438 int subId = getSubId("uce remove-request-disallowed-status");
2439 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2440 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2441 return -1;
2442 }
2443 boolean result;
2444 try {
2445 result = mInterface.removeUceRequestDisallowedStatus(subId);
2446 } catch (RemoteException e) {
2447 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2448 return -1;
2449 }
2450 if (VDBG) {
2451 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2452 }
2453 getOutPrintWriter().println(result);
2454 return 0;
2455 }
2456
James.cf Lin0fc71b02021-05-25 01:37:38 +08002457 private int handleUceSetCapRequestTimeout() {
2458 int subId = getSubId("uce set-capabilities-request-timeout");
2459 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2460 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2461 return -1;
2462 }
2463 long timeoutAfterMs = Long.valueOf(getNextArg());
2464 boolean result;
2465 try {
2466 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2467 } catch (RemoteException e) {
2468 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2469 return -1;
2470 }
2471 if (VDBG) {
2472 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2473 }
2474 getOutPrintWriter().println(result);
2475 return 0;
2476 }
2477
Hui Wangbaaee6a2021-02-19 20:45:36 -08002478 private int handleSrcSetTestEnabledCommand() {
2479 String enabledStr = getNextArg();
2480 if (enabledStr == null) {
2481 return -1;
2482 }
2483
2484 try {
2485 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2486 if (VDBG) {
2487 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2488 }
2489 getOutPrintWriter().println("Done");
2490 } catch (NumberFormatException | RemoteException e) {
2491 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2492 getErrPrintWriter().println("Exception: " + e.getMessage());
2493 return -1;
2494 }
2495 return 0;
2496 }
2497
2498 private int handleSrcGetTestEnabledCommand() {
2499 boolean result = false;
2500 try {
2501 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2502 } catch (RemoteException e) {
2503 return -1;
2504 }
2505 if (VDBG) {
2506 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2507 }
2508 getOutPrintWriter().println(result);
2509 return 0;
2510 }
2511
Brad Ebinger14d467f2021-02-12 06:18:28 +00002512 private int handleUceOverridePublishCaps() {
2513 int subId = getSubId("uce override-published-caps");
2514 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2515 return -1;
2516 }
2517 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2518 String operation = getNextArgRequired();
2519 String caps = getNextArg();
2520 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2521 && !"list".equals(operation)) {
2522 getErrPrintWriter().println("Invalid operation: " + operation);
2523 return -1;
2524 }
2525
2526 // add/remove requires capabilities to be specified.
2527 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2528 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2529 + "specified");
2530 return -1;
2531 }
2532
2533 ArraySet<String> capSet = new ArraySet<>();
2534 if (!TextUtils.isEmpty(caps)) {
2535 String[] capArray = caps.split(":");
2536 for (String cap : capArray) {
2537 // Allow unknown tags to be passed in as well.
2538 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2539 }
2540 }
2541
2542 RcsContactUceCapability result = null;
2543 try {
2544 switch (operation) {
2545 case "add":
2546 result = mInterface.addUceRegistrationOverrideShell(subId,
2547 new ArrayList<>(capSet));
2548 break;
2549 case "remove":
2550 result = mInterface.removeUceRegistrationOverrideShell(subId,
2551 new ArrayList<>(capSet));
2552 break;
2553 case "clear":
2554 result = mInterface.clearUceRegistrationOverrideShell(subId);
2555 break;
2556 case "list":
2557 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2558 break;
2559 }
2560 } catch (RemoteException e) {
2561 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2562 getErrPrintWriter().println("Exception: " + e.getMessage());
2563 return -1;
2564 } catch (ServiceSpecificException sse) {
2565 // Reconstruct ImsException
2566 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2567 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2568 getErrPrintWriter().println("Exception: " + imsException);
2569 return -1;
2570 }
2571 if (result == null) {
2572 getErrPrintWriter().println("Service not available");
2573 return -1;
2574 }
2575 getOutPrintWriter().println(result);
2576 return 0;
2577 }
2578
2579 private int handleUceGetPidfXml() {
2580 int subId = getSubId("uce get-last-publish-pidf");
2581 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2582 return -1;
2583 }
2584
2585 String result;
2586 try {
2587 result = mInterface.getLastUcePidfXmlShell(subId);
2588 } catch (RemoteException e) {
2589 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2590 getErrPrintWriter().println("Exception: " + e.getMessage());
2591 return -1;
2592 } catch (ServiceSpecificException sse) {
2593 // Reconstruct ImsException
2594 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2595 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2596 getErrPrintWriter().println("Exception: " + imsException);
2597 return -1;
2598 }
2599 if (result == null) {
2600 getErrPrintWriter().println("Service not available");
2601 return -1;
2602 }
2603 getOutPrintWriter().println(result);
2604 return 0;
2605 }
2606
Hui Wang761a6682020-10-31 05:12:53 +00002607 private int handleSrcSetDeviceEnabledCommand() {
2608 String enabledStr = getNextArg();
2609 if (enabledStr == null) {
2610 return -1;
2611 }
2612
2613 try {
2614 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2615 if (VDBG) {
2616 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2617 }
2618 getOutPrintWriter().println("Done");
2619 } catch (NumberFormatException | RemoteException e) {
2620 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2621 getErrPrintWriter().println("Exception: " + e.getMessage());
2622 return -1;
2623 }
2624 return 0;
2625 }
2626
2627 private int handleSrcGetDeviceEnabledCommand() {
2628 boolean result = false;
2629 try {
2630 result = mInterface.getDeviceSingleRegistrationEnabled();
2631 } catch (RemoteException e) {
2632 return -1;
2633 }
2634 if (VDBG) {
2635 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2636 }
2637 getOutPrintWriter().println(result);
2638 return 0;
2639 }
2640
2641 private int handleSrcSetCarrierEnabledCommand() {
2642 //the release time value could be -1
2643 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2644 : SubscriptionManager.getDefaultSubscriptionId();
2645 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2646 return -1;
2647 }
2648
2649 String enabledStr = getNextArg();
2650 if (enabledStr == null) {
2651 return -1;
2652 }
2653
2654 try {
2655 boolean result =
2656 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2657 if (VDBG) {
2658 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2659 + enabledStr + ", result=" + result);
2660 }
2661 getOutPrintWriter().println(result);
2662 } catch (NumberFormatException | RemoteException e) {
2663 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2664 + enabledStr + ", error" + e.getMessage());
2665 getErrPrintWriter().println("Exception: " + e.getMessage());
2666 return -1;
2667 }
2668 return 0;
2669 }
2670
2671 private int handleSrcGetCarrierEnabledCommand() {
2672 int subId = getSubId("src get-carrier-enabled");
2673 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2674 return -1;
2675 }
2676
2677 boolean result = false;
2678 try {
2679 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2680 } catch (RemoteException e) {
2681 return -1;
2682 }
2683 if (VDBG) {
2684 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2685 }
2686 getOutPrintWriter().println(result);
2687 return 0;
2688 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002689
Hui Wangb647abe2021-02-26 09:33:38 -08002690 private int handleSrcSetFeatureValidationCommand() {
2691 //the release time value could be -1
2692 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2693 : SubscriptionManager.getDefaultSubscriptionId();
2694 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2695 return -1;
2696 }
2697
2698 String enabledStr = getNextArg();
2699 if (enabledStr == null) {
2700 return -1;
2701 }
2702
2703 try {
2704 boolean result =
2705 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2706 if (VDBG) {
2707 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2708 + enabledStr + ", result=" + result);
2709 }
2710 getOutPrintWriter().println(result);
2711 } catch (NumberFormatException | RemoteException e) {
2712 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2713 + enabledStr + ", error" + e.getMessage());
2714 getErrPrintWriter().println("Exception: " + e.getMessage());
2715 return -1;
2716 }
2717 return 0;
2718 }
2719
2720 private int handleSrcGetFeatureValidationCommand() {
2721 int subId = getSubId("src get-feature-validation");
2722 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2723 return -1;
2724 }
2725
2726 Boolean result = false;
2727 try {
2728 result = mInterface.getImsFeatureValidationOverride(subId);
2729 } catch (RemoteException e) {
2730 return -1;
2731 }
2732 if (VDBG) {
2733 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2734 }
2735 getOutPrintWriter().println(result);
2736 return 0;
2737 }
2738
2739
Hall Liuaa4211e2021-01-20 15:43:39 -08002740 private void onHelpCallComposer() {
2741 PrintWriter pw = getOutPrintWriter();
2742 pw.println("Call composer commands");
2743 pw.println(" callcomposer test-mode enable|disable|query");
2744 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2745 pw.println(" upload/download from carrier servers is disabled, and operations are");
2746 pw.println(" performed using emulated local files instead.");
2747 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2748 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2749 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002750 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2751 pw.println(" Enables or disables the user setting for call composer, as set by");
2752 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002753 }
2754
2755 private int handleCallComposerCommand() {
2756 String arg = getNextArg();
2757 if (arg == null) {
2758 onHelpCallComposer();
2759 return 0;
2760 }
2761
2762 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2763 "MODIFY_PHONE_STATE required for call composer shell cmds");
2764 switch (arg) {
2765 case CALL_COMPOSER_TEST_MODE: {
2766 String enabledStr = getNextArg();
2767 if (ENABLE.equals(enabledStr)) {
2768 CallComposerPictureManager.sTestMode = true;
2769 } else if (DISABLE.equals(enabledStr)) {
2770 CallComposerPictureManager.sTestMode = false;
2771 } else if (QUERY.equals(enabledStr)) {
2772 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2773 } else {
2774 onHelpCallComposer();
2775 return 1;
2776 }
2777 break;
2778 }
2779 case CALL_COMPOSER_SIMULATE_CALL: {
2780 int subscriptionId = Integer.valueOf(getNextArg());
2781 String uuidString = getNextArg();
2782 UUID uuid = UUID.fromString(uuidString);
2783 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2784 Binder.withCleanCallingIdentity(() -> {
2785 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2786 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2787 });
2788 try {
2789 Uri uri = storageUriFuture.get();
2790 getOutPrintWriter().println(String.valueOf(uri));
2791 } catch (Exception e) {
2792 throw new RuntimeException(e);
2793 }
2794 break;
2795 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002796 case CALL_COMPOSER_USER_SETTING: {
2797 try {
2798 int subscriptionId = Integer.valueOf(getNextArg());
2799 String enabledStr = getNextArg();
2800 if (ENABLE.equals(enabledStr)) {
2801 mInterface.setCallComposerStatus(subscriptionId,
2802 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2803 } else if (DISABLE.equals(enabledStr)) {
2804 mInterface.setCallComposerStatus(subscriptionId,
2805 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2806 } else if (QUERY.equals(enabledStr)) {
2807 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2808 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2809 } else {
2810 onHelpCallComposer();
2811 return 1;
2812 }
2813 } catch (RemoteException e) {
2814 e.printStackTrace(getOutPrintWriter());
2815 return 1;
2816 }
2817 break;
2818 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002819 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002820 return 0;
2821 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002822
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002823 private int handleHasCarrierPrivilegesCommand() {
2824 String packageName = getNextArgRequired();
2825
2826 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002827 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002828 try {
2829 hasCarrierPrivileges =
2830 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2831 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2832 } catch (RemoteException e) {
2833 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2834 getErrPrintWriter().println("Exception: " + e.getMessage());
2835 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002836 } finally {
2837 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002838 }
2839
2840 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002841 return 0;
2842 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002843
2844 private int handleAllowedNetworkTypesCommand(String command) {
2845 if (!checkShellUid()) {
2846 return -1;
2847 }
2848
2849 PrintWriter errPw = getErrPrintWriter();
2850 String tag = command + ": ";
2851 String opt;
2852 int subId = -1;
2853 Log.v(LOG_TAG, command + " start");
2854
2855 while ((opt = getNextOption()) != null) {
2856 if (opt.equals("-s")) {
2857 try {
2858 subId = slotStringToSubId(tag, getNextArgRequired());
2859 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2860 errPw.println(tag + "No valid subscription found.");
2861 return -1;
2862 }
2863 } catch (IllegalArgumentException e) {
2864 // Missing slot id
2865 errPw.println(tag + "SLOT_ID expected after -s.");
2866 return -1;
2867 }
2868 } else {
2869 errPw.println(tag + "Unknown option " + opt);
2870 return -1;
2871 }
2872 }
2873
2874 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2875 return handleGetAllowedNetworkTypesCommand(subId);
2876 }
2877 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2878 return handleSetAllowedNetworkTypesCommand(subId);
2879 }
2880 return -1;
2881 }
2882
2883 private int handleGetAllowedNetworkTypesCommand(int subId) {
2884 PrintWriter errPw = getErrPrintWriter();
2885
2886 long result = -1;
2887 try {
2888 if (mInterface != null) {
2889 result = mInterface.getAllowedNetworkTypesForReason(subId,
2890 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2891 } else {
2892 throw new IllegalStateException("telephony service is null.");
2893 }
2894 } catch (RemoteException e) {
2895 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2896 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2897 return -1;
2898 }
2899
2900 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2901 return 0;
2902 }
2903
2904 private int handleSetAllowedNetworkTypesCommand(int subId) {
2905 PrintWriter errPw = getErrPrintWriter();
2906
2907 String bitmaskString = getNextArg();
2908 if (TextUtils.isEmpty(bitmaskString)) {
2909 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2910 return -1;
2911 }
2912 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2913 if (allowedNetworkTypes < 0) {
2914 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2915 return -1;
2916 }
2917 boolean result = false;
2918 try {
2919 if (mInterface != null) {
2920 result = mInterface.setAllowedNetworkTypesForReason(subId,
2921 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2922 } else {
2923 throw new IllegalStateException("telephony service is null.");
2924 }
2925 } catch (RemoteException e) {
2926 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2927 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2928 return -1;
2929 }
2930
2931 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2932 if (result) {
2933 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2934 }
2935 getOutPrintWriter().println(resultMessage);
2936 return 0;
2937 }
2938
2939 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2940 if (TextUtils.isEmpty(bitmaskString)) {
2941 return -1;
2942 }
2943 if (VDBG) {
2944 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2945 + ", length: " + bitmaskString.length());
2946 }
2947 try {
2948 return Long.parseLong(bitmaskString, 2);
2949 } catch (NumberFormatException e) {
2950 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2951 return -1;
2952 }
2953 }
Jack Yu4c0a5502021-12-03 23:58:26 -08002954
jimsun3b9ccac2021-10-26 15:01:23 +08002955 private int handleRadioSetModemServiceCommand() {
2956 PrintWriter errPw = getErrPrintWriter();
2957 String serviceName = null;
2958
2959 String opt;
2960 while ((opt = getNextOption()) != null) {
2961 switch (opt) {
2962 case "-s": {
2963 serviceName = getNextArgRequired();
2964 break;
2965 }
2966 }
2967 }
2968
2969 try {
2970 boolean result = mInterface.setModemService(serviceName);
2971 if (VDBG) {
2972 Log.v(LOG_TAG,
2973 "RadioSetModemService " + serviceName + ", result = " + result);
2974 }
2975 getOutPrintWriter().println(result);
2976 } catch (RemoteException e) {
2977 Log.w(LOG_TAG,
2978 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2979 errPw.println("Exception: " + e.getMessage());
2980 return -1;
2981 }
2982 return 0;
2983 }
2984
2985 private int handleRadioGetModemServiceCommand() {
2986 PrintWriter errPw = getErrPrintWriter();
2987 String result;
2988
2989 try {
2990 result = mInterface.getModemService();
2991 getOutPrintWriter().println(result);
2992 } catch (RemoteException e) {
2993 errPw.println("Exception: " + e.getMessage());
2994 return -1;
2995 }
2996 if (VDBG) {
2997 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2998 }
2999 return 0;
3000 }
3001
3002 private int handleRadioCommand() {
3003 String arg = getNextArg();
3004 if (arg == null) {
3005 onHelpRadio();
3006 return 0;
3007 }
3008
3009 switch (arg) {
3010 case RADIO_SET_MODEM_SERVICE:
3011 return handleRadioSetModemServiceCommand();
3012
3013 case RADIO_GET_MODEM_SERVICE:
3014 return handleRadioGetModemServiceCommand();
3015 }
3016
3017 return -1;
3018 }
arunvoddud7401012022-12-15 16:08:12 +00003019
3020 private int handleCarrierRestrictionStatusCommand() {
3021 try {
3022 String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
3023 if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
3024 mInterface.getModemService()))) {
3025 Log.v(LOG_TAG,
3026 "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
3027 + " checkShellUid fails");
3028 return -1;
3029 }
3030 } catch (RemoteException ex) {
3031 ex.printStackTrace();
3032 }
3033 String callerInfo = getNextOption();
3034 CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
3035 if (TextUtils.isEmpty(callerInfo)) {
3036 // reset the Json content after testing
3037 allowListInfo.updateJsonForTest(null);
3038 return 0;
3039 }
3040 if (callerInfo.startsWith("--")) {
3041 callerInfo = callerInfo.replace("--", "");
3042 }
3043 String params[] = callerInfo.split(",");
3044 StringBuffer jsonStrBuffer = new StringBuffer();
3045 String tokens;
3046 for (int index = 0; index < params.length; index++) {
3047 tokens = convertToJsonString(index, params[index]);
3048 if (TextUtils.isEmpty(tokens)) {
3049 // received wrong format from CTS
3050 if (VDBG) {
3051 Log.v(LOG_TAG,
3052 "handleCarrierRestrictionStatusCommand, Shell command parsing error");
3053 }
3054 return -1;
3055 }
3056 jsonStrBuffer.append(tokens);
3057 }
3058 int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
3059 return result;
3060 }
3061
3062
3063 /**
3064 * Building the string that can be used to build the JsonObject which supports to stub the data
3065 * in CarrierAllowListInfo for CTS testing. sample format is like
3066 * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
3067 */
3068 private String convertToJsonString(int index, String param) {
3069
3070 String token[] = param.split(":");
3071 String jSonString;
3072 switch (index) {
3073 case 0:
3074 jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
3075 break;
3076 case 1:
3077 jSonString =
3078 "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
3079 break;
3080 case 2:
3081 jSonString =
3082 QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
3083 break;
3084 default:
3085 jSonString = null;
3086 }
3087 return jSonString;
3088 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07003089}