blob: 2fd9f7b1c2b5b267090adb98bc7b4bea579def31 [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;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010033import android.telephony.CarrierConfigManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070034import android.telephony.SubscriptionManager;
Michele Berionne54af4632020-12-28 20:23:16 +000035import android.telephony.TelephonyManager;
sqian9d4df8b2019-01-15 18:32:07 -080036import android.telephony.emergency.EmergencyNumber;
Brad Ebinger14d467f2021-02-12 06:18:28 +000037import android.telephony.ims.ImsException;
38import android.telephony.ims.RcsContactUceCapability;
Brad Ebinger24c29992019-12-05 13:03:21 -080039import android.telephony.ims.feature.ImsFeature;
James.cf Linbcdf8b32021-01-14 16:44:13 +080040import android.text.TextUtils;
Brad Ebinger14d467f2021-02-12 06:18:28 +000041import android.util.ArrayMap;
42import android.util.ArraySet;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070043import android.util.Log;
44
Brad Ebinger14d467f2021-02-12 06:18:28 +000045import com.android.ims.rcs.uce.util.FeatureTags;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070046import com.android.internal.telephony.ITelephony;
Qiong Liuf25799b2020-09-10 10:13:46 +080047import com.android.internal.telephony.Phone;
48import com.android.internal.telephony.PhoneFactory;
Tyler Gunn92479152021-01-20 16:30:10 -080049import com.android.internal.telephony.d2d.Communicator;
sqian9d4df8b2019-01-15 18:32:07 -080050import com.android.internal.telephony.emergency.EmergencyNumberTracker;
Meng Wangc4f61042019-11-21 10:51:05 -080051import com.android.internal.telephony.util.TelephonyUtils;
Chiachang Wang99890092020-11-04 10:59:17 +080052import com.android.modules.utils.BasicShellCommandHandler;
Hall Liuaa4211e2021-01-20 15:43:39 -080053import com.android.phone.callcomposer.CallComposerPictureManager;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070054
55import java.io.PrintWriter;
sqian9d4df8b2019-01-15 18:32:07 -080056import java.util.ArrayList;
Brad Ebinger14d467f2021-02-12 06:18:28 +000057import java.util.Arrays;
58import java.util.Collections;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010059import java.util.HashMap;
Brad Ebinger24c29992019-12-05 13:03:21 -080060import java.util.List;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010061import java.util.Map;
Brad Ebinger14d467f2021-02-12 06:18:28 +000062import java.util.Set;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010063import java.util.TreeSet;
Hall Liuaa4211e2021-01-20 15:43:39 -080064import java.util.UUID;
65import java.util.concurrent.CompletableFuture;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070066
67/**
68 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
69 * permission checks have been done before onCommand was called. Make sure any commands processed
70 * here also contain the appropriate permissions checks.
71 */
72
Hall Liua1548bd2019-12-24 14:14:12 -080073public class TelephonyShellCommand extends BasicShellCommandHandler {
Brad Ebinger4dc095a2018-04-03 15:17:52 -070074
75 private static final String LOG_TAG = "TelephonyShellCommand";
76 // Don't commit with this true.
77 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070078 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070079
Hall Liuaa4211e2021-01-20 15:43:39 -080080 private static final String CALL_COMPOSER_SUBCOMMAND = "callcomposer";
Brad Ebinger4dc095a2018-04-03 15:17:52 -070081 private static final String IMS_SUBCOMMAND = "ims";
Hall Liud892bec2018-11-30 14:51:45 -080082 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
Shuo Qianccbaf742021-02-22 18:32:21 -080083 private static final String EMERGENCY_CALLBACK_MODE = "emergency-callback-mode";
sqian9d4df8b2019-01-15 18:32:07 -080084 private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode";
Shuo Qian489d9282020-07-09 11:30:03 -070085 private static final String END_BLOCK_SUPPRESSION = "end-block-suppression";
Michele Berionne54af4632020-12-28 20:23:16 +000086 private static final String RESTART_MODEM = "restart-modem";
Michele Berionne5e411512020-11-13 02:36:59 +000087 private static final String UNATTENDED_REBOOT = "unattended-reboot";
Torbjorn Eklund1050cb02018-11-16 14:05:38 +010088 private static final String CARRIER_CONFIG_SUBCOMMAND = "cc";
Shuo Qianf5125122019-12-16 17:03:07 -080089 private static final String DATA_TEST_MODE = "data";
Hall Liuaa4211e2021-01-20 15:43:39 -080090 private static final String ENABLE = "enable";
91 private static final String DISABLE = "disable";
92 private static final String QUERY = "query";
93
Hall Liu7135e502021-02-04 16:58:17 -080094 private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
Hall Liuaa4211e2021-01-20 15:43:39 -080095 private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
Hall Liu7917ecf2021-02-23 12:22:31 -080096 private static final String CALL_COMPOSER_USER_SETTING = "user-setting";
Hall Liud892bec2018-11-30 14:51:45 -080097
Brad Ebinger999d3302020-11-25 14:31:39 -080098 private static final String IMS_SET_IMS_SERVICE = "set-ims-service";
99 private static final String IMS_GET_IMS_SERVICE = "get-ims-service";
100 private static final String IMS_CLEAR_SERVICE_OVERRIDE = "clear-ims-service-override";
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700101 // Used to disable or enable processing of conference event package data from the network.
102 // This is handy for testing scenarios where CEP data does not exist on a network which does
103 // support CEP data.
104 private static final String IMS_CEP = "conference-event-package";
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700105
Hall Liud892bec2018-11-30 14:51:45 -0800106 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
Hall Liuca5af3a2018-12-04 16:58:23 -0800107 private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call";
Hall Liud892bec2018-11-30 14:51:45 -0800108
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100109 private static final String CC_GET_VALUE = "get-value";
110 private static final String CC_SET_VALUE = "set-value";
111 private static final String CC_CLEAR_VALUES = "clear-values";
112
Hui Wang641e81c2020-10-12 12:14:23 -0700113 private static final String GBA_SUBCOMMAND = "gba";
114 private static final String GBA_SET_SERVICE = "set-service";
115 private static final String GBA_GET_SERVICE = "get-service";
116 private static final String GBA_SET_RELEASE_TIME = "set-release";
117 private static final String GBA_GET_RELEASE_TIME = "get-release";
118
Hui Wang761a6682020-10-31 05:12:53 +0000119 private static final String SINGLE_REGISTATION_CONFIG = "src";
120 private static final String SRC_SET_DEVICE_ENABLED = "set-device-enabled";
121 private static final String SRC_GET_DEVICE_ENABLED = "get-device-enabled";
122 private static final String SRC_SET_CARRIER_ENABLED = "set-carrier-enabled";
123 private static final String SRC_GET_CARRIER_ENABLED = "get-carrier-enabled";
Hui Wangbaaee6a2021-02-19 20:45:36 -0800124 private static final String SRC_SET_TEST_ENABLED = "set-test-enabled";
125 private static final String SRC_GET_TEST_ENABLED = "get-test-enabled";
Hui Wangb647abe2021-02-26 09:33:38 -0800126 private static final String SRC_SET_FEATURE_ENABLED = "set-feature-validation";
127 private static final String SRC_GET_FEATURE_ENABLED = "get-feature-validation";
Hui Wang761a6682020-10-31 05:12:53 +0000128
Tyler Gunn92479152021-01-20 16:30:10 -0800129 private static final String D2D_SUBCOMMAND = "d2d";
130 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800131 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800132
James.cf Linbcdf8b32021-01-14 16:44:13 +0800133 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800134 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800135 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800136 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
137 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000138 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
139 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800140
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800141 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
142 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
143
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700144 // Take advantage of existing methods that already contain permissions checks when possible.
145 private final ITelephony mInterface;
146
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100147 private SubscriptionManager mSubscriptionManager;
148 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700149 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100150
151 private enum CcType {
152 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
153 STRING_ARRAY, UNKNOWN
154 }
155
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100156 private class CcOptionParseResult {
157 public int mSubId;
158 public boolean mPersistent;
159 }
160
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100161 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
162 // keys by looking at the end of the string which usually tells the type.
163 // For instance: "xxxx_string", "xxxx_string_array", etc.
164 // The carrier config keys in this map does not follow this convention. It is therefore not
165 // possible to infer the type for these keys by looking at the string.
166 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
167 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
168 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
169 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
170 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
171 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
172 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
173 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
174 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
175 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
176 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
177 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
178 CcType.STRING);
179 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
180 CcType.STRING_ARRAY);
181 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
182 CcType.STRING_ARRAY);
183 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
184 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
185 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
186 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
187 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
188 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
189 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
190 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
191 }
192 };
193
Brad Ebinger14d467f2021-02-12 06:18:28 +0000194 /**
195 * Map from a shorthand string to the feature tags required in registration required in order
196 * for the RCS feature to be considered "capable".
197 */
198 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
199 static {
200 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
201 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
202 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
203 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
204 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
205 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
206 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
207 FeatureTags.FEATURE_TAG_VIDEO)));
208 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
209 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
210 map.put("call_comp",
211 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
212 map.put("call_comp_mmtel",
213 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
214 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
215 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
216 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
217 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
218 // version
219 map.put("chatbot", new ArraySet<>(Arrays.asList(
220 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
221 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
222 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
223 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
224 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
225 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
226 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
227 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
228 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
229 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
230 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
231 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
232 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
233 }
234
235
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100236 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700237 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100238 mCarrierConfigManager =
239 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
240 mSubscriptionManager = (SubscriptionManager)
241 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700242 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700243 }
244
245 @Override
246 public int onCommand(String cmd) {
247 if (cmd == null) {
248 return handleDefaultCommands(null);
249 }
250
251 switch (cmd) {
252 case IMS_SUBCOMMAND: {
253 return handleImsCommand();
254 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800255 case RCS_UCE_COMMAND:
256 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800257 case NUMBER_VERIFICATION_SUBCOMMAND:
258 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800259 case EMERGENCY_CALLBACK_MODE:
260 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800261 case EMERGENCY_NUMBER_TEST_MODE:
262 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100263 case CARRIER_CONFIG_SUBCOMMAND: {
264 return handleCcCommand();
265 }
Shuo Qianf5125122019-12-16 17:03:07 -0800266 case DATA_TEST_MODE:
267 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700268 case END_BLOCK_SUPPRESSION:
269 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700270 case GBA_SUBCOMMAND:
271 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800272 case D2D_SUBCOMMAND:
273 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000274 case SINGLE_REGISTATION_CONFIG:
275 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000276 case RESTART_MODEM:
277 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800278 case CALL_COMPOSER_SUBCOMMAND:
279 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000280 case UNATTENDED_REBOOT:
281 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800282 case HAS_CARRIER_PRIVILEGES_COMMAND:
283 return handleHasCarrierPrivilegesCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700284 default: {
285 return handleDefaultCommands(cmd);
286 }
287 }
288 }
289
290 @Override
291 public void onHelp() {
292 PrintWriter pw = getOutPrintWriter();
293 pw.println("Telephony Commands:");
294 pw.println(" help");
295 pw.println(" Print this help text.");
296 pw.println(" ims");
297 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800298 pw.println(" uce");
299 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800300 pw.println(" emergency-number-test-mode");
301 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700302 pw.println(" end-block-suppression");
303 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800304 pw.println(" data");
305 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100306 pw.println(" cc");
307 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700308 pw.println(" gba");
309 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000310 pw.println(" src");
311 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000312 pw.println(" restart-modem");
313 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000314 pw.println(" unattended-reboot");
315 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800316 pw.println(" has-carrier-privileges [package]");
317 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700318 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800319 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800320 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700321 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800322 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100323 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700324 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000325 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800326 onHelpD2D();
327 }
328
329 private void onHelpD2D() {
330 PrintWriter pw = getOutPrintWriter();
331 pw.println("D2D Comms Commands:");
332 pw.println(" d2d send TYPE VALUE");
333 pw.println(" Sends a D2D message of specified type and value.");
334 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
335 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
336 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
337 MESSAGE_CALL_AUDIO_CODEC));
338 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
339 + Communicator.messageToString(
340 MESSAGE_DEVICE_BATTERY_STATE));
341 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
342 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800343 pw.println(" d2d transport TYPE");
344 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
345 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700346 }
347
348 private void onHelpIms() {
349 PrintWriter pw = getOutPrintWriter();
350 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800351 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700352 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
353 pw.println(" ImsService. Options are:");
354 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
355 pw.println(" is specified, it will choose the default voice SIM slot.");
356 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
357 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800358 pw.println(" -f: Set the feature that this override if for, if no option is");
359 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700360 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
361 pw.println(" Gets the package name of the currently defined ImsService.");
362 pw.println(" Options are:");
363 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
364 pw.println(" is specified, it will choose the default voice SIM slot.");
365 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000366 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800367 pw.println(" -f: The feature type that the query will be requested for. If none is");
368 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800369 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
370 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
371 pw.println(" configuration overrides. Options are:");
372 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
373 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700374 pw.println(" ims enable [-s SLOT_ID]");
375 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
376 pw.println(" if none is specified.");
377 pw.println(" ims disable [-s SLOT_ID]");
378 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
379 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700380 pw.println(" ims conference-event-package [enable/disable]");
381 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700382 }
383
James.cf Linbcdf8b32021-01-14 16:44:13 +0800384 private void onHelpUce() {
385 PrintWriter pw = getOutPrintWriter();
386 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800387 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
388 pw.println(" Get the EAB contacts from the EAB database.");
389 pw.println(" Options are:");
390 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
391 pw.println(" Expected output format :");
392 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800393 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
394 pw.println(" Remove the EAB contacts from the EAB database.");
395 pw.println(" Options are:");
396 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
397 pw.println(" is specified, it will choose the default voice SIM slot.");
398 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800399 pw.println(" uce get-device-enabled");
400 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
401 pw.println(" uce set-device-enabled true|false");
402 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
403 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000404 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
405 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
406 pw.println(" Options are:");
407 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
408 pw.println(" is specified, it will choose the default voice SIM slot.");
409 pw.println(" add [CAPABILITY]: add a new capability");
410 pw.println(" remove [CAPABILITY]: remove a capability");
411 pw.println(" clear: clear all capability overrides");
412 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
413 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
414 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
415 pw.println(" chatbot_sa, chatbot_role] as well as full length");
416 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
417 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
418 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
419 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800420 }
421
Hall Liud892bec2018-11-30 14:51:45 -0800422 private void onHelpNumberVerification() {
423 PrintWriter pw = getOutPrintWriter();
424 pw.println("Number verification commands");
425 pw.println(" numverify override-package PACKAGE_NAME;");
426 pw.println(" Set the authorized package for number verification.");
427 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800428 pw.println(" numverify fake-call NUMBER;");
429 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
430 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800431 }
432
Shuo Qianf5125122019-12-16 17:03:07 -0800433 private void onHelpDataTestMode() {
434 PrintWriter pw = getOutPrintWriter();
435 pw.println("Mobile Data Test Mode Commands:");
436 pw.println(" data enable: enable mobile data connectivity");
437 pw.println(" data disable: disable mobile data connectivity");
438 }
439
sqian9d4df8b2019-01-15 18:32:07 -0800440 private void onHelpEmergencyNumber() {
441 PrintWriter pw = getOutPrintWriter();
442 pw.println("Emergency Number Test Mode Commands:");
443 pw.println(" emergency-number-test-mode ");
444 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
445 + " the test mode");
446 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700447 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800448 pw.println(" -c: clear the emergency number list in the test mode.");
449 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700450 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800451 pw.println(" -p: get the full emergency number list in the test mode.");
452 }
453
Shuo Qian489d9282020-07-09 11:30:03 -0700454 private void onHelpEndBlockSupperssion() {
455 PrintWriter pw = getOutPrintWriter();
456 pw.println("End Block Suppression command:");
457 pw.println(" end-block-suppression: disable suppressing blocking by contact");
458 pw.println(" with emergency services.");
459 }
460
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100461 private void onHelpCc() {
462 PrintWriter pw = getOutPrintWriter();
463 pw.println("Carrier Config Commands:");
464 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
465 pw.println(" Print carrier config values.");
466 pw.println(" Options are:");
467 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
468 pw.println(" is specified, it will choose the default voice SIM slot.");
469 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
470 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100471 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100472 pw.println(" Set carrier config KEY to NEW_VALUE.");
473 pw.println(" Options are:");
474 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
475 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100476 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100477 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
478 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
479 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
480 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
481 pw.println(" cc clear-values [-s SLOT_ID]");
482 pw.println(" Clear all carrier override values that has previously been set");
483 pw.println(" with set-value");
484 pw.println(" Options are:");
485 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
486 pw.println(" is specified, it will choose the default voice SIM slot.");
487 }
488
Hui Wang641e81c2020-10-12 12:14:23 -0700489 private void onHelpGba() {
490 PrintWriter pw = getOutPrintWriter();
491 pw.println("Gba Commands:");
492 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
493 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
494 pw.println(" Options are:");
495 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
496 pw.println(" is specified, it will choose the default voice SIM slot.");
497 pw.println(" gba get-service [-s SLOT_ID]");
498 pw.println(" Gets the package name of the currently defined GbaService.");
499 pw.println(" Options are:");
500 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
501 pw.println(" is specified, it will choose the default voice SIM slot.");
502 pw.println(" gba set-release [-s SLOT_ID] n");
503 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
504 pw.println(" Do not release/unbind if n is -1.");
505 pw.println(" Options are:");
506 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
507 pw.println(" is specified, it will choose the default voice SIM slot.");
508 pw.println(" gba get-release [-s SLOT_ID]");
509 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
510 pw.println(" Options are:");
511 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
512 pw.println(" is specified, it will choose the default voice SIM slot.");
513 }
514
Hui Wang761a6682020-10-31 05:12:53 +0000515 private void onHelpSrc() {
516 PrintWriter pw = getOutPrintWriter();
517 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800518 pw.println(" src set-test-enabled true|false");
519 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
520 pw.println(" The value could be true, false, or null(undefined).");
521 pw.println(" src get-test-enabled");
522 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000523 pw.println(" src set-device-enabled true|false|null");
524 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
525 pw.println(" The value could be true, false, or null(undefined).");
526 pw.println(" src get-device-enabled");
527 pw.println(" Gets the device config for RCS VoLTE single registration.");
528 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
529 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
530 pw.println(" The value could be true, false, or null(undefined).");
531 pw.println(" Options are:");
532 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
533 pw.println(" is specified, it will choose the default voice SIM slot.");
534 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
535 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
536 pw.println(" Options are:");
537 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
538 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800539 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
540 pw.println(" Sets ims feature validation result.");
541 pw.println(" The value could be true, false, or null(undefined).");
542 pw.println(" Options are:");
543 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
544 pw.println(" is specified, it will choose the default voice SIM slot.");
545 pw.println(" src get-feature-validation [-s SLOT_ID]");
546 pw.println(" Gets ims feature validation override value.");
547 pw.println(" Options are:");
548 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
549 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000550 }
551
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700552 private int handleImsCommand() {
553 String arg = getNextArg();
554 if (arg == null) {
555 onHelpIms();
556 return 0;
557 }
558
559 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800560 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700561 return handleImsSetServiceCommand();
562 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800563 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700564 return handleImsGetServiceCommand();
565 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800566 case IMS_CLEAR_SERVICE_OVERRIDE: {
567 return handleImsClearCarrierServiceCommand();
568 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800569 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700570 return handleEnableIms();
571 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800572 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700573 return handleDisableIms();
574 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700575 case IMS_CEP: {
576 return handleCepChange();
577 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700578 }
579
580 return -1;
581 }
582
Shuo Qianf5125122019-12-16 17:03:07 -0800583 private int handleDataTestModeCommand() {
584 PrintWriter errPw = getErrPrintWriter();
585 String arg = getNextArgRequired();
586 if (arg == null) {
587 onHelpDataTestMode();
588 return 0;
589 }
590 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800591 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800592 try {
593 mInterface.enableDataConnectivity();
594 } catch (RemoteException ex) {
595 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
596 errPw.println("Exception: " + ex.getMessage());
597 return -1;
598 }
599 break;
600 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800601 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800602 try {
603 mInterface.disableDataConnectivity();
604 } catch (RemoteException ex) {
605 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
606 errPw.println("Exception: " + ex.getMessage());
607 return -1;
608 }
609 break;
610 }
611 default:
612 onHelpDataTestMode();
613 break;
614 }
615 return 0;
616 }
617
Shuo Qianccbaf742021-02-22 18:32:21 -0800618 private int handleEmergencyCallbackModeCommand() {
619 PrintWriter errPw = getErrPrintWriter();
620 try {
621 mInterface.startEmergencyCallbackMode();
622 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
623 } catch (RemoteException ex) {
624 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
625 errPw.println("Exception: " + ex.getMessage());
626 return -1;
627 }
628 return 0;
629 }
630
sqian9d4df8b2019-01-15 18:32:07 -0800631 private int handleEmergencyNumberTestModeCommand() {
632 PrintWriter errPw = getErrPrintWriter();
633 String opt = getNextOption();
634 if (opt == null) {
635 onHelpEmergencyNumber();
636 return 0;
637 }
638
639 switch (opt) {
640 case "-a": {
641 String emergencyNumberCmd = getNextArgRequired();
642 if (emergencyNumberCmd == null
643 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700644 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800645 + " to be specified after -a in the command ");
646 return -1;
647 }
648 try {
649 mInterface.updateEmergencyNumberListTestMode(
650 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
651 new EmergencyNumber(emergencyNumberCmd, "", "",
652 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
653 new ArrayList<String>(),
654 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
655 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
656 } catch (RemoteException ex) {
657 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
658 + ", error " + ex.getMessage());
659 errPw.println("Exception: " + ex.getMessage());
660 return -1;
661 }
662 break;
663 }
664 case "-c": {
665 try {
666 mInterface.updateEmergencyNumberListTestMode(
667 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
668 } catch (RemoteException ex) {
669 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
670 errPw.println("Exception: " + ex.getMessage());
671 return -1;
672 }
673 break;
674 }
675 case "-r": {
676 String emergencyNumberCmd = getNextArgRequired();
677 if (emergencyNumberCmd == null
678 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700679 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800680 + " to be specified after -r in the command ");
681 return -1;
682 }
683 try {
684 mInterface.updateEmergencyNumberListTestMode(
685 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
686 new EmergencyNumber(emergencyNumberCmd, "", "",
687 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
688 new ArrayList<String>(),
689 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
690 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
691 } catch (RemoteException ex) {
692 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
693 + ", error " + ex.getMessage());
694 errPw.println("Exception: " + ex.getMessage());
695 return -1;
696 }
697 break;
698 }
699 case "-p": {
700 try {
701 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
702 } catch (RemoteException ex) {
703 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
704 errPw.println("Exception: " + ex.getMessage());
705 return -1;
706 }
707 break;
708 }
709 default:
710 onHelpEmergencyNumber();
711 break;
712 }
713 return 0;
714 }
715
Hall Liud892bec2018-11-30 14:51:45 -0800716 private int handleNumberVerificationCommand() {
717 String arg = getNextArg();
718 if (arg == null) {
719 onHelpNumberVerification();
720 return 0;
721 }
722
Hall Liuca5af3a2018-12-04 16:58:23 -0800723 if (!checkShellUid()) {
724 return -1;
725 }
726
Hall Liud892bec2018-11-30 14:51:45 -0800727 switch (arg) {
728 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800729 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
730 return 0;
731 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800732 case NUMBER_VERIFICATION_FAKE_CALL: {
733 boolean val = NumberVerificationManager.getInstance()
734 .checkIncomingCall(getNextArg());
735 getOutPrintWriter().println(val ? "1" : "0");
736 return 0;
737 }
Hall Liud892bec2018-11-30 14:51:45 -0800738 }
739
740 return -1;
741 }
742
Tyler Gunn92479152021-01-20 16:30:10 -0800743 private int handleD2dCommand() {
744 String arg = getNextArg();
745 if (arg == null) {
746 onHelpD2D();
747 return 0;
748 }
749
750 switch (arg) {
751 case D2D_SEND: {
752 return handleD2dSendCommand();
753 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800754 case D2D_TRANSPORT: {
755 return handleD2dTransportCommand();
756 }
Tyler Gunn92479152021-01-20 16:30:10 -0800757 }
758
759 return -1;
760 }
761
762 private int handleD2dSendCommand() {
763 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800764 int messageType = -1;
765 int messageValue = -1;
766
Tyler Gunn92479152021-01-20 16:30:10 -0800767 String arg = getNextArg();
768 if (arg == null) {
769 onHelpD2D();
770 return 0;
771 }
772 try {
773 messageType = Integer.parseInt(arg);
774 } catch (NumberFormatException e) {
775 errPw.println("message type must be a valid integer");
776 return -1;
777 }
778
779 arg = getNextArg();
780 if (arg == null) {
781 onHelpD2D();
782 return 0;
783 }
784 try {
785 messageValue = Integer.parseInt(arg);
786 } catch (NumberFormatException e) {
787 errPw.println("message value must be a valid integer");
788 return -1;
789 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800790
Tyler Gunn92479152021-01-20 16:30:10 -0800791 try {
792 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
793 } catch (RemoteException e) {
794 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
795 errPw.println("Exception: " + e.getMessage());
796 return -1;
797 }
798
799 return 0;
800 }
801
Tyler Gunnbabbda02021-02-10 11:05:02 -0800802 private int handleD2dTransportCommand() {
803 PrintWriter errPw = getErrPrintWriter();
804
805 String arg = getNextArg();
806 if (arg == null) {
807 onHelpD2D();
808 return 0;
809 }
810
811 try {
812 mInterface.setActiveDeviceToDeviceTransport(arg);
813 } catch (RemoteException e) {
814 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
815 errPw.println("Exception: " + e.getMessage());
816 return -1;
817 }
818 return 0;
819 }
820
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700821 // ims set-ims-service
822 private int handleImsSetServiceCommand() {
823 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700824 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700825 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800826 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700827
828 String opt;
829 while ((opt = getNextOption()) != null) {
830 switch (opt) {
831 case "-s": {
832 try {
833 slotId = Integer.parseInt(getNextArgRequired());
834 } catch (NumberFormatException e) {
835 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
836 return -1;
837 }
838 break;
839 }
840 case "-c": {
841 isCarrierService = true;
842 break;
843 }
844 case "-d": {
845 isCarrierService = false;
846 break;
847 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800848 case "-f": {
849 String featureString = getNextArgRequired();
850 String[] features = featureString.split(",");
851 for (int i = 0; i < features.length; i++) {
852 try {
853 Integer result = Integer.parseInt(features[i]);
854 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
855 || result >= ImsFeature.FEATURE_MAX) {
856 errPw.println("ims set-ims-service -f " + result
857 + " is an invalid feature.");
858 return -1;
859 }
860 featuresList.add(result);
861 } catch (NumberFormatException e) {
862 errPw.println("ims set-ims-service -f tried to parse " + features[i]
863 + " as an integer.");
864 return -1;
865 }
866 }
867 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700868 }
869 }
870 // Mandatory param, either -c or -d
871 if (isCarrierService == null) {
872 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
873 return -1;
874 }
875
876 String packageName = getNextArg();
877
878 try {
879 if (packageName == null) {
880 packageName = "";
881 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800882 int[] featureArray = new int[featuresList.size()];
883 for (int i = 0; i < featuresList.size(); i++) {
884 featureArray[i] = featuresList.get(i);
885 }
886 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
887 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700888 if (VDBG) {
889 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800890 + (isCarrierService ? "-c " : "-d ")
891 + "-f " + featuresList + " "
892 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700893 }
894 getOutPrintWriter().println(result);
895 } catch (RemoteException e) {
896 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800897 + (isCarrierService ? "-c " : "-d ")
898 + "-f " + featuresList + " "
899 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700900 errPw.println("Exception: " + e.getMessage());
901 return -1;
902 }
903 return 0;
904 }
905
Brad Ebinger999d3302020-11-25 14:31:39 -0800906 // ims clear-ims-service-override
907 private int handleImsClearCarrierServiceCommand() {
908 PrintWriter errPw = getErrPrintWriter();
909 int slotId = getDefaultSlot();
910
911 String opt;
912 while ((opt = getNextOption()) != null) {
913 switch (opt) {
914 case "-s": {
915 try {
916 slotId = Integer.parseInt(getNextArgRequired());
917 } catch (NumberFormatException e) {
918 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
919 return -1;
920 }
921 break;
922 }
923 }
924 }
925
926 try {
927 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
928 if (VDBG) {
929 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
930 + ", result=" + result);
931 }
932 getOutPrintWriter().println(result);
933 } catch (RemoteException e) {
934 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
935 + ", error" + e.getMessage());
936 errPw.println("Exception: " + e.getMessage());
937 return -1;
938 }
939 return 0;
940 }
941
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700942 // ims get-ims-service
943 private int handleImsGetServiceCommand() {
944 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700945 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700946 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800947 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700948
949 String opt;
950 while ((opt = getNextOption()) != null) {
951 switch (opt) {
952 case "-s": {
953 try {
954 slotId = Integer.parseInt(getNextArgRequired());
955 } catch (NumberFormatException e) {
956 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
957 return -1;
958 }
959 break;
960 }
961 case "-c": {
962 isCarrierService = true;
963 break;
964 }
965 case "-d": {
966 isCarrierService = false;
967 break;
968 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800969 case "-f": {
970 try {
971 featureType = Integer.parseInt(getNextArg());
972 } catch (NumberFormatException e) {
973 errPw.println("ims get-ims-service -f requires valid integer as feature.");
974 return -1;
975 }
976 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
977 || featureType >= ImsFeature.FEATURE_MAX) {
978 errPw.println("ims get-ims-service -f invalid feature.");
979 return -1;
980 }
981 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700982 }
983 }
984 // Mandatory param, either -c or -d
985 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800986 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700987 return -1;
988 }
989
990 String result;
991 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800992 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700993 } catch (RemoteException e) {
994 return -1;
995 }
996 if (VDBG) {
997 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800998 + (isCarrierService ? "-c " : "-d ")
999 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1000 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001001 }
1002 getOutPrintWriter().println(result);
1003 return 0;
1004 }
1005
1006 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001007 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001008 String opt;
1009 while ((opt = getNextOption()) != null) {
1010 switch (opt) {
1011 case "-s": {
1012 try {
1013 slotId = Integer.parseInt(getNextArgRequired());
1014 } catch (NumberFormatException e) {
1015 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1016 return -1;
1017 }
1018 break;
1019 }
1020 }
1021 }
1022 try {
1023 mInterface.enableIms(slotId);
1024 } catch (RemoteException e) {
1025 return -1;
1026 }
1027 if (VDBG) {
1028 Log.v(LOG_TAG, "ims enable -s " + slotId);
1029 }
1030 return 0;
1031 }
1032
1033 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001034 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001035 String opt;
1036 while ((opt = getNextOption()) != null) {
1037 switch (opt) {
1038 case "-s": {
1039 try {
1040 slotId = Integer.parseInt(getNextArgRequired());
1041 } catch (NumberFormatException e) {
1042 getErrPrintWriter().println(
1043 "ims disable requires an integer as a SLOT_ID.");
1044 return -1;
1045 }
1046 break;
1047 }
1048 }
1049 }
1050 try {
1051 mInterface.disableIms(slotId);
1052 } catch (RemoteException e) {
1053 return -1;
1054 }
1055 if (VDBG) {
1056 Log.v(LOG_TAG, "ims disable -s " + slotId);
1057 }
1058 return 0;
1059 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001060
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001061 private int handleCepChange() {
1062 Log.i(LOG_TAG, "handleCepChange");
1063 String opt = getNextArg();
1064 if (opt == null) {
1065 return -1;
1066 }
1067 boolean isCepEnabled = opt.equals("enable");
1068
1069 try {
1070 mInterface.setCepEnabled(isCepEnabled);
1071 } catch (RemoteException e) {
1072 return -1;
1073 }
1074 return 0;
1075 }
1076
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001077 private int getDefaultSlot() {
1078 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1079 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1080 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1081 // If there is no default, default to slot 0.
1082 slotId = DEFAULT_PHONE_ID;
1083 }
1084 return slotId;
1085 }
sqian2fff4a32018-11-05 14:18:37 -08001086
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001087 // Parse options related to Carrier Config Commands.
1088 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001089 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001090 CcOptionParseResult result = new CcOptionParseResult();
1091 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1092 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001093
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001094 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001095 while ((opt = getNextOption()) != null) {
1096 switch (opt) {
1097 case "-s": {
1098 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001099 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1100 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1101 errPw.println(tag + "No valid subscription found.");
1102 return null;
1103 }
1104
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001105 } catch (IllegalArgumentException e) {
1106 // Missing slot id
1107 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001108 return null;
1109 }
1110 break;
1111 }
1112 case "-p": {
1113 if (allowOptionPersistent) {
1114 result.mPersistent = true;
1115 } else {
1116 errPw.println(tag + "Unexpected option " + opt);
1117 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001118 }
1119 break;
1120 }
1121 default: {
1122 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001123 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001124 }
1125 }
1126 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001127 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001128 }
1129
1130 private int slotStringToSubId(String tag, String slotString) {
1131 int slotId = -1;
1132 try {
1133 slotId = Integer.parseInt(slotString);
1134 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001135 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1136 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1137 }
1138
1139 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001140 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1141 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1142 }
1143
Qiong Liuf25799b2020-09-10 10:13:46 +08001144 Phone phone = PhoneFactory.getPhone(slotId);
1145 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001146 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1147 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1148 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001149 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001150 }
1151
Hall Liud892bec2018-11-30 14:51:45 -08001152 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001153 // adb can run as root or as shell, depending on whether the device is rooted.
1154 return Binder.getCallingUid() == Process.SHELL_UID
1155 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001156 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001157
1158 private int handleCcCommand() {
1159 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1160 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001161 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001162 getErrPrintWriter().println("cc: Permission denied.");
1163 return -1;
1164 }
1165
1166 String arg = getNextArg();
1167 if (arg == null) {
1168 onHelpCc();
1169 return 0;
1170 }
1171
1172 switch (arg) {
1173 case CC_GET_VALUE: {
1174 return handleCcGetValue();
1175 }
1176 case CC_SET_VALUE: {
1177 return handleCcSetValue();
1178 }
1179 case CC_CLEAR_VALUES: {
1180 return handleCcClearValues();
1181 }
1182 default: {
1183 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1184 }
1185 }
1186 return -1;
1187 }
1188
1189 // cc get-value
1190 private int handleCcGetValue() {
1191 PrintWriter errPw = getErrPrintWriter();
1192 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1193 String key = null;
1194
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001195 // Parse all options
1196 CcOptionParseResult options = parseCcOptions(tag, false);
1197 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001198 return -1;
1199 }
1200
1201 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001202 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001203 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001204 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001205 return -1;
1206 }
1207
1208 // Get the key.
1209 key = getNextArg();
1210 if (key != null) {
1211 // A key was provided. Verify if it is a valid key
1212 if (!bundle.containsKey(key)) {
1213 errPw.println(tag + key + " is not a valid key.");
1214 return -1;
1215 }
1216
1217 // Print the carrier config value for key.
1218 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1219 } else {
1220 // No key provided. Show all values.
1221 // Iterate over a sorted list of all carrier config keys and print them.
1222 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1223 for (String k : sortedSet) {
1224 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1225 }
1226 }
1227 return 0;
1228 }
1229
1230 // cc set-value
1231 private int handleCcSetValue() {
1232 PrintWriter errPw = getErrPrintWriter();
1233 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1234
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001235 // Parse all options
1236 CcOptionParseResult options = parseCcOptions(tag, true);
1237 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001238 return -1;
1239 }
1240
1241 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001242 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001243 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001244 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001245 return -1;
1246 }
1247
1248 // Get the key.
1249 String key = getNextArg();
1250 if (key == null || key.equals("")) {
1251 errPw.println(tag + "KEY is missing");
1252 return -1;
1253 }
1254
1255 // Verify if the key is valid
1256 if (!originalValues.containsKey(key)) {
1257 errPw.println(tag + key + " is not a valid key.");
1258 return -1;
1259 }
1260
1261 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1262 ArrayList<String> valueList = new ArrayList<String>();
1263 while (peekNextArg() != null) {
1264 valueList.add(getNextArg());
1265 }
1266
1267 // Find the type of the carrier config value
1268 CcType type = getType(tag, key, originalValues);
1269 if (type == CcType.UNKNOWN) {
1270 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1271 return -1;
1272 }
1273
1274 // Create an override bundle containing the key and value that should be overriden.
1275 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1276 if (overrideBundle == null) {
1277 return -1;
1278 }
1279
1280 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001281 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001282
1283 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001284 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001285 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001286 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001287 return -1;
1288 }
1289
1290 // Print the original and new value.
1291 String originalValueString = ccValueToString(key, type, originalValues);
1292 String newValueString = ccValueToString(key, type, newValues);
1293 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1294 getOutPrintWriter().println("New value: \n" + newValueString);
1295
1296 return 0;
1297 }
1298
1299 // cc clear-values
1300 private int handleCcClearValues() {
1301 PrintWriter errPw = getErrPrintWriter();
1302 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1303
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001304 // Parse all options
1305 CcOptionParseResult options = parseCcOptions(tag, false);
1306 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001307 return -1;
1308 }
1309
1310 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001311 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001312 getOutPrintWriter()
1313 .println("All previously set carrier config override values has been cleared");
1314 return 0;
1315 }
1316
1317 private CcType getType(String tag, String key, PersistableBundle bundle) {
1318 // Find the type by checking the type of the current value stored in the bundle.
1319 Object value = bundle.get(key);
1320
1321 if (CC_TYPE_MAP.containsKey(key)) {
1322 return CC_TYPE_MAP.get(key);
1323 } else if (value != null) {
1324 if (value instanceof Boolean) {
1325 return CcType.BOOLEAN;
1326 } else if (value instanceof Double) {
1327 return CcType.DOUBLE;
1328 } else if (value instanceof double[]) {
1329 return CcType.DOUBLE_ARRAY;
1330 } else if (value instanceof Integer) {
1331 return CcType.INT;
1332 } else if (value instanceof int[]) {
1333 return CcType.INT_ARRAY;
1334 } else if (value instanceof Long) {
1335 return CcType.LONG;
1336 } else if (value instanceof long[]) {
1337 return CcType.LONG_ARRAY;
1338 } else if (value instanceof String) {
1339 return CcType.STRING;
1340 } else if (value instanceof String[]) {
1341 return CcType.STRING_ARRAY;
1342 }
1343 } else {
1344 // Current value was null and can therefore not be used in order to find the type.
1345 // Check the name of the key to infer the type. This check is not needed for primitive
1346 // data types (boolean, double, int and long), since they can not be null.
1347 if (key.endsWith("double_array")) {
1348 return CcType.DOUBLE_ARRAY;
1349 }
1350 if (key.endsWith("int_array")) {
1351 return CcType.INT_ARRAY;
1352 }
1353 if (key.endsWith("long_array")) {
1354 return CcType.LONG_ARRAY;
1355 }
1356 if (key.endsWith("string")) {
1357 return CcType.STRING;
1358 }
1359 if (key.endsWith("string_array") || key.endsWith("strings")) {
1360 return CcType.STRING_ARRAY;
1361 }
1362 }
1363
1364 // Not possible to infer the type by looking at the current value or the key.
1365 PrintWriter errPw = getErrPrintWriter();
1366 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1367 return CcType.UNKNOWN;
1368 }
1369
1370 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1371 String result;
1372 StringBuilder valueString = new StringBuilder();
1373 String typeString = type.toString();
1374 Object value = bundle.get(key);
1375
1376 if (value == null) {
1377 valueString.append("null");
1378 } else {
1379 switch (type) {
1380 case DOUBLE_ARRAY: {
1381 // Format the string representation of the int array as value1 value2......
1382 double[] valueArray = (double[]) value;
1383 for (int i = 0; i < valueArray.length; i++) {
1384 if (i != 0) {
1385 valueString.append(" ");
1386 }
1387 valueString.append(valueArray[i]);
1388 }
1389 break;
1390 }
1391 case INT_ARRAY: {
1392 // Format the string representation of the int array as value1 value2......
1393 int[] valueArray = (int[]) value;
1394 for (int i = 0; i < valueArray.length; i++) {
1395 if (i != 0) {
1396 valueString.append(" ");
1397 }
1398 valueString.append(valueArray[i]);
1399 }
1400 break;
1401 }
1402 case LONG_ARRAY: {
1403 // Format the string representation of the int array as value1 value2......
1404 long[] valueArray = (long[]) value;
1405 for (int i = 0; i < valueArray.length; i++) {
1406 if (i != 0) {
1407 valueString.append(" ");
1408 }
1409 valueString.append(valueArray[i]);
1410 }
1411 break;
1412 }
1413 case STRING: {
1414 valueString.append("\"" + value.toString() + "\"");
1415 break;
1416 }
1417 case STRING_ARRAY: {
1418 // Format the string representation of the string array as "value1" "value2"....
1419 String[] valueArray = (String[]) value;
1420 for (int i = 0; i < valueArray.length; i++) {
1421 if (i != 0) {
1422 valueString.append(" ");
1423 }
1424 if (valueArray[i] != null) {
1425 valueString.append("\"" + valueArray[i] + "\"");
1426 } else {
1427 valueString.append("null");
1428 }
1429 }
1430 break;
1431 }
1432 default: {
1433 valueString.append(value.toString());
1434 }
1435 }
1436 }
1437 return String.format("%-70s %-15s %s", key, typeString, valueString);
1438 }
1439
1440 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1441 ArrayList<String> valueList) {
1442 PrintWriter errPw = getErrPrintWriter();
1443 PersistableBundle bundle = new PersistableBundle();
1444
1445 // First verify that a valid number of values has been provided for the type.
1446 switch (type) {
1447 case BOOLEAN:
1448 case DOUBLE:
1449 case INT:
1450 case LONG: {
1451 if (valueList.size() != 1) {
1452 errPw.println(tag + "Expected 1 value for type " + type
1453 + ". Found: " + valueList.size());
1454 return null;
1455 }
1456 break;
1457 }
1458 case STRING: {
1459 if (valueList.size() > 1) {
1460 errPw.println(tag + "Expected 0 or 1 values for type " + type
1461 + ". Found: " + valueList.size());
1462 return null;
1463 }
1464 break;
1465 }
1466 }
1467
1468 // Parse the value according to type and add it to the Bundle.
1469 switch (type) {
1470 case BOOLEAN: {
1471 if ("true".equalsIgnoreCase(valueList.get(0))) {
1472 bundle.putBoolean(key, true);
1473 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1474 bundle.putBoolean(key, false);
1475 } else {
1476 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1477 return null;
1478 }
1479 break;
1480 }
1481 case DOUBLE: {
1482 try {
1483 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1484 } catch (NumberFormatException nfe) {
1485 // Not a valid double
1486 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1487 return null;
1488 }
1489 break;
1490 }
1491 case DOUBLE_ARRAY: {
1492 double[] valueDoubleArray = null;
1493 if (valueList.size() > 0) {
1494 valueDoubleArray = new double[valueList.size()];
1495 for (int i = 0; i < valueList.size(); i++) {
1496 try {
1497 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1498 } catch (NumberFormatException nfe) {
1499 // Not a valid double
1500 errPw.println(
1501 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1502 return null;
1503 }
1504 }
1505 }
1506 bundle.putDoubleArray(key, valueDoubleArray);
1507 break;
1508 }
1509 case INT: {
1510 try {
1511 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1512 } catch (NumberFormatException nfe) {
1513 // Not a valid integer
1514 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1515 return null;
1516 }
1517 break;
1518 }
1519 case INT_ARRAY: {
1520 int[] valueIntArray = null;
1521 if (valueList.size() > 0) {
1522 valueIntArray = new int[valueList.size()];
1523 for (int i = 0; i < valueList.size(); i++) {
1524 try {
1525 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1526 } catch (NumberFormatException nfe) {
1527 // Not a valid integer
1528 errPw.println(tag
1529 + "Unable to parse " + valueList.get(i) + " as an integer.");
1530 return null;
1531 }
1532 }
1533 }
1534 bundle.putIntArray(key, valueIntArray);
1535 break;
1536 }
1537 case LONG: {
1538 try {
1539 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1540 } catch (NumberFormatException nfe) {
1541 // Not a valid long
1542 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1543 return null;
1544 }
1545 break;
1546 }
1547 case LONG_ARRAY: {
1548 long[] valueLongArray = null;
1549 if (valueList.size() > 0) {
1550 valueLongArray = new long[valueList.size()];
1551 for (int i = 0; i < valueList.size(); i++) {
1552 try {
1553 valueLongArray[i] = Long.parseLong(valueList.get(i));
1554 } catch (NumberFormatException nfe) {
1555 // Not a valid long
1556 errPw.println(
1557 tag + "Unable to parse " + valueList.get(i) + " as a long");
1558 return null;
1559 }
1560 }
1561 }
1562 bundle.putLongArray(key, valueLongArray);
1563 break;
1564 }
1565 case STRING: {
1566 String value = null;
1567 if (valueList.size() > 0) {
1568 value = valueList.get(0);
1569 }
1570 bundle.putString(key, value);
1571 break;
1572 }
1573 case STRING_ARRAY: {
1574 String[] valueStringArray = null;
1575 if (valueList.size() > 0) {
1576 valueStringArray = new String[valueList.size()];
1577 valueList.toArray(valueStringArray);
1578 }
1579 bundle.putStringArray(key, valueStringArray);
1580 break;
1581 }
1582 }
1583 return bundle;
1584 }
Shuo Qian489d9282020-07-09 11:30:03 -07001585
1586 private int handleEndBlockSuppressionCommand() {
1587 if (!checkShellUid()) {
1588 return -1;
1589 }
1590
1591 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1592 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1593 }
1594 return 0;
1595 }
Hui Wang641e81c2020-10-12 12:14:23 -07001596
Michele Berionne54af4632020-12-28 20:23:16 +00001597 private int handleRestartModemCommand() {
1598 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1599 // non user build.
1600 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1601 getErrPrintWriter().println("RestartModem: Permission denied.");
1602 return -1;
1603 }
1604
1605 boolean result = TelephonyManager.getDefault().rebootRadio();
1606 getOutPrintWriter().println(result);
1607
1608 return result ? 0 : -1;
1609 }
1610
Michele Berionne5e411512020-11-13 02:36:59 +00001611 private int handleUnattendedReboot() {
1612 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1613 // non user build.
1614 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1615 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1616 return -1;
1617 }
1618
1619 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1620 getOutPrintWriter().println("result: " + result);
1621
1622 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1623 }
1624
Hui Wang641e81c2020-10-12 12:14:23 -07001625 private int handleGbaCommand() {
1626 String arg = getNextArg();
1627 if (arg == null) {
1628 onHelpGba();
1629 return 0;
1630 }
1631
1632 switch (arg) {
1633 case GBA_SET_SERVICE: {
1634 return handleGbaSetServiceCommand();
1635 }
1636 case GBA_GET_SERVICE: {
1637 return handleGbaGetServiceCommand();
1638 }
1639 case GBA_SET_RELEASE_TIME: {
1640 return handleGbaSetReleaseCommand();
1641 }
1642 case GBA_GET_RELEASE_TIME: {
1643 return handleGbaGetReleaseCommand();
1644 }
1645 }
1646
1647 return -1;
1648 }
1649
1650 private int getSubId(String cmd) {
1651 int slotId = getDefaultSlot();
1652 String opt = getNextOption();
1653 if (opt != null && opt.equals("-s")) {
1654 try {
1655 slotId = Integer.parseInt(getNextArgRequired());
1656 } catch (NumberFormatException e) {
1657 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1658 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1659 }
1660 }
1661 int[] subIds = SubscriptionManager.getSubId(slotId);
1662 return subIds[0];
1663 }
1664
1665 private int handleGbaSetServiceCommand() {
1666 int subId = getSubId("gba set-service");
1667 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1668 return -1;
1669 }
1670
1671 String packageName = getNextArg();
1672 try {
1673 if (packageName == null) {
1674 packageName = "";
1675 }
1676 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1677 if (VDBG) {
1678 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1679 + packageName + ", result=" + result);
1680 }
1681 getOutPrintWriter().println(result);
1682 } catch (RemoteException e) {
1683 Log.w(LOG_TAG, "gba set-service " + subId + " "
1684 + packageName + ", error" + e.getMessage());
1685 getErrPrintWriter().println("Exception: " + e.getMessage());
1686 return -1;
1687 }
1688 return 0;
1689 }
1690
1691 private int handleGbaGetServiceCommand() {
1692 String result;
1693
1694 int subId = getSubId("gba get-service");
1695 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1696 return -1;
1697 }
1698
1699 try {
1700 result = mInterface.getBoundGbaService(subId);
1701 } catch (RemoteException e) {
1702 return -1;
1703 }
1704 if (VDBG) {
1705 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1706 }
1707 getOutPrintWriter().println(result);
1708 return 0;
1709 }
1710
1711 private int handleGbaSetReleaseCommand() {
1712 //the release time value could be -1
1713 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1714 : SubscriptionManager.getDefaultSubscriptionId();
1715 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1716 return -1;
1717 }
1718
1719 String intervalStr = getNextArg();
1720 if (intervalStr == null) {
1721 return -1;
1722 }
1723
1724 try {
1725 int interval = Integer.parseInt(intervalStr);
1726 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1727 if (VDBG) {
1728 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1729 + intervalStr + ", result=" + result);
1730 }
1731 getOutPrintWriter().println(result);
1732 } catch (NumberFormatException | RemoteException e) {
1733 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1734 + intervalStr + ", error" + e.getMessage());
1735 getErrPrintWriter().println("Exception: " + e.getMessage());
1736 return -1;
1737 }
1738 return 0;
1739 }
1740
1741 private int handleGbaGetReleaseCommand() {
1742 int subId = getSubId("gba get-release");
1743 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1744 return -1;
1745 }
1746
1747 int result = 0;
1748 try {
1749 result = mInterface.getGbaReleaseTime(subId);
1750 } catch (RemoteException e) {
1751 return -1;
1752 }
1753 if (VDBG) {
1754 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1755 }
1756 getOutPrintWriter().println(result);
1757 return 0;
1758 }
Hui Wang761a6682020-10-31 05:12:53 +00001759
1760 private int handleSingleRegistrationConfigCommand() {
1761 String arg = getNextArg();
1762 if (arg == null) {
1763 onHelpSrc();
1764 return 0;
1765 }
1766
1767 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001768 case SRC_SET_TEST_ENABLED: {
1769 return handleSrcSetTestEnabledCommand();
1770 }
1771 case SRC_GET_TEST_ENABLED: {
1772 return handleSrcGetTestEnabledCommand();
1773 }
Hui Wang761a6682020-10-31 05:12:53 +00001774 case SRC_SET_DEVICE_ENABLED: {
1775 return handleSrcSetDeviceEnabledCommand();
1776 }
1777 case SRC_GET_DEVICE_ENABLED: {
1778 return handleSrcGetDeviceEnabledCommand();
1779 }
1780 case SRC_SET_CARRIER_ENABLED: {
1781 return handleSrcSetCarrierEnabledCommand();
1782 }
1783 case SRC_GET_CARRIER_ENABLED: {
1784 return handleSrcGetCarrierEnabledCommand();
1785 }
Hui Wangb647abe2021-02-26 09:33:38 -08001786 case SRC_SET_FEATURE_ENABLED: {
1787 return handleSrcSetFeatureValidationCommand();
1788 }
1789 case SRC_GET_FEATURE_ENABLED: {
1790 return handleSrcGetFeatureValidationCommand();
1791 }
Hui Wang761a6682020-10-31 05:12:53 +00001792 }
1793
1794 return -1;
1795 }
1796
James.cf Linbcdf8b32021-01-14 16:44:13 +08001797 private int handleRcsUceCommand() {
1798 String arg = getNextArg();
1799 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00001800 onHelpUce();
1801 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001802 }
1803
1804 switch (arg) {
1805 case UCE_REMOVE_EAB_CONTACT:
1806 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001807 case UCE_GET_EAB_CONTACT:
1808 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001809 case UCE_GET_DEVICE_ENABLED:
1810 return handleUceGetDeviceEnabledCommand();
1811 case UCE_SET_DEVICE_ENABLED:
1812 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00001813 case UCE_OVERRIDE_PUBLISH_CAPS:
1814 return handleUceOverridePublishCaps();
1815 case UCE_GET_LAST_PIDF_XML:
1816 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001817 }
1818 return -1;
1819 }
1820
1821 private int handleRemovingEabContactCommand() {
1822 int subId = getSubId("uce remove-eab-contact");
1823 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1824 return -1;
1825 }
1826
1827 String phoneNumber = getNextArgRequired();
1828 if (TextUtils.isEmpty(phoneNumber)) {
1829 return -1;
1830 }
1831 int result = 0;
1832 try {
1833 result = mInterface.removeContactFromEab(subId, phoneNumber);
1834 } catch (RemoteException e) {
1835 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1836 getErrPrintWriter().println("Exception: " + e.getMessage());
1837 return -1;
1838 }
1839
1840 if (VDBG) {
1841 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1842 }
calvinpan293ea1b2021-02-04 17:52:13 +08001843 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001844 }
1845
calvinpane4a8a1d2021-01-25 13:51:18 +08001846 private int handleGettingEabContactCommand() {
1847 String phoneNumber = getNextArgRequired();
1848 if (TextUtils.isEmpty(phoneNumber)) {
1849 return -1;
1850 }
1851 String result = "";
1852 try {
1853 result = mInterface.getContactFromEab(phoneNumber);
1854
1855 } catch (RemoteException e) {
1856 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1857 getErrPrintWriter().println("Exception: " + e.getMessage());
1858 return -1;
1859 }
1860
1861 if (VDBG) {
1862 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1863 }
calvinpan293ea1b2021-02-04 17:52:13 +08001864 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001865 return 0;
1866 }
1867
1868 private int handleUceGetDeviceEnabledCommand() {
1869 boolean result = false;
1870 try {
1871 result = mInterface.getDeviceUceEnabled();
1872 } catch (RemoteException e) {
1873 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1874 return -1;
1875 }
1876 if (VDBG) {
1877 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1878 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001879 getOutPrintWriter().println(result);
1880 return 0;
1881 }
1882
James.cf Lin4b784aa2021-01-31 03:25:15 +08001883 private int handleUceSetDeviceEnabledCommand() {
1884 String enabledStr = getNextArg();
1885 if (TextUtils.isEmpty(enabledStr)) {
1886 return -1;
1887 }
1888
1889 try {
1890 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1891 mInterface.setDeviceUceEnabled(isEnabled);
1892 if (VDBG) {
1893 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1894 }
1895 } catch (NumberFormatException | RemoteException e) {
1896 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1897 getErrPrintWriter().println("Exception: " + e.getMessage());
1898 return -1;
1899 }
1900 return 0;
1901 }
1902
Hui Wangbaaee6a2021-02-19 20:45:36 -08001903 private int handleSrcSetTestEnabledCommand() {
1904 String enabledStr = getNextArg();
1905 if (enabledStr == null) {
1906 return -1;
1907 }
1908
1909 try {
1910 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1911 if (VDBG) {
1912 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1913 }
1914 getOutPrintWriter().println("Done");
1915 } catch (NumberFormatException | RemoteException e) {
1916 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1917 getErrPrintWriter().println("Exception: " + e.getMessage());
1918 return -1;
1919 }
1920 return 0;
1921 }
1922
1923 private int handleSrcGetTestEnabledCommand() {
1924 boolean result = false;
1925 try {
1926 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1927 } catch (RemoteException e) {
1928 return -1;
1929 }
1930 if (VDBG) {
1931 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1932 }
1933 getOutPrintWriter().println(result);
1934 return 0;
1935 }
1936
Brad Ebinger14d467f2021-02-12 06:18:28 +00001937 private int handleUceOverridePublishCaps() {
1938 int subId = getSubId("uce override-published-caps");
1939 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1940 return -1;
1941 }
1942 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
1943 String operation = getNextArgRequired();
1944 String caps = getNextArg();
1945 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
1946 && !"list".equals(operation)) {
1947 getErrPrintWriter().println("Invalid operation: " + operation);
1948 return -1;
1949 }
1950
1951 // add/remove requires capabilities to be specified.
1952 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
1953 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
1954 + "specified");
1955 return -1;
1956 }
1957
1958 ArraySet<String> capSet = new ArraySet<>();
1959 if (!TextUtils.isEmpty(caps)) {
1960 String[] capArray = caps.split(":");
1961 for (String cap : capArray) {
1962 // Allow unknown tags to be passed in as well.
1963 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
1964 }
1965 }
1966
1967 RcsContactUceCapability result = null;
1968 try {
1969 switch (operation) {
1970 case "add":
1971 result = mInterface.addUceRegistrationOverrideShell(subId,
1972 new ArrayList<>(capSet));
1973 break;
1974 case "remove":
1975 result = mInterface.removeUceRegistrationOverrideShell(subId,
1976 new ArrayList<>(capSet));
1977 break;
1978 case "clear":
1979 result = mInterface.clearUceRegistrationOverrideShell(subId);
1980 break;
1981 case "list":
1982 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
1983 break;
1984 }
1985 } catch (RemoteException e) {
1986 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
1987 getErrPrintWriter().println("Exception: " + e.getMessage());
1988 return -1;
1989 } catch (ServiceSpecificException sse) {
1990 // Reconstruct ImsException
1991 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
1992 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
1993 getErrPrintWriter().println("Exception: " + imsException);
1994 return -1;
1995 }
1996 if (result == null) {
1997 getErrPrintWriter().println("Service not available");
1998 return -1;
1999 }
2000 getOutPrintWriter().println(result);
2001 return 0;
2002 }
2003
2004 private int handleUceGetPidfXml() {
2005 int subId = getSubId("uce get-last-publish-pidf");
2006 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2007 return -1;
2008 }
2009
2010 String result;
2011 try {
2012 result = mInterface.getLastUcePidfXmlShell(subId);
2013 } catch (RemoteException e) {
2014 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2015 getErrPrintWriter().println("Exception: " + e.getMessage());
2016 return -1;
2017 } catch (ServiceSpecificException sse) {
2018 // Reconstruct ImsException
2019 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2020 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2021 getErrPrintWriter().println("Exception: " + imsException);
2022 return -1;
2023 }
2024 if (result == null) {
2025 getErrPrintWriter().println("Service not available");
2026 return -1;
2027 }
2028 getOutPrintWriter().println(result);
2029 return 0;
2030 }
2031
Hui Wang761a6682020-10-31 05:12:53 +00002032 private int handleSrcSetDeviceEnabledCommand() {
2033 String enabledStr = getNextArg();
2034 if (enabledStr == null) {
2035 return -1;
2036 }
2037
2038 try {
2039 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2040 if (VDBG) {
2041 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2042 }
2043 getOutPrintWriter().println("Done");
2044 } catch (NumberFormatException | RemoteException e) {
2045 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2046 getErrPrintWriter().println("Exception: " + e.getMessage());
2047 return -1;
2048 }
2049 return 0;
2050 }
2051
2052 private int handleSrcGetDeviceEnabledCommand() {
2053 boolean result = false;
2054 try {
2055 result = mInterface.getDeviceSingleRegistrationEnabled();
2056 } catch (RemoteException e) {
2057 return -1;
2058 }
2059 if (VDBG) {
2060 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2061 }
2062 getOutPrintWriter().println(result);
2063 return 0;
2064 }
2065
2066 private int handleSrcSetCarrierEnabledCommand() {
2067 //the release time value could be -1
2068 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2069 : SubscriptionManager.getDefaultSubscriptionId();
2070 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2071 return -1;
2072 }
2073
2074 String enabledStr = getNextArg();
2075 if (enabledStr == null) {
2076 return -1;
2077 }
2078
2079 try {
2080 boolean result =
2081 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2082 if (VDBG) {
2083 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2084 + enabledStr + ", result=" + result);
2085 }
2086 getOutPrintWriter().println(result);
2087 } catch (NumberFormatException | RemoteException e) {
2088 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2089 + enabledStr + ", error" + e.getMessage());
2090 getErrPrintWriter().println("Exception: " + e.getMessage());
2091 return -1;
2092 }
2093 return 0;
2094 }
2095
2096 private int handleSrcGetCarrierEnabledCommand() {
2097 int subId = getSubId("src get-carrier-enabled");
2098 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2099 return -1;
2100 }
2101
2102 boolean result = false;
2103 try {
2104 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2105 } catch (RemoteException e) {
2106 return -1;
2107 }
2108 if (VDBG) {
2109 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2110 }
2111 getOutPrintWriter().println(result);
2112 return 0;
2113 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002114
Hui Wangb647abe2021-02-26 09:33:38 -08002115 private int handleSrcSetFeatureValidationCommand() {
2116 //the release time value could be -1
2117 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2118 : SubscriptionManager.getDefaultSubscriptionId();
2119 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2120 return -1;
2121 }
2122
2123 String enabledStr = getNextArg();
2124 if (enabledStr == null) {
2125 return -1;
2126 }
2127
2128 try {
2129 boolean result =
2130 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2131 if (VDBG) {
2132 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2133 + enabledStr + ", result=" + result);
2134 }
2135 getOutPrintWriter().println(result);
2136 } catch (NumberFormatException | RemoteException e) {
2137 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2138 + enabledStr + ", error" + e.getMessage());
2139 getErrPrintWriter().println("Exception: " + e.getMessage());
2140 return -1;
2141 }
2142 return 0;
2143 }
2144
2145 private int handleSrcGetFeatureValidationCommand() {
2146 int subId = getSubId("src get-feature-validation");
2147 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2148 return -1;
2149 }
2150
2151 Boolean result = false;
2152 try {
2153 result = mInterface.getImsFeatureValidationOverride(subId);
2154 } catch (RemoteException e) {
2155 return -1;
2156 }
2157 if (VDBG) {
2158 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2159 }
2160 getOutPrintWriter().println(result);
2161 return 0;
2162 }
2163
2164
Hall Liuaa4211e2021-01-20 15:43:39 -08002165 private void onHelpCallComposer() {
2166 PrintWriter pw = getOutPrintWriter();
2167 pw.println("Call composer commands");
2168 pw.println(" callcomposer test-mode enable|disable|query");
2169 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2170 pw.println(" upload/download from carrier servers is disabled, and operations are");
2171 pw.println(" performed using emulated local files instead.");
2172 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2173 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2174 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002175 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2176 pw.println(" Enables or disables the user setting for call composer, as set by");
2177 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002178 }
2179
2180 private int handleCallComposerCommand() {
2181 String arg = getNextArg();
2182 if (arg == null) {
2183 onHelpCallComposer();
2184 return 0;
2185 }
2186
2187 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2188 "MODIFY_PHONE_STATE required for call composer shell cmds");
2189 switch (arg) {
2190 case CALL_COMPOSER_TEST_MODE: {
2191 String enabledStr = getNextArg();
2192 if (ENABLE.equals(enabledStr)) {
2193 CallComposerPictureManager.sTestMode = true;
2194 } else if (DISABLE.equals(enabledStr)) {
2195 CallComposerPictureManager.sTestMode = false;
2196 } else if (QUERY.equals(enabledStr)) {
2197 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2198 } else {
2199 onHelpCallComposer();
2200 return 1;
2201 }
2202 break;
2203 }
2204 case CALL_COMPOSER_SIMULATE_CALL: {
2205 int subscriptionId = Integer.valueOf(getNextArg());
2206 String uuidString = getNextArg();
2207 UUID uuid = UUID.fromString(uuidString);
2208 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2209 Binder.withCleanCallingIdentity(() -> {
2210 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2211 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2212 });
2213 try {
2214 Uri uri = storageUriFuture.get();
2215 getOutPrintWriter().println(String.valueOf(uri));
2216 } catch (Exception e) {
2217 throw new RuntimeException(e);
2218 }
2219 break;
2220 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002221 case CALL_COMPOSER_USER_SETTING: {
2222 try {
2223 int subscriptionId = Integer.valueOf(getNextArg());
2224 String enabledStr = getNextArg();
2225 if (ENABLE.equals(enabledStr)) {
2226 mInterface.setCallComposerStatus(subscriptionId,
2227 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2228 } else if (DISABLE.equals(enabledStr)) {
2229 mInterface.setCallComposerStatus(subscriptionId,
2230 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2231 } else if (QUERY.equals(enabledStr)) {
2232 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2233 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2234 } else {
2235 onHelpCallComposer();
2236 return 1;
2237 }
2238 } catch (RemoteException e) {
2239 e.printStackTrace(getOutPrintWriter());
2240 return 1;
2241 }
2242 break;
2243 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002244 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002245 return 0;
2246 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002247
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002248 private int handleHasCarrierPrivilegesCommand() {
2249 String packageName = getNextArgRequired();
2250
2251 boolean hasCarrierPrivileges;
2252 try {
2253 hasCarrierPrivileges =
2254 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2255 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2256 } catch (RemoteException e) {
2257 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2258 getErrPrintWriter().println("Exception: " + e.getMessage());
2259 return -1;
2260 }
2261
2262 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002263 return 0;
2264 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002265}