blob: 1c41b1d2415263e7553919c8e45b7dd373434076 [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
Hall Liuaa4211e2021-01-20 15:43:39 -080024import android.Manifest;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010025import android.content.Context;
Hall Liuaa4211e2021-01-20 15:43:39 -080026import android.net.Uri;
Hall Liud892bec2018-11-30 14:51:45 -080027import android.os.Binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010028import android.os.PersistableBundle;
Hall Liud892bec2018-11-30 14:51:45 -080029import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070030import android.os.RemoteException;
Brad Ebinger14d467f2021-02-12 06:18:28 +000031import android.os.ServiceSpecificException;
Shuo Qian489d9282020-07-09 11:30:03 -070032import android.provider.BlockedNumberContract;
Jack Yu43c3dfe2021-12-03 23:58:26 -080033import android.provider.DeviceConfig;
Nazanin014f41e2021-05-06 17:26:31 -070034import android.telephony.BarringInfo;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010035import android.telephony.CarrierConfigManager;
Jordan Liu0ccee222021-04-27 11:55:13 -070036import android.telephony.SubscriptionInfo;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070037import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000038import android.telephony.TelephonyManager;
Nazanin014f41e2021-05-06 17:26:31 -070039import android.telephony.TelephonyRegistryManager;
sqian9d4df8b2019-01-15 18:32:07 -080040import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000041import android.telephony.ims.ImsException;
42import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080043import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080044import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000045import android.util.ArrayMap;
46import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070047import android.util.Log;
Nazanin014f41e2021-05-06 17:26:31 -070048import android.util.SparseArray;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070049
Brad Ebinger14d467f2021-02-12 06:18:28 +000050import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070051import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080052import com.android.internal.telephony.Phone;
53import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080054import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080055import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080056import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080057import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080058import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070059
Allen Xue5522892022-03-14 21:04:49 +000060import java.io.IOException;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070061import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080062import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000063import java.util.Arrays;
64import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010065import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080066import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010067import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000068import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010069import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080070import java.util.UUID;
71import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070072
73/**
74 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
75 * permission checks have been done before onCommand was called. Make sure any commands processed
76 * here also contain the appropriate permissions checks.
77 */
78
Hall Liua1548bd2019-12-24 14:14:12 -080079public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070080
81 private static final String LOG_TAG = "TelephonyShellCommand";
82 // Don't commit with this true.
83 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070084 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070085
Hall Liuaa4211e2021-01-20 15:43:39 -080086 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070087 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080088 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080089 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080090 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070091 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000092 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000093 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010094 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080095 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080096 private static final String ENABLE = "enable";
97 private static final String DISABLE = "disable";
98 private static final String QUERY = "query";
99
Hall Liu7135e502021-02-04 16:58:17 -0800100 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -0800101 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -0800102 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -0800103
Brad Ebinger999d3302020-11-25 14:31:39 -0800104 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
105 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
106 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700107 // Used to disable or enable processing of conference event package data from the network.
108 // This is handy for testing scenarios where CEP data does not exist on a network which does
109 // support CEP data.
110 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700111
Hall Liud892bec2018-11-30 14:51:45 -0800112 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800113 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800114
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100115 private static final String CC_GET_VALUE = "get-value";
116 private static final String CC_SET_VALUE = "set-value";
Allen Xue5522892022-03-14 21:04:49 +0000117 private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100118 private static final String CC_CLEAR_VALUES = "clear-values";
119
Hui Wang641e81c2020-10-12 12:14:23 -0700120 private static final String GBA_SUBCOMMAND = "gba";
121 private static final String GBA_SET_SERVICE = "set-service";
122 private static final String GBA_GET_SERVICE = "get-service";
123 private static final String GBA_SET_RELEASE_TIME = "set-release";
124 private static final String GBA_GET_RELEASE_TIME = "get-release";
125
Hui Wang761a6682020-10-31 05:12:53 +0000126 private static final String SINGLE_REGISTATION_CONFIG = "src";
127 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
128 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
129 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
130 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800131 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
132 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800133 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
134 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000135
Tyler Gunn92479152021-01-20 16:30:10 -0800136 private static final String D2D_SUBCOMMAND = "d2d";
137 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800138 private static final String D2D_TRANSPORT = "transport";
Tyler Gunnd4575212021-05-03 14:46:49 -0700139 private static final String D2D_SET_DEVICE_SUPPORT = "set-device-support";
Tyler Gunn92479152021-01-20 16:30:10 -0800140
Nazanin014f41e2021-05-06 17:26:31 -0700141 private static final String BARRING_SUBCOMMAND = "barring";
142 private static final String BARRING_SEND_INFO = "send";
143
James.cf Linbcdf8b32021-01-14 16:44:13 +0800144 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800145 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
Calvin Pana1434322021-07-01 19:27:01 +0800146 private static final String UCE_GET_EAB_CAPABILITY = "get-eab-capability";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800147 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800148 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
149 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000150 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
151 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Line8713a42021-04-29 16:04:26 +0800152 private static final String UCE_REMOVE_REQUEST_DISALLOWED_STATUS =
153 "remove-request-disallowed-status";
James.cf Lin0fc71b02021-05-25 01:37:38 +0800154 private static final String UCE_SET_CAPABILITY_REQUEST_TIMEOUT =
155 "set-capabilities-request-timeout";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800156
jimsun38340bf2021-10-26 15:01:23 +0800157 private static final String RADIO_SUBCOMMAND = "radio";
158 private static final String RADIO_SET_MODEM_SERVICE = "set-modem-service";
159 private static final String RADIO_GET_MODEM_SERVICE = "get-modem-service";
160
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800161 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
162 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
163
Jordan Liu0ccee222021-04-27 11:55:13 -0700164 private static final String DISABLE_PHYSICAL_SUBSCRIPTION = "disable-physical-subscription";
165 private static final String ENABLE_PHYSICAL_SUBSCRIPTION = "enable-physical-subscription";
166
Jack Nudelman644b91a2021-03-12 14:09:48 -0800167 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
168 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
169 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
170
SongFerngWang98dd5992021-05-13 17:50:00 +0800171 private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
172 "get-allowed-network-types-for-users";
173 private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
174 "set-allowed-network-types-for-users";
Jack Yu43c3dfe2021-12-03 23:58:26 -0800175 // Check if telephony new data stack is enabled.
176 private static final String GET_DATA_MODE = "get-data-mode";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700177 // Take advantage of existing methods that already contain permissions checks when possible.
178 private final ITelephony mInterface;
179
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100180 private SubscriptionManager mSubscriptionManager;
181 private CarrierConfigManager mCarrierConfigManager;
Nazanin014f41e2021-05-06 17:26:31 -0700182 private TelephonyRegistryManager mTelephonyRegistryManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700183 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100184
185 private enum CcType {
186 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
Allen Xue5522892022-03-14 21:04:49 +0000187 STRING_ARRAY, PERSISTABLE_BUNDLE, UNKNOWN
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100188 }
189
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100190 private class CcOptionParseResult {
191 public int mSubId;
192 public boolean mPersistent;
193 }
194
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100195 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
196 // keys by looking at the end of the string which usually tells the type.
197 // For instance: "xxxx_string", "xxxx_string_array", etc.
198 // The carrier config keys in this map does not follow this convention. It is therefore not
199 // possible to infer the type for these keys by looking at the string.
200 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
201 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
202 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
203 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
204 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
205 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
206 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
207 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
208 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
209 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
210 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
211 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
212 CcType.STRING);
213 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
214 CcType.STRING_ARRAY);
215 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
216 CcType.STRING_ARRAY);
217 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
218 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
219 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
220 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
221 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
222 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
223 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
224 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
225 }
226 };
227
Brad Ebinger14d467f2021-02-12 06:18:28 +0000228 /**
229 * Map from a shorthand string to the feature tags required in registration required in order
230 * for the RCS feature to be considered "capable".
231 */
232 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
233 static {
234 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
235 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
236 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
237 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
238 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
239 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
240 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
241 FeatureTags.FEATURE_TAG_VIDEO)));
242 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
243 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
244 map.put("call_comp",
245 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
246 map.put("call_comp_mmtel",
247 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
248 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
249 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
250 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
251 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
252 // version
253 map.put("chatbot", new ArraySet<>(Arrays.asList(
254 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
255 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
256 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
257 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
Hyunhofa4ac962022-01-11 12:44:19 +0000258 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000259 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
260 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
261 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
262 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
263 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
Hyunhofa4ac962022-01-11 12:44:19 +0000264 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
Brad Ebinger14d467f2021-02-12 06:18:28 +0000265 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
266 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
267 }
268
269
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100270 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700271 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100272 mCarrierConfigManager =
273 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
274 mSubscriptionManager = (SubscriptionManager)
275 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Nazanin014f41e2021-05-06 17:26:31 -0700276 mTelephonyRegistryManager = (TelephonyRegistryManager)
277 context.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700278 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700279 }
280
281 @Override
282 public int onCommand(String cmd) {
283 if (cmd == null) {
284 return handleDefaultCommands(null);
285 }
286
287 switch (cmd) {
288 case IMS_SUBCOMMAND: {
289 return handleImsCommand();
290 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800291 case RCS_UCE_COMMAND:
292 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800293 case NUMBER_VERIFICATION_SUBCOMMAND:
294 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800295 case EMERGENCY_CALLBACK_MODE:
296 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800297 case EMERGENCY_NUMBER_TEST_MODE:
298 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100299 case CARRIER_CONFIG_SUBCOMMAND: {
300 return handleCcCommand();
301 }
Shuo Qianf5125122019-12-16 17:03:07 -0800302 case DATA_TEST_MODE:
303 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700304 case END_BLOCK_SUPPRESSION:
305 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700306 case GBA_SUBCOMMAND:
307 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800308 case D2D_SUBCOMMAND:
309 return handleD2dCommand();
Nazanin014f41e2021-05-06 17:26:31 -0700310 case BARRING_SUBCOMMAND:
311 return handleBarringCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000312 case SINGLE_REGISTATION_CONFIG:
313 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000314 case RESTART_MODEM:
315 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800316 case CALL_COMPOSER_SUBCOMMAND:
317 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000318 case UNATTENDED_REBOOT:
319 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800320 case HAS_CARRIER_PRIVILEGES_COMMAND:
321 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800322 case THERMAL_MITIGATION_COMMAND:
323 return handleThermalMitigationCommand();
Jordan Liu0ccee222021-04-27 11:55:13 -0700324 case DISABLE_PHYSICAL_SUBSCRIPTION:
325 return handleEnablePhysicalSubscription(false);
326 case ENABLE_PHYSICAL_SUBSCRIPTION:
327 return handleEnablePhysicalSubscription(true);
SongFerngWang98dd5992021-05-13 17:50:00 +0800328 case GET_ALLOWED_NETWORK_TYPES_FOR_USER:
329 case SET_ALLOWED_NETWORK_TYPES_FOR_USER:
330 return handleAllowedNetworkTypesCommand(cmd);
Jack Yu43c3dfe2021-12-03 23:58:26 -0800331 case GET_DATA_MODE:
332 return handleGetDataMode();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700333 default: {
334 return handleDefaultCommands(cmd);
335 }
336 }
337 }
338
339 @Override
340 public void onHelp() {
341 PrintWriter pw = getOutPrintWriter();
342 pw.println("Telephony Commands:");
343 pw.println(" help");
344 pw.println(" Print this help text.");
345 pw.println(" ims");
346 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800347 pw.println(" uce");
348 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800349 pw.println(" emergency-number-test-mode");
350 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700351 pw.println(" end-block-suppression");
352 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800353 pw.println(" data");
354 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100355 pw.println(" cc");
356 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700357 pw.println(" gba");
358 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000359 pw.println(" src");
360 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000361 pw.println(" restart-modem");
362 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000363 pw.println(" unattended-reboot");
364 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800365 pw.println(" has-carrier-privileges [package]");
366 pw.println(" Query carrier privilege status for a package. Prints true or false.");
SongFerngWang98dd5992021-05-13 17:50:00 +0800367 pw.println(" get-allowed-network-types-for-users");
368 pw.println(" Get the Allowed Network Types.");
369 pw.println(" set-allowed-network-types-for-users");
370 pw.println(" Set the Allowed Network Types.");
jimsun38340bf2021-10-26 15:01:23 +0800371 pw.println(" radio");
372 pw.println(" Radio Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700373 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800374 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800375 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700376 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800377 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100378 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700379 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000380 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800381 onHelpD2D();
Jordan Liu0ccee222021-04-27 11:55:13 -0700382 onHelpDisableOrEnablePhysicalSubscription();
SongFerngWang98dd5992021-05-13 17:50:00 +0800383 onHelpAllowedNetworkTypes();
jimsun38340bf2021-10-26 15:01:23 +0800384 onHelpRadio();
Tyler Gunn92479152021-01-20 16:30:10 -0800385 }
386
387 private void onHelpD2D() {
388 PrintWriter pw = getOutPrintWriter();
389 pw.println("D2D Comms Commands:");
390 pw.println(" d2d send TYPE VALUE");
391 pw.println(" Sends a D2D message of specified type and value.");
392 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
393 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
394 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
395 MESSAGE_CALL_AUDIO_CODEC));
396 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
397 + Communicator.messageToString(
398 MESSAGE_DEVICE_BATTERY_STATE));
399 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
400 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800401 pw.println(" d2d transport TYPE");
402 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
403 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Tyler Gunnd4575212021-05-03 14:46:49 -0700404 pw.println(" d2d set-device-support true/default");
405 pw.println(" true - forces device support to be enabled for D2D.");
406 pw.println(" default - clear any previously set force-enable of D2D, reverting to ");
407 pw.println(" the current device's configuration.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700408 }
409
Nazanin014f41e2021-05-06 17:26:31 -0700410 private void onHelpBarring() {
411 PrintWriter pw = getOutPrintWriter();
412 pw.println("Barring Commands:");
413 pw.println(" barring send -s SLOT_ID -b BARRING_TYPE -c IS_CONDITIONALLY_BARRED"
414 + " -t CONDITIONAL_BARRING_TIME_SECS");
415 pw.println(" Notifies of a barring info change for the specified slot id.");
416 pw.println(" BARRING_TYPE: 0 for BARRING_TYPE_NONE");
417 pw.println(" BARRING_TYPE: 1 for BARRING_TYPE_UNCONDITIONAL");
418 pw.println(" BARRING_TYPE: 2 for BARRING_TYPE_CONDITIONAL");
419 pw.println(" BARRING_TYPE: -1 for BARRING_TYPE_UNKNOWN");
420 }
421
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700422 private void onHelpIms() {
423 PrintWriter pw = getOutPrintWriter();
424 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800425 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700426 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
427 pw.println(" ImsService. Options are:");
428 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
429 pw.println(" is specified, it will choose the default voice SIM slot.");
430 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
431 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800432 pw.println(" -f: Set the feature that this override if for, if no option is");
433 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700434 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
435 pw.println(" Gets the package name of the currently defined ImsService.");
436 pw.println(" Options are:");
437 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
438 pw.println(" is specified, it will choose the default voice SIM slot.");
439 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000440 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800441 pw.println(" -f: The feature type that the query will be requested for. If none is");
442 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800443 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
444 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
445 pw.println(" configuration overrides. Options are:");
446 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
447 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700448 pw.println(" ims enable [-s SLOT_ID]");
449 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
450 pw.println(" if none is specified.");
451 pw.println(" ims disable [-s SLOT_ID]");
452 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
453 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700454 pw.println(" ims conference-event-package [enable/disable]");
455 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700456 }
457
James.cf Linbcdf8b32021-01-14 16:44:13 +0800458 private void onHelpUce() {
459 PrintWriter pw = getOutPrintWriter();
460 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800461 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
462 pw.println(" Get the EAB contacts from the EAB database.");
463 pw.println(" Options are:");
464 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
465 pw.println(" Expected output format :");
466 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800467 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
468 pw.println(" Remove the EAB contacts from the EAB database.");
469 pw.println(" Options are:");
470 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
471 pw.println(" is specified, it will choose the default voice SIM slot.");
472 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800473 pw.println(" uce get-device-enabled");
474 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
475 pw.println(" uce set-device-enabled true|false");
476 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
477 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000478 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
479 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
480 pw.println(" Options are:");
481 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
482 pw.println(" is specified, it will choose the default voice SIM slot.");
483 pw.println(" add [CAPABILITY]: add a new capability");
484 pw.println(" remove [CAPABILITY]: remove a capability");
485 pw.println(" clear: clear all capability overrides");
486 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
487 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
488 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
489 pw.println(" chatbot_sa, chatbot_role] as well as full length");
490 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
491 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
492 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
493 pw.println(" PUBLISH is active");
James.cf Line8713a42021-04-29 16:04:26 +0800494 pw.println(" uce remove-request-disallowed-status [-s SLOT_ID]");
495 pw.println(" Remove the UCE is disallowed to execute UCE requests status");
James.cf Lin0fc71b02021-05-25 01:37:38 +0800496 pw.println(" uce set-capabilities-request-timeout [-s SLOT_ID] [REQUEST_TIMEOUT_MS]");
497 pw.println(" Set the timeout for contact capabilities request.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800498 }
499
Hall Liud892bec2018-11-30 14:51:45 -0800500 private void onHelpNumberVerification() {
501 PrintWriter pw = getOutPrintWriter();
502 pw.println("Number verification commands");
503 pw.println(" numverify override-package PACKAGE_NAME;");
504 pw.println(" Set the authorized package for number verification.");
505 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800506 pw.println(" numverify fake-call NUMBER;");
507 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
508 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800509 }
510
Jack Nudelman644b91a2021-03-12 14:09:48 -0800511 private void onHelpThermalMitigation() {
512 PrintWriter pw = getOutPrintWriter();
513 pw.println("Thermal mitigation commands");
514 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
515 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
516 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
517 pw.println(" Remove the package from one of the authorized packages for thermal "
518 + "mitigation.");
519 }
520
Jordan Liu0ccee222021-04-27 11:55:13 -0700521 private void onHelpDisableOrEnablePhysicalSubscription() {
522 PrintWriter pw = getOutPrintWriter();
523 pw.println("Disable or enable a physical subscription");
524 pw.println(" disable-physical-subscription SUB_ID");
525 pw.println(" Disable the physical subscription with the provided subId, if allowed.");
526 pw.println(" enable-physical-subscription SUB_ID");
527 pw.println(" Enable the physical subscription with the provided subId, if allowed.");
528 }
529
Shuo Qianf5125122019-12-16 17:03:07 -0800530 private void onHelpDataTestMode() {
531 PrintWriter pw = getOutPrintWriter();
532 pw.println("Mobile Data Test Mode Commands:");
533 pw.println(" data enable: enable mobile data connectivity");
534 pw.println(" data disable: disable mobile data connectivity");
535 }
536
sqian9d4df8b2019-01-15 18:32:07 -0800537 private void onHelpEmergencyNumber() {
538 PrintWriter pw = getOutPrintWriter();
539 pw.println("Emergency Number Test Mode Commands:");
540 pw.println(" emergency-number-test-mode ");
541 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
542 + " the test mode");
543 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700544 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800545 pw.println(" -c: clear the emergency number list in the test mode.");
546 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700547 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800548 pw.println(" -p: get the full emergency number list in the test mode.");
549 }
550
Shuo Qian489d9282020-07-09 11:30:03 -0700551 private void onHelpEndBlockSupperssion() {
552 PrintWriter pw = getOutPrintWriter();
553 pw.println("End Block Suppression command:");
554 pw.println(" end-block-suppression: disable suppressing blocking by contact");
555 pw.println(" with emergency services.");
556 }
557
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100558 private void onHelpCc() {
559 PrintWriter pw = getOutPrintWriter();
560 pw.println("Carrier Config Commands:");
561 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
562 pw.println(" Print carrier config values.");
563 pw.println(" Options are:");
564 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
565 pw.println(" is specified, it will choose the default voice SIM slot.");
566 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
567 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100568 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100569 pw.println(" Set carrier config KEY to NEW_VALUE.");
570 pw.println(" Options are:");
571 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
572 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100573 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100574 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
575 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
576 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
577 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
Allen Xue5522892022-03-14 21:04:49 +0000578 pw.println(" cc set-values-from-xml [-s SLOT_ID] [-p] < XML_FILE_PATH");
579 pw.println(" Set carrier config based on the contents of the XML_FILE. File must be");
580 pw.println(" provided through standard input and follow CarrierConfig XML format.");
581 pw.println(" Example: packages/apps/CarrierConfig/assets/*.xml");
582 pw.println(" Options are:");
583 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
584 pw.println(" is specified, it will choose the default voice SIM slot.");
585 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100586 pw.println(" cc clear-values [-s SLOT_ID]");
587 pw.println(" Clear all carrier override values that has previously been set");
Allen Xue5522892022-03-14 21:04:49 +0000588 pw.println(" with set-value or set-values-from-xml");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100589 pw.println(" Options are:");
590 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
591 pw.println(" is specified, it will choose the default voice SIM slot.");
592 }
593
Hui Wang641e81c2020-10-12 12:14:23 -0700594 private void onHelpGba() {
595 PrintWriter pw = getOutPrintWriter();
596 pw.println("Gba Commands:");
597 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
598 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
599 pw.println(" Options are:");
600 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
601 pw.println(" is specified, it will choose the default voice SIM slot.");
602 pw.println(" gba get-service [-s SLOT_ID]");
603 pw.println(" Gets the package name of the currently defined GbaService.");
604 pw.println(" Options are:");
605 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
606 pw.println(" is specified, it will choose the default voice SIM slot.");
607 pw.println(" gba set-release [-s SLOT_ID] n");
608 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
609 pw.println(" Do not release/unbind if n is -1.");
610 pw.println(" Options are:");
611 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
612 pw.println(" is specified, it will choose the default voice SIM slot.");
613 pw.println(" gba get-release [-s SLOT_ID]");
614 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
615 pw.println(" Options are:");
616 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
617 pw.println(" is specified, it will choose the default voice SIM slot.");
618 }
619
Hui Wang761a6682020-10-31 05:12:53 +0000620 private void onHelpSrc() {
621 PrintWriter pw = getOutPrintWriter();
622 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800623 pw.println(" src set-test-enabled true|false");
624 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
625 pw.println(" The value could be true, false, or null(undefined).");
626 pw.println(" src get-test-enabled");
627 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000628 pw.println(" src set-device-enabled true|false|null");
629 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
630 pw.println(" The value could be true, false, or null(undefined).");
631 pw.println(" src get-device-enabled");
632 pw.println(" Gets the device config for RCS VoLTE single registration.");
633 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
634 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
635 pw.println(" The value could be true, false, or null(undefined).");
636 pw.println(" Options are:");
637 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
638 pw.println(" is specified, it will choose the default voice SIM slot.");
639 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
640 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
641 pw.println(" Options are:");
642 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
643 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800644 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
645 pw.println(" Sets ims feature validation result.");
646 pw.println(" The value could be true, false, or null(undefined).");
647 pw.println(" Options are:");
648 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
649 pw.println(" is specified, it will choose the default voice SIM slot.");
650 pw.println(" src get-feature-validation [-s SLOT_ID]");
651 pw.println(" Gets ims feature validation override value.");
652 pw.println(" Options are:");
653 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
654 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000655 }
656
SongFerngWang98dd5992021-05-13 17:50:00 +0800657 private void onHelpAllowedNetworkTypes() {
658 PrintWriter pw = getOutPrintWriter();
659 pw.println("Allowed Network Types Commands:");
660 pw.println(" get-allowed-network-types-for-users [-s SLOT_ID]");
661 pw.println(" Print allowed network types value.");
662 pw.println(" Options are:");
663 pw.println(" -s: The SIM slot ID to read allowed network types value for. If no");
664 pw.println(" option is specified, it will choose the default voice SIM slot.");
665 pw.println(" set-allowed-network-types-for-users [-s SLOT_ID] [NETWORK_TYPES_BITMASK]");
666 pw.println(" Sets allowed network types to NETWORK_TYPES_BITMASK.");
667 pw.println(" Options are:");
668 pw.println(" -s: The SIM slot ID to set allowed network types value for. If no");
669 pw.println(" option is specified, it will choose the default voice SIM slot.");
670 pw.println(" NETWORK_TYPES_BITMASK specifies the new network types value and this type");
671 pw.println(" is bitmask in binary format. Reference the NetworkTypeBitMask");
672 pw.println(" at TelephonyManager.java");
673 pw.println(" For example:");
674 pw.println(" NR only : 10000000000000000000");
675 pw.println(" NR|LTE : 11000001000000000000");
676 pw.println(" NR|LTE|CDMA|EVDO|GSM|WCDMA : 11001111101111111111");
677 pw.println(" LTE|CDMA|EVDO|GSM|WCDMA : 01001111101111111111");
678 pw.println(" LTE only : 01000001000000000000");
679 }
680
jimsun38340bf2021-10-26 15:01:23 +0800681 private void onHelpRadio() {
682 PrintWriter pw = getOutPrintWriter();
683 pw.println("Radio Commands:");
684 pw.println(" radio set-modem-service [-s SERVICE_NAME]");
685 pw.println(" Sets the class name of modem service defined in SERVICE_NAME");
686 pw.println(" to be the bound. Options are:");
687 pw.println(" -s: the service name that the modem service should be bound for.");
688 pw.println(" If no option is specified, it will bind to the default.");
689 pw.println(" radio get-modem-service");
690 pw.println(" Gets the service name of the currently defined modem service.");
691 pw.println(" If it is binding to default, 'default' returns.");
692 pw.println(" If it doesn't bind to any modem service for some reasons,");
693 pw.println(" the result would be 'unknown'.");
694 }
695
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700696 private int handleImsCommand() {
697 String arg = getNextArg();
698 if (arg == null) {
699 onHelpIms();
700 return 0;
701 }
702
703 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800704 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700705 return handleImsSetServiceCommand();
706 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800707 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700708 return handleImsGetServiceCommand();
709 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800710 case IMS_CLEAR_SERVICE_OVERRIDE: {
711 return handleImsClearCarrierServiceCommand();
712 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800713 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700714 return handleEnableIms();
715 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800716 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700717 return handleDisableIms();
718 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700719 case IMS_CEP: {
720 return handleCepChange();
721 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700722 }
723
724 return -1;
725 }
726
Shuo Qianf5125122019-12-16 17:03:07 -0800727 private int handleDataTestModeCommand() {
728 PrintWriter errPw = getErrPrintWriter();
729 String arg = getNextArgRequired();
730 if (arg == null) {
731 onHelpDataTestMode();
732 return 0;
733 }
734 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800735 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800736 try {
Sarah Chin706acd92022-03-31 21:16:48 -0700737 mInterface.enableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800738 } catch (RemoteException ex) {
739 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
740 errPw.println("Exception: " + ex.getMessage());
741 return -1;
742 }
743 break;
744 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800745 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800746 try {
Sarah Chin706acd92022-03-31 21:16:48 -0700747 mInterface.disableDataConnectivity(mContext.getOpPackageName());
Shuo Qianf5125122019-12-16 17:03:07 -0800748 } catch (RemoteException ex) {
749 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
750 errPw.println("Exception: " + ex.getMessage());
751 return -1;
752 }
753 break;
754 }
755 default:
756 onHelpDataTestMode();
757 break;
758 }
759 return 0;
760 }
761
Shuo Qianccbaf742021-02-22 18:32:21 -0800762 private int handleEmergencyCallbackModeCommand() {
763 PrintWriter errPw = getErrPrintWriter();
764 try {
765 mInterface.startEmergencyCallbackMode();
766 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
767 } catch (RemoteException ex) {
768 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
769 errPw.println("Exception: " + ex.getMessage());
770 return -1;
771 }
772 return 0;
773 }
774
sqian9d4df8b2019-01-15 18:32:07 -0800775 private int handleEmergencyNumberTestModeCommand() {
776 PrintWriter errPw = getErrPrintWriter();
777 String opt = getNextOption();
778 if (opt == null) {
779 onHelpEmergencyNumber();
780 return 0;
781 }
782
783 switch (opt) {
784 case "-a": {
785 String emergencyNumberCmd = getNextArgRequired();
786 if (emergencyNumberCmd == null
787 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700788 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800789 + " to be specified after -a in the command ");
790 return -1;
791 }
792 try {
793 mInterface.updateEmergencyNumberListTestMode(
794 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
795 new EmergencyNumber(emergencyNumberCmd, "", "",
796 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
797 new ArrayList<String>(),
798 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
799 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
800 } catch (RemoteException ex) {
801 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
802 + ", error " + ex.getMessage());
803 errPw.println("Exception: " + ex.getMessage());
804 return -1;
805 }
806 break;
807 }
808 case "-c": {
809 try {
810 mInterface.updateEmergencyNumberListTestMode(
811 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
812 } catch (RemoteException ex) {
813 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
814 errPw.println("Exception: " + ex.getMessage());
815 return -1;
816 }
817 break;
818 }
819 case "-r": {
820 String emergencyNumberCmd = getNextArgRequired();
821 if (emergencyNumberCmd == null
822 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700823 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800824 + " to be specified after -r in the command ");
825 return -1;
826 }
827 try {
828 mInterface.updateEmergencyNumberListTestMode(
829 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
830 new EmergencyNumber(emergencyNumberCmd, "", "",
831 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
832 new ArrayList<String>(),
833 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
834 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
835 } catch (RemoteException ex) {
836 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
837 + ", error " + ex.getMessage());
838 errPw.println("Exception: " + ex.getMessage());
839 return -1;
840 }
841 break;
842 }
843 case "-p": {
844 try {
845 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
846 } catch (RemoteException ex) {
847 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
848 errPw.println("Exception: " + ex.getMessage());
849 return -1;
850 }
851 break;
852 }
853 default:
854 onHelpEmergencyNumber();
855 break;
856 }
857 return 0;
858 }
859
Hall Liud892bec2018-11-30 14:51:45 -0800860 private int handleNumberVerificationCommand() {
861 String arg = getNextArg();
862 if (arg == null) {
863 onHelpNumberVerification();
864 return 0;
865 }
866
Hall Liuca5af3a2018-12-04 16:58:23 -0800867 if (!checkShellUid()) {
868 return -1;
869 }
870
Hall Liud892bec2018-11-30 14:51:45 -0800871 switch (arg) {
872 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800873 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
874 return 0;
875 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800876 case NUMBER_VERIFICATION_FAKE_CALL: {
877 boolean val = NumberVerificationManager.getInstance()
878 .checkIncomingCall(getNextArg());
879 getOutPrintWriter().println(val ? "1" : "0");
880 return 0;
881 }
Hall Liud892bec2018-11-30 14:51:45 -0800882 }
883
884 return -1;
885 }
886
Jordan Liu0ccee222021-04-27 11:55:13 -0700887 private boolean subIsEsim(int subId) {
888 SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(subId);
889 if (info != null) {
890 return info.isEmbedded();
891 }
892 return false;
893 }
894
895 private int handleEnablePhysicalSubscription(boolean enable) {
896 PrintWriter errPw = getErrPrintWriter();
897 int subId = 0;
898 try {
899 subId = Integer.parseInt(getNextArgRequired());
900 } catch (NumberFormatException e) {
901 errPw.println((enable ? "enable" : "disable")
902 + "-physical-subscription requires an integer as a subId.");
903 return -1;
904 }
905 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
906 // non user build.
907 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
908 errPw.println("cc: Permission denied.");
909 return -1;
910 }
911 // Verify that the subId represents a physical sub
912 if (subIsEsim(subId)) {
913 errPw.println("SubId " + subId + " is not for a physical subscription");
914 return -1;
915 }
916 Log.d(LOG_TAG, (enable ? "Enabling" : "Disabling")
917 + " physical subscription with subId=" + subId);
918 mSubscriptionManager.setUiccApplicationsEnabled(subId, enable);
919 return 0;
920 }
921
Jack Nudelman644b91a2021-03-12 14:09:48 -0800922 private int handleThermalMitigationCommand() {
923 String arg = getNextArg();
924 String packageName = getNextArg();
925 if (arg == null || packageName == null) {
926 onHelpThermalMitigation();
927 return 0;
928 }
929
930 if (!checkShellUid()) {
931 return -1;
932 }
933
934 switch (arg) {
935 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
936 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
937 return 0;
938 }
939 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
940 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
941 mContext);
942 return 0;
943 }
944 default:
945 onHelpThermalMitigation();
946 }
947
948 return -1;
949
950 }
951
Tyler Gunn92479152021-01-20 16:30:10 -0800952 private int handleD2dCommand() {
953 String arg = getNextArg();
954 if (arg == null) {
955 onHelpD2D();
956 return 0;
957 }
958
959 switch (arg) {
960 case D2D_SEND: {
961 return handleD2dSendCommand();
962 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800963 case D2D_TRANSPORT: {
964 return handleD2dTransportCommand();
965 }
Tyler Gunnd4575212021-05-03 14:46:49 -0700966 case D2D_SET_DEVICE_SUPPORT: {
967 return handleD2dDeviceSupportedCommand();
968 }
Tyler Gunn92479152021-01-20 16:30:10 -0800969 }
970
971 return -1;
972 }
973
974 private int handleD2dSendCommand() {
975 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800976 int messageType = -1;
977 int messageValue = -1;
978
Tyler Gunn92479152021-01-20 16:30:10 -0800979 String arg = getNextArg();
980 if (arg == null) {
981 onHelpD2D();
982 return 0;
983 }
984 try {
985 messageType = Integer.parseInt(arg);
986 } catch (NumberFormatException e) {
987 errPw.println("message type must be a valid integer");
988 return -1;
989 }
990
991 arg = getNextArg();
992 if (arg == null) {
993 onHelpD2D();
994 return 0;
995 }
996 try {
997 messageValue = Integer.parseInt(arg);
998 } catch (NumberFormatException e) {
999 errPw.println("message value must be a valid integer");
1000 return -1;
1001 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08001002
Tyler Gunn92479152021-01-20 16:30:10 -08001003 try {
1004 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
1005 } catch (RemoteException e) {
1006 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
1007 errPw.println("Exception: " + e.getMessage());
1008 return -1;
1009 }
1010
1011 return 0;
1012 }
1013
Tyler Gunnbabbda02021-02-10 11:05:02 -08001014 private int handleD2dTransportCommand() {
1015 PrintWriter errPw = getErrPrintWriter();
1016
1017 String arg = getNextArg();
1018 if (arg == null) {
1019 onHelpD2D();
1020 return 0;
1021 }
1022
1023 try {
1024 mInterface.setActiveDeviceToDeviceTransport(arg);
1025 } catch (RemoteException e) {
1026 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
1027 errPw.println("Exception: " + e.getMessage());
1028 return -1;
1029 }
1030 return 0;
1031 }
Nazanin014f41e2021-05-06 17:26:31 -07001032 private int handleBarringCommand() {
1033 String arg = getNextArg();
1034 if (arg == null) {
1035 onHelpBarring();
1036 return 0;
1037 }
1038
1039 switch (arg) {
1040 case BARRING_SEND_INFO: {
1041 return handleBarringSendCommand();
1042 }
1043 }
1044 return -1;
1045 }
1046
1047 private int handleBarringSendCommand() {
1048 PrintWriter errPw = getErrPrintWriter();
1049 int slotId = getDefaultSlot();
1050 int subId = SubscriptionManager.getSubId(slotId)[0];
1051 @BarringInfo.BarringServiceInfo.BarringType int barringType =
1052 BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
1053 boolean isConditionallyBarred = false;
1054 int conditionalBarringTimeSeconds = 0;
1055
1056 String opt;
1057 while ((opt = getNextOption()) != null) {
1058 switch (opt) {
1059 case "-s": {
1060 try {
1061 slotId = Integer.parseInt(getNextArgRequired());
1062 subId = SubscriptionManager.getSubId(slotId)[0];
1063 } catch (NumberFormatException e) {
1064 errPw.println("barring send requires an integer as a SLOT_ID.");
1065 return -1;
1066 }
1067 break;
1068 }
1069 case "-b": {
1070 try {
1071 barringType = Integer.parseInt(getNextArgRequired());
1072 if (barringType < -1 || barringType > 2) {
1073 throw new NumberFormatException();
1074 }
1075
1076 } catch (NumberFormatException e) {
1077 errPw.println("barring send requires an integer in range [-1,2] as "
1078 + "a BARRING_TYPE.");
1079 return -1;
1080 }
1081 break;
1082 }
1083 case "-c": {
1084 try {
1085 isConditionallyBarred = Boolean.parseBoolean(getNextArgRequired());
1086 } catch (Exception e) {
1087 errPw.println("barring send requires a boolean after -c indicating"
1088 + " conditional barring");
1089 return -1;
1090 }
1091 break;
1092 }
1093 case "-t": {
1094 try {
1095 conditionalBarringTimeSeconds = Integer.parseInt(getNextArgRequired());
1096 } catch (NumberFormatException e) {
1097 errPw.println("barring send requires an integer for time of barring"
1098 + " in seconds after -t for conditional barring");
1099 return -1;
1100 }
1101 break;
1102 }
1103 }
1104 }
1105 SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
1106 BarringInfo.BarringServiceInfo bsi = new BarringInfo.BarringServiceInfo(
1107 barringType, isConditionallyBarred, 0, conditionalBarringTimeSeconds);
1108 barringServiceInfos.append(0, bsi);
1109 BarringInfo barringInfo = new BarringInfo(null, barringServiceInfos);
1110 try {
1111 mTelephonyRegistryManager.notifyBarringInfoChanged(slotId, subId, barringInfo);
1112 } catch (Exception e) {
1113 Log.w(LOG_TAG, "barring send error: " + e.getMessage());
1114 errPw.println("Exception: " + e.getMessage());
1115 return -1;
1116 }
1117 return 0;
1118 }
Tyler Gunnbabbda02021-02-10 11:05:02 -08001119
Tyler Gunnd4575212021-05-03 14:46:49 -07001120 private int handleD2dDeviceSupportedCommand() {
1121 PrintWriter errPw = getErrPrintWriter();
1122
1123 String arg = getNextArg();
1124 if (arg == null) {
1125 onHelpD2D();
1126 return 0;
1127 }
1128
1129 boolean isEnabled = "true".equals(arg.toLowerCase());
1130 try {
1131 mInterface.setDeviceToDeviceForceEnabled(isEnabled);
1132 } catch (RemoteException e) {
1133 Log.w(LOG_TAG, "Error forcing D2D enabled: " + e.getMessage());
1134 errPw.println("Exception: " + e.getMessage());
1135 return -1;
1136 }
1137 return 0;
1138 }
1139
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001140 // ims set-ims-service
1141 private int handleImsSetServiceCommand() {
1142 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001143 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001144 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001145 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001146
1147 String opt;
1148 while ((opt = getNextOption()) != null) {
1149 switch (opt) {
1150 case "-s": {
1151 try {
1152 slotId = Integer.parseInt(getNextArgRequired());
1153 } catch (NumberFormatException e) {
1154 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1155 return -1;
1156 }
1157 break;
1158 }
1159 case "-c": {
1160 isCarrierService = true;
1161 break;
1162 }
1163 case "-d": {
1164 isCarrierService = false;
1165 break;
1166 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001167 case "-f": {
1168 String featureString = getNextArgRequired();
1169 String[] features = featureString.split(",");
1170 for (int i = 0; i < features.length; i++) {
1171 try {
1172 Integer result = Integer.parseInt(features[i]);
1173 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
1174 || result >= ImsFeature.FEATURE_MAX) {
1175 errPw.println("ims set-ims-service -f " + result
1176 + " is an invalid feature.");
1177 return -1;
1178 }
1179 featuresList.add(result);
1180 } catch (NumberFormatException e) {
1181 errPw.println("ims set-ims-service -f tried to parse " + features[i]
1182 + " as an integer.");
1183 return -1;
1184 }
1185 }
1186 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001187 }
1188 }
1189 // Mandatory param, either -c or -d
1190 if (isCarrierService == null) {
1191 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
1192 return -1;
1193 }
1194
1195 String packageName = getNextArg();
1196
1197 try {
1198 if (packageName == null) {
1199 packageName = "";
1200 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001201 int[] featureArray = new int[featuresList.size()];
1202 for (int i = 0; i < featuresList.size(); i++) {
1203 featureArray[i] = featuresList.get(i);
1204 }
1205 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
1206 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001207 if (VDBG) {
1208 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001209 + (isCarrierService ? "-c " : "-d ")
1210 + "-f " + featuresList + " "
1211 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001212 }
1213 getOutPrintWriter().println(result);
1214 } catch (RemoteException e) {
1215 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001216 + (isCarrierService ? "-c " : "-d ")
1217 + "-f " + featuresList + " "
1218 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001219 errPw.println("Exception: " + e.getMessage());
1220 return -1;
1221 }
1222 return 0;
1223 }
1224
Brad Ebinger999d3302020-11-25 14:31:39 -08001225 // ims clear-ims-service-override
1226 private int handleImsClearCarrierServiceCommand() {
1227 PrintWriter errPw = getErrPrintWriter();
1228 int slotId = getDefaultSlot();
1229
1230 String opt;
1231 while ((opt = getNextOption()) != null) {
1232 switch (opt) {
1233 case "-s": {
1234 try {
1235 slotId = Integer.parseInt(getNextArgRequired());
1236 } catch (NumberFormatException e) {
1237 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1238 return -1;
1239 }
1240 break;
1241 }
1242 }
1243 }
1244
1245 try {
1246 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
1247 if (VDBG) {
1248 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1249 + ", result=" + result);
1250 }
1251 getOutPrintWriter().println(result);
1252 } catch (RemoteException e) {
1253 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
1254 + ", error" + e.getMessage());
1255 errPw.println("Exception: " + e.getMessage());
1256 return -1;
1257 }
1258 return 0;
1259 }
1260
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001261 // ims get-ims-service
1262 private int handleImsGetServiceCommand() {
1263 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001264 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001265 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -08001266 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001267
1268 String opt;
1269 while ((opt = getNextOption()) != null) {
1270 switch (opt) {
1271 case "-s": {
1272 try {
1273 slotId = Integer.parseInt(getNextArgRequired());
1274 } catch (NumberFormatException e) {
1275 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1276 return -1;
1277 }
1278 break;
1279 }
1280 case "-c": {
1281 isCarrierService = true;
1282 break;
1283 }
1284 case "-d": {
1285 isCarrierService = false;
1286 break;
1287 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001288 case "-f": {
1289 try {
1290 featureType = Integer.parseInt(getNextArg());
1291 } catch (NumberFormatException e) {
1292 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1293 return -1;
1294 }
1295 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1296 || featureType >= ImsFeature.FEATURE_MAX) {
1297 errPw.println("ims get-ims-service -f invalid feature.");
1298 return -1;
1299 }
1300 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001301 }
1302 }
1303 // Mandatory param, either -c or -d
1304 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001305 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001306 return -1;
1307 }
1308
1309 String result;
1310 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001311 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001312 } catch (RemoteException e) {
1313 return -1;
1314 }
1315 if (VDBG) {
1316 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001317 + (isCarrierService ? "-c " : "-d ")
1318 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1319 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001320 }
1321 getOutPrintWriter().println(result);
1322 return 0;
1323 }
1324
1325 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001326 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001327 String opt;
1328 while ((opt = getNextOption()) != null) {
1329 switch (opt) {
1330 case "-s": {
1331 try {
1332 slotId = Integer.parseInt(getNextArgRequired());
1333 } catch (NumberFormatException e) {
1334 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1335 return -1;
1336 }
1337 break;
1338 }
1339 }
1340 }
1341 try {
1342 mInterface.enableIms(slotId);
1343 } catch (RemoteException e) {
1344 return -1;
1345 }
1346 if (VDBG) {
1347 Log.v(LOG_TAG, "ims enable -s " + slotId);
1348 }
1349 return 0;
1350 }
1351
1352 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001353 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001354 String opt;
1355 while ((opt = getNextOption()) != null) {
1356 switch (opt) {
1357 case "-s": {
1358 try {
1359 slotId = Integer.parseInt(getNextArgRequired());
1360 } catch (NumberFormatException e) {
1361 getErrPrintWriter().println(
1362 "ims disable requires an integer as a SLOT_ID.");
1363 return -1;
1364 }
1365 break;
1366 }
1367 }
1368 }
1369 try {
1370 mInterface.disableIms(slotId);
1371 } catch (RemoteException e) {
1372 return -1;
1373 }
1374 if (VDBG) {
1375 Log.v(LOG_TAG, "ims disable -s " + slotId);
1376 }
1377 return 0;
1378 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001379
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001380 private int handleCepChange() {
1381 Log.i(LOG_TAG, "handleCepChange");
1382 String opt = getNextArg();
1383 if (opt == null) {
1384 return -1;
1385 }
1386 boolean isCepEnabled = opt.equals("enable");
1387
1388 try {
1389 mInterface.setCepEnabled(isCepEnabled);
1390 } catch (RemoteException e) {
1391 return -1;
1392 }
1393 return 0;
1394 }
1395
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001396 private int getDefaultSlot() {
1397 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1398 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1399 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1400 // If there is no default, default to slot 0.
1401 slotId = DEFAULT_PHONE_ID;
1402 }
1403 return slotId;
1404 }
sqian2fff4a32018-11-05 14:18:37 -08001405
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001406 // Parse options related to Carrier Config Commands.
1407 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001408 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001409 CcOptionParseResult result = new CcOptionParseResult();
1410 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1411 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001412
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001413 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001414 while ((opt = getNextOption()) != null) {
1415 switch (opt) {
1416 case "-s": {
1417 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001418 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1419 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1420 errPw.println(tag + "No valid subscription found.");
1421 return null;
1422 }
1423
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001424 } catch (IllegalArgumentException e) {
1425 // Missing slot id
1426 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001427 return null;
1428 }
1429 break;
1430 }
1431 case "-p": {
1432 if (allowOptionPersistent) {
1433 result.mPersistent = true;
1434 } else {
1435 errPw.println(tag + "Unexpected option " + opt);
1436 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001437 }
1438 break;
1439 }
1440 default: {
1441 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001442 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001443 }
1444 }
1445 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001446 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001447 }
1448
1449 private int slotStringToSubId(String tag, String slotString) {
1450 int slotId = -1;
1451 try {
1452 slotId = Integer.parseInt(slotString);
1453 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001454 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1455 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1456 }
1457
1458 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001459 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1460 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1461 }
1462
Qiong Liuf25799b2020-09-10 10:13:46 +08001463 Phone phone = PhoneFactory.getPhone(slotId);
1464 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001465 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1466 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1467 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001468 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001469 }
1470
Hall Liud892bec2018-11-30 14:51:45 -08001471 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001472 // adb can run as root or as shell, depending on whether the device is rooted.
1473 return Binder.getCallingUid() == Process.SHELL_UID
1474 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001475 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001476
1477 private int handleCcCommand() {
1478 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1479 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001480 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001481 getErrPrintWriter().println("cc: Permission denied.");
1482 return -1;
1483 }
1484
1485 String arg = getNextArg();
1486 if (arg == null) {
1487 onHelpCc();
1488 return 0;
1489 }
1490
1491 switch (arg) {
1492 case CC_GET_VALUE: {
1493 return handleCcGetValue();
1494 }
1495 case CC_SET_VALUE: {
1496 return handleCcSetValue();
1497 }
Allen Xue5522892022-03-14 21:04:49 +00001498 case CC_SET_VALUES_FROM_XML: {
1499 return handleCcSetValuesFromXml();
1500 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001501 case CC_CLEAR_VALUES: {
1502 return handleCcClearValues();
1503 }
1504 default: {
1505 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1506 }
1507 }
1508 return -1;
1509 }
1510
1511 // cc get-value
1512 private int handleCcGetValue() {
1513 PrintWriter errPw = getErrPrintWriter();
1514 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1515 String key = null;
1516
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001517 // Parse all options
Allen Xue5522892022-03-14 21:04:49 +00001518 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001519 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001520 return -1;
1521 }
1522
1523 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001524 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001525 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001526 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001527 return -1;
1528 }
1529
1530 // Get the key.
1531 key = getNextArg();
1532 if (key != null) {
1533 // A key was provided. Verify if it is a valid key
1534 if (!bundle.containsKey(key)) {
1535 errPw.println(tag + key + " is not a valid key.");
1536 return -1;
1537 }
1538
1539 // Print the carrier config value for key.
1540 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1541 } else {
1542 // No key provided. Show all values.
1543 // Iterate over a sorted list of all carrier config keys and print them.
1544 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1545 for (String k : sortedSet) {
1546 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1547 }
1548 }
1549 return 0;
1550 }
1551
1552 // cc set-value
1553 private int handleCcSetValue() {
1554 PrintWriter errPw = getErrPrintWriter();
1555 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1556
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001557 // Parse all options
Allen Xue5522892022-03-14 21:04:49 +00001558 CcOptionParseResult options = parseCcOptions(tag, true);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001559 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001560 return -1;
1561 }
1562
1563 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001564 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001565 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001566 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001567 return -1;
1568 }
1569
1570 // Get the key.
1571 String key = getNextArg();
1572 if (key == null || key.equals("")) {
1573 errPw.println(tag + "KEY is missing");
1574 return -1;
1575 }
1576
1577 // Verify if the key is valid
1578 if (!originalValues.containsKey(key)) {
1579 errPw.println(tag + key + " is not a valid key.");
1580 return -1;
1581 }
1582
1583 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1584 ArrayList<String> valueList = new ArrayList<String>();
1585 while (peekNextArg() != null) {
1586 valueList.add(getNextArg());
1587 }
1588
1589 // Find the type of the carrier config value
1590 CcType type = getType(tag, key, originalValues);
1591 if (type == CcType.UNKNOWN) {
1592 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1593 return -1;
1594 }
Allen Xue5522892022-03-14 21:04:49 +00001595 if (type == CcType.PERSISTABLE_BUNDLE) {
1596 errPw.println(tag + "ERROR: Overriding of persistable bundle type is not supported. "
1597 + "Use set-values-from-xml instead.");
1598 return -1;
1599 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001600
1601 // Create an override bundle containing the key and value that should be overriden.
1602 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1603 if (overrideBundle == null) {
1604 return -1;
1605 }
1606
1607 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001608 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001609
1610 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001611 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001612 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001613 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001614 return -1;
1615 }
1616
1617 // Print the original and new value.
1618 String originalValueString = ccValueToString(key, type, originalValues);
1619 String newValueString = ccValueToString(key, type, newValues);
1620 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1621 getOutPrintWriter().println("New value: \n" + newValueString);
1622
1623 return 0;
1624 }
1625
Allen Xue5522892022-03-14 21:04:49 +00001626 // cc set-values-from-xml
1627 private int handleCcSetValuesFromXml() {
1628 PrintWriter errPw = getErrPrintWriter();
1629 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUES_FROM_XML + ": ";
1630
1631 // Parse all options
Allen Xud8db8332022-05-20 22:26:42 +00001632 CcOptionParseResult options = parseCcOptions(tag, true);
Allen Xue5522892022-03-14 21:04:49 +00001633 if (options == null) {
1634 return -1;
1635 }
1636
1637 // Get bundle containing all current carrier configuration values.
1638 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1639 if (originalValues == null) {
1640 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1641 return -1;
1642 }
1643
1644 PersistableBundle overrideBundle = readPersistableBundleFromXml(tag);
1645 if (overrideBundle == null) {
1646 return -1;
1647 }
1648
1649 // Verify all values are valid types
1650 for (String key : overrideBundle.keySet()) {
1651 CcType type = getType(tag, key, originalValues);
1652 if (type == CcType.UNKNOWN) {
1653 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1654 return -1;
1655 }
1656 }
1657
1658 // Override the value
1659 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
1660
1661 // Find bundle containing all new carrier configuration values after the override.
1662 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
1663 if (newValues == null) {
1664 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
1665 return -1;
1666 }
1667
1668 // Print the original and new values
1669 overrideBundle.keySet().forEach(key -> {
1670 CcType type = getType(tag, key, originalValues);
1671 String originalValueString = ccValueToString(key, type, originalValues);
1672 String newValueString = ccValueToString(key, type, newValues);
1673 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1674 getOutPrintWriter().println("New value: \n" + newValueString);
1675 });
1676
1677 return 0;
1678 }
1679
1680 private PersistableBundle readPersistableBundleFromXml(String tag) {
1681 PersistableBundle subIdBundles;
1682 try {
1683 subIdBundles = PersistableBundle.readFromStream(getRawInputStream());
1684 } catch (IOException | RuntimeException e) {
1685 PrintWriter errPw = getErrPrintWriter();
1686 errPw.println(tag + e);
1687 return null;
1688 }
1689
1690 return subIdBundles;
1691 }
1692
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001693 // cc clear-values
1694 private int handleCcClearValues() {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001695 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1696
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001697 // Parse all options
Allen Xue5522892022-03-14 21:04:49 +00001698 CcOptionParseResult options = parseCcOptions(tag, false);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001699 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001700 return -1;
1701 }
1702
1703 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001704 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001705 getOutPrintWriter()
1706 .println("All previously set carrier config override values has been cleared");
1707 return 0;
1708 }
1709
1710 private CcType getType(String tag, String key, PersistableBundle bundle) {
1711 // Find the type by checking the type of the current value stored in the bundle.
1712 Object value = bundle.get(key);
1713
1714 if (CC_TYPE_MAP.containsKey(key)) {
1715 return CC_TYPE_MAP.get(key);
1716 } else if (value != null) {
1717 if (value instanceof Boolean) {
1718 return CcType.BOOLEAN;
Allen Xue5522892022-03-14 21:04:49 +00001719 }
1720 if (value instanceof Double) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001721 return CcType.DOUBLE;
Allen Xue5522892022-03-14 21:04:49 +00001722 }
1723 if (value instanceof double[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001724 return CcType.DOUBLE_ARRAY;
Allen Xue5522892022-03-14 21:04:49 +00001725 }
1726 if (value instanceof Integer) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001727 return CcType.INT;
Allen Xue5522892022-03-14 21:04:49 +00001728 }
1729 if (value instanceof int[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001730 return CcType.INT_ARRAY;
Allen Xue5522892022-03-14 21:04:49 +00001731 }
1732 if (value instanceof Long) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001733 return CcType.LONG;
Allen Xue5522892022-03-14 21:04:49 +00001734 }
1735 if (value instanceof long[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001736 return CcType.LONG_ARRAY;
Allen Xue5522892022-03-14 21:04:49 +00001737 }
1738 if (value instanceof String) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001739 return CcType.STRING;
Allen Xue5522892022-03-14 21:04:49 +00001740 }
1741 if (value instanceof String[]) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001742 return CcType.STRING_ARRAY;
1743 }
Allen Xue5522892022-03-14 21:04:49 +00001744 if (value instanceof PersistableBundle) {
1745 return CcType.PERSISTABLE_BUNDLE;
1746 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001747 } else {
1748 // Current value was null and can therefore not be used in order to find the type.
1749 // Check the name of the key to infer the type. This check is not needed for primitive
1750 // data types (boolean, double, int and long), since they can not be null.
1751 if (key.endsWith("double_array")) {
1752 return CcType.DOUBLE_ARRAY;
1753 }
1754 if (key.endsWith("int_array")) {
1755 return CcType.INT_ARRAY;
1756 }
1757 if (key.endsWith("long_array")) {
1758 return CcType.LONG_ARRAY;
1759 }
1760 if (key.endsWith("string")) {
1761 return CcType.STRING;
1762 }
1763 if (key.endsWith("string_array") || key.endsWith("strings")) {
1764 return CcType.STRING_ARRAY;
1765 }
Allen Xue5522892022-03-14 21:04:49 +00001766 if (key.endsWith("bundle")) {
1767 return CcType.PERSISTABLE_BUNDLE;
1768 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001769 }
1770
1771 // Not possible to infer the type by looking at the current value or the key.
1772 PrintWriter errPw = getErrPrintWriter();
1773 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1774 return CcType.UNKNOWN;
1775 }
1776
1777 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1778 String result;
1779 StringBuilder valueString = new StringBuilder();
1780 String typeString = type.toString();
1781 Object value = bundle.get(key);
1782
1783 if (value == null) {
1784 valueString.append("null");
1785 } else {
1786 switch (type) {
1787 case DOUBLE_ARRAY: {
1788 // Format the string representation of the int array as value1 value2......
1789 double[] valueArray = (double[]) value;
1790 for (int i = 0; i < valueArray.length; i++) {
1791 if (i != 0) {
1792 valueString.append(" ");
1793 }
1794 valueString.append(valueArray[i]);
1795 }
1796 break;
1797 }
1798 case INT_ARRAY: {
1799 // Format the string representation of the int array as value1 value2......
1800 int[] valueArray = (int[]) value;
1801 for (int i = 0; i < valueArray.length; i++) {
1802 if (i != 0) {
1803 valueString.append(" ");
1804 }
1805 valueString.append(valueArray[i]);
1806 }
1807 break;
1808 }
1809 case LONG_ARRAY: {
1810 // Format the string representation of the int array as value1 value2......
1811 long[] valueArray = (long[]) value;
1812 for (int i = 0; i < valueArray.length; i++) {
1813 if (i != 0) {
1814 valueString.append(" ");
1815 }
1816 valueString.append(valueArray[i]);
1817 }
1818 break;
1819 }
1820 case STRING: {
1821 valueString.append("\"" + value.toString() + "\"");
1822 break;
1823 }
1824 case STRING_ARRAY: {
1825 // Format the string representation of the string array as "value1" "value2"....
1826 String[] valueArray = (String[]) value;
1827 for (int i = 0; i < valueArray.length; i++) {
1828 if (i != 0) {
1829 valueString.append(" ");
1830 }
1831 if (valueArray[i] != null) {
1832 valueString.append("\"" + valueArray[i] + "\"");
1833 } else {
1834 valueString.append("null");
1835 }
1836 }
1837 break;
1838 }
1839 default: {
1840 valueString.append(value.toString());
1841 }
1842 }
1843 }
1844 return String.format("%-70s %-15s %s", key, typeString, valueString);
1845 }
1846
1847 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1848 ArrayList<String> valueList) {
1849 PrintWriter errPw = getErrPrintWriter();
1850 PersistableBundle bundle = new PersistableBundle();
1851
1852 // First verify that a valid number of values has been provided for the type.
1853 switch (type) {
1854 case BOOLEAN:
1855 case DOUBLE:
1856 case INT:
1857 case LONG: {
1858 if (valueList.size() != 1) {
1859 errPw.println(tag + "Expected 1 value for type " + type
1860 + ". Found: " + valueList.size());
1861 return null;
1862 }
1863 break;
1864 }
1865 case STRING: {
1866 if (valueList.size() > 1) {
1867 errPw.println(tag + "Expected 0 or 1 values for type " + type
1868 + ". Found: " + valueList.size());
1869 return null;
1870 }
1871 break;
1872 }
1873 }
1874
1875 // Parse the value according to type and add it to the Bundle.
1876 switch (type) {
1877 case BOOLEAN: {
1878 if ("true".equalsIgnoreCase(valueList.get(0))) {
1879 bundle.putBoolean(key, true);
1880 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1881 bundle.putBoolean(key, false);
1882 } else {
1883 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1884 return null;
1885 }
1886 break;
1887 }
1888 case DOUBLE: {
1889 try {
1890 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1891 } catch (NumberFormatException nfe) {
1892 // Not a valid double
1893 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1894 return null;
1895 }
1896 break;
1897 }
1898 case DOUBLE_ARRAY: {
1899 double[] valueDoubleArray = null;
1900 if (valueList.size() > 0) {
1901 valueDoubleArray = new double[valueList.size()];
1902 for (int i = 0; i < valueList.size(); i++) {
1903 try {
1904 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1905 } catch (NumberFormatException nfe) {
1906 // Not a valid double
1907 errPw.println(
1908 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1909 return null;
1910 }
1911 }
1912 }
1913 bundle.putDoubleArray(key, valueDoubleArray);
1914 break;
1915 }
1916 case INT: {
1917 try {
1918 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1919 } catch (NumberFormatException nfe) {
1920 // Not a valid integer
1921 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1922 return null;
1923 }
1924 break;
1925 }
1926 case INT_ARRAY: {
1927 int[] valueIntArray = null;
1928 if (valueList.size() > 0) {
1929 valueIntArray = new int[valueList.size()];
1930 for (int i = 0; i < valueList.size(); i++) {
1931 try {
1932 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1933 } catch (NumberFormatException nfe) {
1934 // Not a valid integer
1935 errPw.println(tag
1936 + "Unable to parse " + valueList.get(i) + " as an integer.");
1937 return null;
1938 }
1939 }
1940 }
1941 bundle.putIntArray(key, valueIntArray);
1942 break;
1943 }
1944 case LONG: {
1945 try {
1946 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1947 } catch (NumberFormatException nfe) {
1948 // Not a valid long
1949 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1950 return null;
1951 }
1952 break;
1953 }
1954 case LONG_ARRAY: {
1955 long[] valueLongArray = null;
1956 if (valueList.size() > 0) {
1957 valueLongArray = new long[valueList.size()];
1958 for (int i = 0; i < valueList.size(); i++) {
1959 try {
1960 valueLongArray[i] = Long.parseLong(valueList.get(i));
1961 } catch (NumberFormatException nfe) {
1962 // Not a valid long
1963 errPw.println(
1964 tag + "Unable to parse " + valueList.get(i) + " as a long");
1965 return null;
1966 }
1967 }
1968 }
1969 bundle.putLongArray(key, valueLongArray);
1970 break;
1971 }
1972 case STRING: {
1973 String value = null;
1974 if (valueList.size() > 0) {
1975 value = valueList.get(0);
1976 }
1977 bundle.putString(key, value);
1978 break;
1979 }
1980 case STRING_ARRAY: {
1981 String[] valueStringArray = null;
1982 if (valueList.size() > 0) {
1983 valueStringArray = new String[valueList.size()];
1984 valueList.toArray(valueStringArray);
1985 }
1986 bundle.putStringArray(key, valueStringArray);
1987 break;
1988 }
1989 }
1990 return bundle;
1991 }
Shuo Qian489d9282020-07-09 11:30:03 -07001992
1993 private int handleEndBlockSuppressionCommand() {
1994 if (!checkShellUid()) {
1995 return -1;
1996 }
1997
1998 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1999 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
2000 }
2001 return 0;
2002 }
Hui Wang641e81c2020-10-12 12:14:23 -07002003
Michele Berionne54af4632020-12-28 20:23:16 +00002004 private int handleRestartModemCommand() {
2005 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2006 // non user build.
2007 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2008 getErrPrintWriter().println("RestartModem: Permission denied.");
2009 return -1;
2010 }
2011
2012 boolean result = TelephonyManager.getDefault().rebootRadio();
2013 getOutPrintWriter().println(result);
2014
2015 return result ? 0 : -1;
2016 }
2017
Michele Berionne5e411512020-11-13 02:36:59 +00002018 private int handleUnattendedReboot() {
2019 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
2020 // non user build.
2021 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
2022 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
2023 return -1;
2024 }
2025
2026 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
2027 getOutPrintWriter().println("result: " + result);
2028
2029 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
2030 }
2031
Hui Wang641e81c2020-10-12 12:14:23 -07002032 private int handleGbaCommand() {
2033 String arg = getNextArg();
2034 if (arg == null) {
2035 onHelpGba();
2036 return 0;
2037 }
2038
2039 switch (arg) {
2040 case GBA_SET_SERVICE: {
2041 return handleGbaSetServiceCommand();
2042 }
2043 case GBA_GET_SERVICE: {
2044 return handleGbaGetServiceCommand();
2045 }
2046 case GBA_SET_RELEASE_TIME: {
2047 return handleGbaSetReleaseCommand();
2048 }
2049 case GBA_GET_RELEASE_TIME: {
2050 return handleGbaGetReleaseCommand();
2051 }
2052 }
2053
2054 return -1;
2055 }
2056
2057 private int getSubId(String cmd) {
2058 int slotId = getDefaultSlot();
2059 String opt = getNextOption();
2060 if (opt != null && opt.equals("-s")) {
2061 try {
2062 slotId = Integer.parseInt(getNextArgRequired());
2063 } catch (NumberFormatException e) {
2064 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
2065 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
2066 }
2067 }
2068 int[] subIds = SubscriptionManager.getSubId(slotId);
2069 return subIds[0];
2070 }
2071
2072 private int handleGbaSetServiceCommand() {
2073 int subId = getSubId("gba set-service");
2074 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2075 return -1;
2076 }
2077
2078 String packageName = getNextArg();
2079 try {
2080 if (packageName == null) {
2081 packageName = "";
2082 }
2083 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
2084 if (VDBG) {
2085 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
2086 + packageName + ", result=" + result);
2087 }
2088 getOutPrintWriter().println(result);
2089 } catch (RemoteException e) {
2090 Log.w(LOG_TAG, "gba set-service " + subId + " "
2091 + packageName + ", error" + e.getMessage());
2092 getErrPrintWriter().println("Exception: " + e.getMessage());
2093 return -1;
2094 }
2095 return 0;
2096 }
2097
2098 private int handleGbaGetServiceCommand() {
2099 String result;
2100
2101 int subId = getSubId("gba get-service");
2102 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2103 return -1;
2104 }
2105
2106 try {
2107 result = mInterface.getBoundGbaService(subId);
2108 } catch (RemoteException e) {
2109 return -1;
2110 }
2111 if (VDBG) {
2112 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
2113 }
2114 getOutPrintWriter().println(result);
2115 return 0;
2116 }
2117
2118 private int handleGbaSetReleaseCommand() {
2119 //the release time value could be -1
2120 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
2121 : SubscriptionManager.getDefaultSubscriptionId();
2122 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2123 return -1;
2124 }
2125
2126 String intervalStr = getNextArg();
2127 if (intervalStr == null) {
2128 return -1;
2129 }
2130
2131 try {
2132 int interval = Integer.parseInt(intervalStr);
2133 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
2134 if (VDBG) {
2135 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
2136 + intervalStr + ", result=" + result);
2137 }
2138 getOutPrintWriter().println(result);
2139 } catch (NumberFormatException | RemoteException e) {
2140 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
2141 + intervalStr + ", error" + e.getMessage());
2142 getErrPrintWriter().println("Exception: " + e.getMessage());
2143 return -1;
2144 }
2145 return 0;
2146 }
2147
2148 private int handleGbaGetReleaseCommand() {
2149 int subId = getSubId("gba get-release");
2150 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2151 return -1;
2152 }
2153
2154 int result = 0;
2155 try {
2156 result = mInterface.getGbaReleaseTime(subId);
2157 } catch (RemoteException e) {
2158 return -1;
2159 }
2160 if (VDBG) {
2161 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
2162 }
2163 getOutPrintWriter().println(result);
2164 return 0;
2165 }
Hui Wang761a6682020-10-31 05:12:53 +00002166
2167 private int handleSingleRegistrationConfigCommand() {
2168 String arg = getNextArg();
2169 if (arg == null) {
2170 onHelpSrc();
2171 return 0;
2172 }
2173
2174 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08002175 case SRC_SET_TEST_ENABLED: {
2176 return handleSrcSetTestEnabledCommand();
2177 }
2178 case SRC_GET_TEST_ENABLED: {
2179 return handleSrcGetTestEnabledCommand();
2180 }
Hui Wang761a6682020-10-31 05:12:53 +00002181 case SRC_SET_DEVICE_ENABLED: {
2182 return handleSrcSetDeviceEnabledCommand();
2183 }
2184 case SRC_GET_DEVICE_ENABLED: {
2185 return handleSrcGetDeviceEnabledCommand();
2186 }
2187 case SRC_SET_CARRIER_ENABLED: {
2188 return handleSrcSetCarrierEnabledCommand();
2189 }
2190 case SRC_GET_CARRIER_ENABLED: {
2191 return handleSrcGetCarrierEnabledCommand();
2192 }
Hui Wangb647abe2021-02-26 09:33:38 -08002193 case SRC_SET_FEATURE_ENABLED: {
2194 return handleSrcSetFeatureValidationCommand();
2195 }
2196 case SRC_GET_FEATURE_ENABLED: {
2197 return handleSrcGetFeatureValidationCommand();
2198 }
Hui Wang761a6682020-10-31 05:12:53 +00002199 }
2200
2201 return -1;
2202 }
2203
James.cf Linbcdf8b32021-01-14 16:44:13 +08002204 private int handleRcsUceCommand() {
2205 String arg = getNextArg();
2206 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00002207 onHelpUce();
2208 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002209 }
2210
2211 switch (arg) {
2212 case UCE_REMOVE_EAB_CONTACT:
2213 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08002214 case UCE_GET_EAB_CONTACT:
2215 return handleGettingEabContactCommand();
Calvin Pana1434322021-07-01 19:27:01 +08002216 case UCE_GET_EAB_CAPABILITY:
2217 return handleGettingEabCapabilityCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08002218 case UCE_GET_DEVICE_ENABLED:
2219 return handleUceGetDeviceEnabledCommand();
2220 case UCE_SET_DEVICE_ENABLED:
2221 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00002222 case UCE_OVERRIDE_PUBLISH_CAPS:
2223 return handleUceOverridePublishCaps();
2224 case UCE_GET_LAST_PIDF_XML:
2225 return handleUceGetPidfXml();
James.cf Line8713a42021-04-29 16:04:26 +08002226 case UCE_REMOVE_REQUEST_DISALLOWED_STATUS:
2227 return handleUceRemoveRequestDisallowedStatus();
James.cf Lin0fc71b02021-05-25 01:37:38 +08002228 case UCE_SET_CAPABILITY_REQUEST_TIMEOUT:
2229 return handleUceSetCapRequestTimeout();
James.cf Linbcdf8b32021-01-14 16:44:13 +08002230 }
2231 return -1;
2232 }
2233
2234 private int handleRemovingEabContactCommand() {
2235 int subId = getSubId("uce remove-eab-contact");
2236 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2237 return -1;
2238 }
2239
2240 String phoneNumber = getNextArgRequired();
2241 if (TextUtils.isEmpty(phoneNumber)) {
2242 return -1;
2243 }
2244 int result = 0;
2245 try {
2246 result = mInterface.removeContactFromEab(subId, phoneNumber);
2247 } catch (RemoteException e) {
2248 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
2249 getErrPrintWriter().println("Exception: " + e.getMessage());
2250 return -1;
2251 }
2252
2253 if (VDBG) {
2254 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
2255 }
calvinpan293ea1b2021-02-04 17:52:13 +08002256 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08002257 }
2258
calvinpane4a8a1d2021-01-25 13:51:18 +08002259 private int handleGettingEabContactCommand() {
2260 String phoneNumber = getNextArgRequired();
2261 if (TextUtils.isEmpty(phoneNumber)) {
2262 return -1;
2263 }
2264 String result = "";
2265 try {
2266 result = mInterface.getContactFromEab(phoneNumber);
calvinpane4a8a1d2021-01-25 13:51:18 +08002267 } catch (RemoteException e) {
2268 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
2269 getErrPrintWriter().println("Exception: " + e.getMessage());
2270 return -1;
2271 }
2272
2273 if (VDBG) {
2274 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
2275 }
calvinpan293ea1b2021-02-04 17:52:13 +08002276 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08002277 return 0;
2278 }
2279
Calvin Pana1434322021-07-01 19:27:01 +08002280 private int handleGettingEabCapabilityCommand() {
2281 String phoneNumber = getNextArgRequired();
2282 if (TextUtils.isEmpty(phoneNumber)) {
2283 return -1;
2284 }
2285 String result = "";
2286 try {
2287 result = mInterface.getCapabilityFromEab(phoneNumber);
2288 } catch (RemoteException e) {
2289 Log.w(LOG_TAG, "uce get-eab-capability, error " + e.getMessage());
2290 getErrPrintWriter().println("Exception: " + e.getMessage());
2291 return -1;
2292 }
2293
2294 if (VDBG) {
2295 Log.v(LOG_TAG, "uce get-eab-capability, result: " + result);
2296 }
2297 getOutPrintWriter().println(result);
2298 return 0;
2299 }
2300
James.cf Lin4b784aa2021-01-31 03:25:15 +08002301 private int handleUceGetDeviceEnabledCommand() {
2302 boolean result = false;
2303 try {
2304 result = mInterface.getDeviceUceEnabled();
2305 } catch (RemoteException e) {
2306 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
2307 return -1;
2308 }
2309 if (VDBG) {
2310 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
2311 }
calvinpane4a8a1d2021-01-25 13:51:18 +08002312 getOutPrintWriter().println(result);
2313 return 0;
2314 }
2315
James.cf Lin4b784aa2021-01-31 03:25:15 +08002316 private int handleUceSetDeviceEnabledCommand() {
2317 String enabledStr = getNextArg();
2318 if (TextUtils.isEmpty(enabledStr)) {
2319 return -1;
2320 }
2321
2322 try {
2323 boolean isEnabled = Boolean.parseBoolean(enabledStr);
2324 mInterface.setDeviceUceEnabled(isEnabled);
2325 if (VDBG) {
2326 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
2327 }
2328 } catch (NumberFormatException | RemoteException e) {
2329 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
2330 getErrPrintWriter().println("Exception: " + e.getMessage());
2331 return -1;
2332 }
2333 return 0;
2334 }
2335
James.cf Line8713a42021-04-29 16:04:26 +08002336 private int handleUceRemoveRequestDisallowedStatus() {
2337 int subId = getSubId("uce remove-request-disallowed-status");
2338 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2339 Log.w(LOG_TAG, "uce remove-request-disallowed-status, Invalid subscription ID");
2340 return -1;
2341 }
2342 boolean result;
2343 try {
2344 result = mInterface.removeUceRequestDisallowedStatus(subId);
2345 } catch (RemoteException e) {
2346 Log.w(LOG_TAG, "uce remove-request-disallowed-status, error " + e.getMessage());
2347 return -1;
2348 }
2349 if (VDBG) {
2350 Log.v(LOG_TAG, "uce remove-request-disallowed-status, returned: " + result);
2351 }
2352 getOutPrintWriter().println(result);
2353 return 0;
2354 }
2355
James.cf Lin0fc71b02021-05-25 01:37:38 +08002356 private int handleUceSetCapRequestTimeout() {
2357 int subId = getSubId("uce set-capabilities-request-timeout");
2358 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2359 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, Invalid subscription ID");
2360 return -1;
2361 }
2362 long timeoutAfterMs = Long.valueOf(getNextArg());
2363 boolean result;
2364 try {
2365 result = mInterface.setCapabilitiesRequestTimeout(subId, timeoutAfterMs);
2366 } catch (RemoteException e) {
2367 Log.w(LOG_TAG, "uce set-capabilities-request-timeout, error " + e.getMessage());
2368 return -1;
2369 }
2370 if (VDBG) {
2371 Log.v(LOG_TAG, "uce set-capabilities-request-timeout, returned: " + result);
2372 }
2373 getOutPrintWriter().println(result);
2374 return 0;
2375 }
2376
Hui Wangbaaee6a2021-02-19 20:45:36 -08002377 private int handleSrcSetTestEnabledCommand() {
2378 String enabledStr = getNextArg();
2379 if (enabledStr == null) {
2380 return -1;
2381 }
2382
2383 try {
2384 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
2385 if (VDBG) {
2386 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
2387 }
2388 getOutPrintWriter().println("Done");
2389 } catch (NumberFormatException | RemoteException e) {
2390 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
2391 getErrPrintWriter().println("Exception: " + e.getMessage());
2392 return -1;
2393 }
2394 return 0;
2395 }
2396
2397 private int handleSrcGetTestEnabledCommand() {
2398 boolean result = false;
2399 try {
2400 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
2401 } catch (RemoteException e) {
2402 return -1;
2403 }
2404 if (VDBG) {
2405 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
2406 }
2407 getOutPrintWriter().println(result);
2408 return 0;
2409 }
2410
Brad Ebinger14d467f2021-02-12 06:18:28 +00002411 private int handleUceOverridePublishCaps() {
2412 int subId = getSubId("uce override-published-caps");
2413 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2414 return -1;
2415 }
2416 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
2417 String operation = getNextArgRequired();
2418 String caps = getNextArg();
2419 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
2420 && !"list".equals(operation)) {
2421 getErrPrintWriter().println("Invalid operation: " + operation);
2422 return -1;
2423 }
2424
2425 // add/remove requires capabilities to be specified.
2426 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
2427 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2428 + "specified");
2429 return -1;
2430 }
2431
2432 ArraySet<String> capSet = new ArraySet<>();
2433 if (!TextUtils.isEmpty(caps)) {
2434 String[] capArray = caps.split(":");
2435 for (String cap : capArray) {
2436 // Allow unknown tags to be passed in as well.
2437 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2438 }
2439 }
2440
2441 RcsContactUceCapability result = null;
2442 try {
2443 switch (operation) {
2444 case "add":
2445 result = mInterface.addUceRegistrationOverrideShell(subId,
2446 new ArrayList<>(capSet));
2447 break;
2448 case "remove":
2449 result = mInterface.removeUceRegistrationOverrideShell(subId,
2450 new ArrayList<>(capSet));
2451 break;
2452 case "clear":
2453 result = mInterface.clearUceRegistrationOverrideShell(subId);
2454 break;
2455 case "list":
2456 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2457 break;
2458 }
2459 } catch (RemoteException e) {
2460 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2461 getErrPrintWriter().println("Exception: " + e.getMessage());
2462 return -1;
2463 } catch (ServiceSpecificException sse) {
2464 // Reconstruct ImsException
2465 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2466 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2467 getErrPrintWriter().println("Exception: " + imsException);
2468 return -1;
2469 }
2470 if (result == null) {
2471 getErrPrintWriter().println("Service not available");
2472 return -1;
2473 }
2474 getOutPrintWriter().println(result);
2475 return 0;
2476 }
2477
2478 private int handleUceGetPidfXml() {
2479 int subId = getSubId("uce get-last-publish-pidf");
2480 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2481 return -1;
2482 }
2483
2484 String result;
2485 try {
2486 result = mInterface.getLastUcePidfXmlShell(subId);
2487 } catch (RemoteException e) {
2488 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2489 getErrPrintWriter().println("Exception: " + e.getMessage());
2490 return -1;
2491 } catch (ServiceSpecificException sse) {
2492 // Reconstruct ImsException
2493 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2494 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2495 getErrPrintWriter().println("Exception: " + imsException);
2496 return -1;
2497 }
2498 if (result == null) {
2499 getErrPrintWriter().println("Service not available");
2500 return -1;
2501 }
2502 getOutPrintWriter().println(result);
2503 return 0;
2504 }
2505
Hui Wang761a6682020-10-31 05:12:53 +00002506 private int handleSrcSetDeviceEnabledCommand() {
2507 String enabledStr = getNextArg();
2508 if (enabledStr == null) {
2509 return -1;
2510 }
2511
2512 try {
2513 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2514 if (VDBG) {
2515 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2516 }
2517 getOutPrintWriter().println("Done");
2518 } catch (NumberFormatException | RemoteException e) {
2519 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2520 getErrPrintWriter().println("Exception: " + e.getMessage());
2521 return -1;
2522 }
2523 return 0;
2524 }
2525
2526 private int handleSrcGetDeviceEnabledCommand() {
2527 boolean result = false;
2528 try {
2529 result = mInterface.getDeviceSingleRegistrationEnabled();
2530 } catch (RemoteException e) {
2531 return -1;
2532 }
2533 if (VDBG) {
2534 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2535 }
2536 getOutPrintWriter().println(result);
2537 return 0;
2538 }
2539
2540 private int handleSrcSetCarrierEnabledCommand() {
2541 //the release time value could be -1
2542 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2543 : SubscriptionManager.getDefaultSubscriptionId();
2544 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2545 return -1;
2546 }
2547
2548 String enabledStr = getNextArg();
2549 if (enabledStr == null) {
2550 return -1;
2551 }
2552
2553 try {
2554 boolean result =
2555 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2556 if (VDBG) {
2557 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2558 + enabledStr + ", result=" + result);
2559 }
2560 getOutPrintWriter().println(result);
2561 } catch (NumberFormatException | RemoteException e) {
2562 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2563 + enabledStr + ", error" + e.getMessage());
2564 getErrPrintWriter().println("Exception: " + e.getMessage());
2565 return -1;
2566 }
2567 return 0;
2568 }
2569
2570 private int handleSrcGetCarrierEnabledCommand() {
2571 int subId = getSubId("src get-carrier-enabled");
2572 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2573 return -1;
2574 }
2575
2576 boolean result = false;
2577 try {
2578 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2579 } catch (RemoteException e) {
2580 return -1;
2581 }
2582 if (VDBG) {
2583 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2584 }
2585 getOutPrintWriter().println(result);
2586 return 0;
2587 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002588
Hui Wangb647abe2021-02-26 09:33:38 -08002589 private int handleSrcSetFeatureValidationCommand() {
2590 //the release time value could be -1
2591 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2592 : SubscriptionManager.getDefaultSubscriptionId();
2593 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2594 return -1;
2595 }
2596
2597 String enabledStr = getNextArg();
2598 if (enabledStr == null) {
2599 return -1;
2600 }
2601
2602 try {
2603 boolean result =
2604 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2605 if (VDBG) {
2606 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2607 + enabledStr + ", result=" + result);
2608 }
2609 getOutPrintWriter().println(result);
2610 } catch (NumberFormatException | RemoteException e) {
2611 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2612 + enabledStr + ", error" + e.getMessage());
2613 getErrPrintWriter().println("Exception: " + e.getMessage());
2614 return -1;
2615 }
2616 return 0;
2617 }
2618
2619 private int handleSrcGetFeatureValidationCommand() {
2620 int subId = getSubId("src get-feature-validation");
2621 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2622 return -1;
2623 }
2624
2625 Boolean result = false;
2626 try {
2627 result = mInterface.getImsFeatureValidationOverride(subId);
2628 } catch (RemoteException e) {
2629 return -1;
2630 }
2631 if (VDBG) {
2632 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2633 }
2634 getOutPrintWriter().println(result);
2635 return 0;
2636 }
2637
2638
Hall Liuaa4211e2021-01-20 15:43:39 -08002639 private void onHelpCallComposer() {
2640 PrintWriter pw = getOutPrintWriter();
2641 pw.println("Call composer commands");
2642 pw.println(" callcomposer test-mode enable|disable|query");
2643 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2644 pw.println(" upload/download from carrier servers is disabled, and operations are");
2645 pw.println(" performed using emulated local files instead.");
2646 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2647 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2648 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002649 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2650 pw.println(" Enables or disables the user setting for call composer, as set by");
2651 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002652 }
2653
2654 private int handleCallComposerCommand() {
2655 String arg = getNextArg();
2656 if (arg == null) {
2657 onHelpCallComposer();
2658 return 0;
2659 }
2660
2661 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2662 "MODIFY_PHONE_STATE required for call composer shell cmds");
2663 switch (arg) {
2664 case CALL_COMPOSER_TEST_MODE: {
2665 String enabledStr = getNextArg();
2666 if (ENABLE.equals(enabledStr)) {
2667 CallComposerPictureManager.sTestMode = true;
2668 } else if (DISABLE.equals(enabledStr)) {
2669 CallComposerPictureManager.sTestMode = false;
2670 } else if (QUERY.equals(enabledStr)) {
2671 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2672 } else {
2673 onHelpCallComposer();
2674 return 1;
2675 }
2676 break;
2677 }
2678 case CALL_COMPOSER_SIMULATE_CALL: {
2679 int subscriptionId = Integer.valueOf(getNextArg());
2680 String uuidString = getNextArg();
2681 UUID uuid = UUID.fromString(uuidString);
2682 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2683 Binder.withCleanCallingIdentity(() -> {
2684 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2685 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2686 });
2687 try {
2688 Uri uri = storageUriFuture.get();
2689 getOutPrintWriter().println(String.valueOf(uri));
2690 } catch (Exception e) {
2691 throw new RuntimeException(e);
2692 }
2693 break;
2694 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002695 case CALL_COMPOSER_USER_SETTING: {
2696 try {
2697 int subscriptionId = Integer.valueOf(getNextArg());
2698 String enabledStr = getNextArg();
2699 if (ENABLE.equals(enabledStr)) {
2700 mInterface.setCallComposerStatus(subscriptionId,
2701 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2702 } else if (DISABLE.equals(enabledStr)) {
2703 mInterface.setCallComposerStatus(subscriptionId,
2704 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2705 } else if (QUERY.equals(enabledStr)) {
2706 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2707 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2708 } else {
2709 onHelpCallComposer();
2710 return 1;
2711 }
2712 } catch (RemoteException e) {
2713 e.printStackTrace(getOutPrintWriter());
2714 return 1;
2715 }
2716 break;
2717 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002718 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002719 return 0;
2720 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002721
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002722 private int handleHasCarrierPrivilegesCommand() {
2723 String packageName = getNextArgRequired();
2724
2725 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002726 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002727 try {
2728 hasCarrierPrivileges =
2729 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2730 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2731 } catch (RemoteException e) {
2732 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2733 getErrPrintWriter().println("Exception: " + e.getMessage());
2734 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002735 } finally {
2736 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002737 }
2738
2739 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002740 return 0;
2741 }
SongFerngWang98dd5992021-05-13 17:50:00 +08002742
2743 private int handleAllowedNetworkTypesCommand(String command) {
2744 if (!checkShellUid()) {
2745 return -1;
2746 }
2747
2748 PrintWriter errPw = getErrPrintWriter();
2749 String tag = command + ": ";
2750 String opt;
2751 int subId = -1;
2752 Log.v(LOG_TAG, command + " start");
2753
2754 while ((opt = getNextOption()) != null) {
2755 if (opt.equals("-s")) {
2756 try {
2757 subId = slotStringToSubId(tag, getNextArgRequired());
2758 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2759 errPw.println(tag + "No valid subscription found.");
2760 return -1;
2761 }
2762 } catch (IllegalArgumentException e) {
2763 // Missing slot id
2764 errPw.println(tag + "SLOT_ID expected after -s.");
2765 return -1;
2766 }
2767 } else {
2768 errPw.println(tag + "Unknown option " + opt);
2769 return -1;
2770 }
2771 }
2772
2773 if (GET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2774 return handleGetAllowedNetworkTypesCommand(subId);
2775 }
2776 if (SET_ALLOWED_NETWORK_TYPES_FOR_USER.equals(command)) {
2777 return handleSetAllowedNetworkTypesCommand(subId);
2778 }
2779 return -1;
2780 }
2781
2782 private int handleGetAllowedNetworkTypesCommand(int subId) {
2783 PrintWriter errPw = getErrPrintWriter();
2784
2785 long result = -1;
2786 try {
2787 if (mInterface != null) {
2788 result = mInterface.getAllowedNetworkTypesForReason(subId,
2789 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
2790 } else {
2791 throw new IllegalStateException("telephony service is null.");
2792 }
2793 } catch (RemoteException e) {
2794 Log.e(TAG, "getAllowedNetworkTypesForReason RemoteException" + e);
2795 errPw.println(GET_ALLOWED_NETWORK_TYPES_FOR_USER + "RemoteException " + e);
2796 return -1;
2797 }
2798
2799 getOutPrintWriter().println(TelephonyManager.convertNetworkTypeBitmaskToString(result));
2800 return 0;
2801 }
2802
2803 private int handleSetAllowedNetworkTypesCommand(int subId) {
2804 PrintWriter errPw = getErrPrintWriter();
2805
2806 String bitmaskString = getNextArg();
2807 if (TextUtils.isEmpty(bitmaskString)) {
2808 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No NETWORK_TYPES_BITMASK");
2809 return -1;
2810 }
2811 long allowedNetworkTypes = convertNetworkTypeBitmaskFromStringToLong(bitmaskString);
2812 if (allowedNetworkTypes < 0) {
2813 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " No valid NETWORK_TYPES_BITMASK");
2814 return -1;
2815 }
2816 boolean result = false;
2817 try {
2818 if (mInterface != null) {
2819 result = mInterface.setAllowedNetworkTypesForReason(subId,
2820 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, allowedNetworkTypes);
2821 } else {
2822 throw new IllegalStateException("telephony service is null.");
2823 }
2824 } catch (RemoteException e) {
2825 Log.e(TAG, "setAllowedNetworkTypesForReason RemoteException" + e);
2826 errPw.println(SET_ALLOWED_NETWORK_TYPES_FOR_USER + " RemoteException " + e);
2827 return -1;
2828 }
2829
2830 String resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " failed";
2831 if (result) {
2832 resultMessage = SET_ALLOWED_NETWORK_TYPES_FOR_USER + " completed";
2833 }
2834 getOutPrintWriter().println(resultMessage);
2835 return 0;
2836 }
2837
2838 private long convertNetworkTypeBitmaskFromStringToLong(String bitmaskString) {
2839 if (TextUtils.isEmpty(bitmaskString)) {
2840 return -1;
2841 }
2842 if (VDBG) {
2843 Log.v(LOG_TAG, "AllowedNetworkTypes:" + bitmaskString
2844 + ", length: " + bitmaskString.length());
2845 }
2846 try {
2847 return Long.parseLong(bitmaskString, 2);
2848 } catch (NumberFormatException e) {
2849 Log.e(LOG_TAG, "AllowedNetworkTypes: " + e);
2850 return -1;
2851 }
2852 }
jimsun38340bf2021-10-26 15:01:23 +08002853
2854 private int handleRadioSetModemServiceCommand() {
2855 PrintWriter errPw = getErrPrintWriter();
2856 String serviceName = null;
2857
2858 String opt;
2859 while ((opt = getNextOption()) != null) {
2860 switch (opt) {
2861 case "-s": {
2862 serviceName = getNextArgRequired();
2863 break;
2864 }
2865 }
2866 }
2867
2868 try {
2869 boolean result = mInterface.setModemService(serviceName);
2870 if (VDBG) {
2871 Log.v(LOG_TAG,
2872 "RadioSetModemService " + serviceName + ", result = " + result);
2873 }
2874 getOutPrintWriter().println(result);
2875 } catch (RemoteException e) {
2876 Log.w(LOG_TAG,
2877 "RadioSetModemService: " + serviceName + ", error = " + e.getMessage());
2878 errPw.println("Exception: " + e.getMessage());
2879 return -1;
2880 }
2881 return 0;
2882 }
2883
2884 private int handleRadioGetModemServiceCommand() {
2885 PrintWriter errPw = getErrPrintWriter();
2886 String result;
2887
2888 try {
2889 result = mInterface.getModemService();
2890 getOutPrintWriter().println(result);
2891 } catch (RemoteException e) {
2892 errPw.println("Exception: " + e.getMessage());
2893 return -1;
2894 }
2895 if (VDBG) {
2896 Log.v(LOG_TAG, "RadioGetModemService, result = " + result);
2897 }
2898 return 0;
2899 }
2900
2901 private int handleRadioCommand() {
2902 String arg = getNextArg();
2903 if (arg == null) {
2904 onHelpRadio();
2905 return 0;
2906 }
2907
2908 switch (arg) {
2909 case RADIO_SET_MODEM_SERVICE:
2910 return handleRadioSetModemServiceCommand();
2911
2912 case RADIO_GET_MODEM_SERVICE:
2913 return handleRadioGetModemServiceCommand();
2914 }
2915
2916 return -1;
2917 }
Jack Yu43c3dfe2021-12-03 23:58:26 -08002918
2919 private int handleGetDataMode() {
2920 if (!checkShellUid()) {
2921 return -1;
2922 }
2923
2924 boolean newDataStackEnabled = false;
2925 try {
2926 newDataStackEnabled = mInterface.isUsingNewDataStack();
2927 } catch (RemoteException e) {
2928 getOutPrintWriter().println("Something went wrong. " + e);
2929 return -1;
2930 }
2931
2932 getOutPrintWriter().println("Telephony new data stack is "
2933 + (newDataStackEnabled ? "enabled." : "disabled."));
2934
2935 boolean configEnabled = Boolean.parseBoolean(DeviceConfig.getProperty(
2936 DeviceConfig.NAMESPACE_TELEPHONY, "new_telephony_data_enabled"));
2937 if (configEnabled != newDataStackEnabled) {
2938 getOutPrintWriter().println("The config has been "
2939 + (configEnabled ? "enabled" : "disabled") + ". Need to reboot the device.");
2940 } else {
2941 getOutPrintWriter().println("Run the following command to "
2942 + (configEnabled ? "disable" : "enable") + " the new telephony data stack.");
2943 getOutPrintWriter().println("adb root && adb shell device_config put telephony "
2944 + "new_telephony_data_enabled " + (configEnabled ? "false" : "true")
2945 + " && adb reboot");
2946 }
2947 return 0;
2948 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002949}