blob: 07136d75d349484c960275ca538bf9e4eda23244 [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 Wang761a6682020-10-31 05:12:53 +0000126
Tyler Gunn92479152021-01-20 16:30:10 -0800127 private static final String D2D_SUBCOMMAND = "d2d";
128 private static final String D2D_SEND = "send";
Tyler Gunnbabbda02021-02-10 11:05:02 -0800129 private static final String D2D_TRANSPORT = "transport";
Tyler Gunn92479152021-01-20 16:30:10 -0800130
James.cf Linbcdf8b32021-01-14 16:44:13 +0800131 private static final String RCS_UCE_COMMAND = "uce";
calvinpane4a8a1d2021-01-25 13:51:18 +0800132 private static final String UCE_GET_EAB_CONTACT = "get-eab-contact";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800133 private static final String UCE_REMOVE_EAB_CONTACT = "remove-eab-contact";
James.cf Lin4b784aa2021-01-31 03:25:15 +0800134 private static final String UCE_GET_DEVICE_ENABLED = "get-device-enabled";
135 private static final String UCE_SET_DEVICE_ENABLED = "set-device-enabled";
Brad Ebinger14d467f2021-02-12 06:18:28 +0000136 private static final String UCE_OVERRIDE_PUBLISH_CAPS = "override-published-caps";
137 private static final String UCE_GET_LAST_PIDF_XML = "get-last-publish-pidf";
James.cf Linbcdf8b32021-01-14 16:44:13 +0800138
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800139 // Check if a package has carrier privileges on any SIM, regardless of subId/phoneId.
140 private static final String HAS_CARRIER_PRIVILEGES_COMMAND = "has-carrier-privileges";
141
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700142 // Take advantage of existing methods that already contain permissions checks when possible.
143 private final ITelephony mInterface;
144
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100145 private SubscriptionManager mSubscriptionManager;
146 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700147 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100148
149 private enum CcType {
150 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
151 STRING_ARRAY, UNKNOWN
152 }
153
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100154 private class CcOptionParseResult {
155 public int mSubId;
156 public boolean mPersistent;
157 }
158
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100159 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
160 // keys by looking at the end of the string which usually tells the type.
161 // For instance: "xxxx_string", "xxxx_string_array", etc.
162 // The carrier config keys in this map does not follow this convention. It is therefore not
163 // possible to infer the type for these keys by looking at the string.
164 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
165 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
166 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
167 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
168 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
169 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
170 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
171 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
172 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
173 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
174 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
175 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
176 CcType.STRING);
177 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
178 CcType.STRING_ARRAY);
179 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
180 CcType.STRING_ARRAY);
181 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
182 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
183 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
184 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
185 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
186 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
187 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
188 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
189 }
190 };
191
Brad Ebinger14d467f2021-02-12 06:18:28 +0000192 /**
193 * Map from a shorthand string to the feature tags required in registration required in order
194 * for the RCS feature to be considered "capable".
195 */
196 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
197 static {
198 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
199 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
200 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
201 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
202 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
203 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
204 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
205 FeatureTags.FEATURE_TAG_VIDEO)));
206 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
207 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
208 map.put("call_comp",
209 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
210 map.put("call_comp_mmtel",
211 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
212 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
213 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
214 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
215 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
216 // version
217 map.put("chatbot", new ArraySet<>(Arrays.asList(
218 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
219 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
220 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
221 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
222 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
223 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
224 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
225 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
226 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
227 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
228 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
229 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
230 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
231 }
232
233
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100234 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700235 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100236 mCarrierConfigManager =
237 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
238 mSubscriptionManager = (SubscriptionManager)
239 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700240 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700241 }
242
243 @Override
244 public int onCommand(String cmd) {
245 if (cmd == null) {
246 return handleDefaultCommands(null);
247 }
248
249 switch (cmd) {
250 case IMS_SUBCOMMAND: {
251 return handleImsCommand();
252 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800253 case RCS_UCE_COMMAND:
254 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800255 case NUMBER_VERIFICATION_SUBCOMMAND:
256 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800257 case EMERGENCY_CALLBACK_MODE:
258 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800259 case EMERGENCY_NUMBER_TEST_MODE:
260 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100261 case CARRIER_CONFIG_SUBCOMMAND: {
262 return handleCcCommand();
263 }
Shuo Qianf5125122019-12-16 17:03:07 -0800264 case DATA_TEST_MODE:
265 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700266 case END_BLOCK_SUPPRESSION:
267 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700268 case GBA_SUBCOMMAND:
269 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800270 case D2D_SUBCOMMAND:
271 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000272 case SINGLE_REGISTATION_CONFIG:
273 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000274 case RESTART_MODEM:
275 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800276 case CALL_COMPOSER_SUBCOMMAND:
277 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000278 case UNATTENDED_REBOOT:
279 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800280 case HAS_CARRIER_PRIVILEGES_COMMAND:
281 return handleHasCarrierPrivilegesCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700282 default: {
283 return handleDefaultCommands(cmd);
284 }
285 }
286 }
287
288 @Override
289 public void onHelp() {
290 PrintWriter pw = getOutPrintWriter();
291 pw.println("Telephony Commands:");
292 pw.println(" help");
293 pw.println(" Print this help text.");
294 pw.println(" ims");
295 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800296 pw.println(" uce");
297 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800298 pw.println(" emergency-number-test-mode");
299 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700300 pw.println(" end-block-suppression");
301 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800302 pw.println(" data");
303 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100304 pw.println(" cc");
305 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700306 pw.println(" gba");
307 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000308 pw.println(" src");
309 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000310 pw.println(" restart-modem");
311 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000312 pw.println(" unattended-reboot");
313 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800314 pw.println(" has-carrier-privileges [package]");
315 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700316 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800317 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800318 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700319 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800320 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100321 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700322 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000323 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800324 onHelpD2D();
325 }
326
327 private void onHelpD2D() {
328 PrintWriter pw = getOutPrintWriter();
329 pw.println("D2D Comms Commands:");
330 pw.println(" d2d send TYPE VALUE");
331 pw.println(" Sends a D2D message of specified type and value.");
332 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
333 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
334 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
335 MESSAGE_CALL_AUDIO_CODEC));
336 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
337 + Communicator.messageToString(
338 MESSAGE_DEVICE_BATTERY_STATE));
339 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
340 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800341 pw.println(" d2d transport TYPE");
342 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
343 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700344 }
345
346 private void onHelpIms() {
347 PrintWriter pw = getOutPrintWriter();
348 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800349 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700350 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
351 pw.println(" ImsService. Options are:");
352 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
353 pw.println(" is specified, it will choose the default voice SIM slot.");
354 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
355 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800356 pw.println(" -f: Set the feature that this override if for, if no option is");
357 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700358 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
359 pw.println(" Gets the package name of the currently defined ImsService.");
360 pw.println(" Options are:");
361 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
362 pw.println(" is specified, it will choose the default voice SIM slot.");
363 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000364 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800365 pw.println(" -f: The feature type that the query will be requested for. If none is");
366 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800367 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
368 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
369 pw.println(" configuration overrides. Options are:");
370 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
371 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700372 pw.println(" ims enable [-s SLOT_ID]");
373 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
374 pw.println(" if none is specified.");
375 pw.println(" ims disable [-s SLOT_ID]");
376 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
377 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700378 pw.println(" ims conference-event-package [enable/disable]");
379 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700380 }
381
James.cf Linbcdf8b32021-01-14 16:44:13 +0800382 private void onHelpUce() {
383 PrintWriter pw = getOutPrintWriter();
384 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800385 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
386 pw.println(" Get the EAB contacts from the EAB database.");
387 pw.println(" Options are:");
388 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
389 pw.println(" Expected output format :");
390 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800391 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
392 pw.println(" Remove the EAB contacts from the EAB database.");
393 pw.println(" Options are:");
394 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
395 pw.println(" is specified, it will choose the default voice SIM slot.");
396 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800397 pw.println(" uce get-device-enabled");
398 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
399 pw.println(" uce set-device-enabled true|false");
400 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
401 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000402 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
403 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
404 pw.println(" Options are:");
405 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
406 pw.println(" is specified, it will choose the default voice SIM slot.");
407 pw.println(" add [CAPABILITY]: add a new capability");
408 pw.println(" remove [CAPABILITY]: remove a capability");
409 pw.println(" clear: clear all capability overrides");
410 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
411 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
412 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
413 pw.println(" chatbot_sa, chatbot_role] as well as full length");
414 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
415 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
416 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
417 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800418 }
419
Hall Liud892bec2018-11-30 14:51:45 -0800420 private void onHelpNumberVerification() {
421 PrintWriter pw = getOutPrintWriter();
422 pw.println("Number verification commands");
423 pw.println(" numverify override-package PACKAGE_NAME;");
424 pw.println(" Set the authorized package for number verification.");
425 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800426 pw.println(" numverify fake-call NUMBER;");
427 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
428 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800429 }
430
Shuo Qianf5125122019-12-16 17:03:07 -0800431 private void onHelpDataTestMode() {
432 PrintWriter pw = getOutPrintWriter();
433 pw.println("Mobile Data Test Mode Commands:");
434 pw.println(" data enable: enable mobile data connectivity");
435 pw.println(" data disable: disable mobile data connectivity");
436 }
437
sqian9d4df8b2019-01-15 18:32:07 -0800438 private void onHelpEmergencyNumber() {
439 PrintWriter pw = getOutPrintWriter();
440 pw.println("Emergency Number Test Mode Commands:");
441 pw.println(" emergency-number-test-mode ");
442 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
443 + " the test mode");
444 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700445 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800446 pw.println(" -c: clear the emergency number list in the test mode.");
447 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700448 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800449 pw.println(" -p: get the full emergency number list in the test mode.");
450 }
451
Shuo Qian489d9282020-07-09 11:30:03 -0700452 private void onHelpEndBlockSupperssion() {
453 PrintWriter pw = getOutPrintWriter();
454 pw.println("End Block Suppression command:");
455 pw.println(" end-block-suppression: disable suppressing blocking by contact");
456 pw.println(" with emergency services.");
457 }
458
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100459 private void onHelpCc() {
460 PrintWriter pw = getOutPrintWriter();
461 pw.println("Carrier Config Commands:");
462 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
463 pw.println(" Print carrier config values.");
464 pw.println(" Options are:");
465 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
466 pw.println(" is specified, it will choose the default voice SIM slot.");
467 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
468 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100469 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100470 pw.println(" Set carrier config KEY to NEW_VALUE.");
471 pw.println(" Options are:");
472 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
473 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100474 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100475 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
476 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
477 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
478 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
479 pw.println(" cc clear-values [-s SLOT_ID]");
480 pw.println(" Clear all carrier override values that has previously been set");
481 pw.println(" with set-value");
482 pw.println(" Options are:");
483 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
484 pw.println(" is specified, it will choose the default voice SIM slot.");
485 }
486
Hui Wang641e81c2020-10-12 12:14:23 -0700487 private void onHelpGba() {
488 PrintWriter pw = getOutPrintWriter();
489 pw.println("Gba Commands:");
490 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
491 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
492 pw.println(" Options are:");
493 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
494 pw.println(" is specified, it will choose the default voice SIM slot.");
495 pw.println(" gba get-service [-s SLOT_ID]");
496 pw.println(" Gets the package name of the currently defined GbaService.");
497 pw.println(" Options are:");
498 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
499 pw.println(" is specified, it will choose the default voice SIM slot.");
500 pw.println(" gba set-release [-s SLOT_ID] n");
501 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
502 pw.println(" Do not release/unbind if n is -1.");
503 pw.println(" Options are:");
504 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
505 pw.println(" is specified, it will choose the default voice SIM slot.");
506 pw.println(" gba get-release [-s SLOT_ID]");
507 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
508 pw.println(" Options are:");
509 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
510 pw.println(" is specified, it will choose the default voice SIM slot.");
511 }
512
Hui Wang761a6682020-10-31 05:12:53 +0000513 private void onHelpSrc() {
514 PrintWriter pw = getOutPrintWriter();
515 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800516 pw.println(" src set-test-enabled true|false");
517 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
518 pw.println(" The value could be true, false, or null(undefined).");
519 pw.println(" src get-test-enabled");
520 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000521 pw.println(" src set-device-enabled true|false|null");
522 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
523 pw.println(" The value could be true, false, or null(undefined).");
524 pw.println(" src get-device-enabled");
525 pw.println(" Gets the device config for RCS VoLTE single registration.");
526 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
527 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
528 pw.println(" The value could be true, false, or null(undefined).");
529 pw.println(" Options are:");
530 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
531 pw.println(" is specified, it will choose the default voice SIM slot.");
532 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
533 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
534 pw.println(" Options are:");
535 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
536 pw.println(" is specified, it will choose the default voice SIM slot.");
537 }
538
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700539 private int handleImsCommand() {
540 String arg = getNextArg();
541 if (arg == null) {
542 onHelpIms();
543 return 0;
544 }
545
546 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800547 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700548 return handleImsSetServiceCommand();
549 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800550 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700551 return handleImsGetServiceCommand();
552 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800553 case IMS_CLEAR_SERVICE_OVERRIDE: {
554 return handleImsClearCarrierServiceCommand();
555 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800556 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700557 return handleEnableIms();
558 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800559 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700560 return handleDisableIms();
561 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700562 case IMS_CEP: {
563 return handleCepChange();
564 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700565 }
566
567 return -1;
568 }
569
Shuo Qianf5125122019-12-16 17:03:07 -0800570 private int handleDataTestModeCommand() {
571 PrintWriter errPw = getErrPrintWriter();
572 String arg = getNextArgRequired();
573 if (arg == null) {
574 onHelpDataTestMode();
575 return 0;
576 }
577 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800578 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800579 try {
580 mInterface.enableDataConnectivity();
581 } catch (RemoteException ex) {
582 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
583 errPw.println("Exception: " + ex.getMessage());
584 return -1;
585 }
586 break;
587 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800588 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800589 try {
590 mInterface.disableDataConnectivity();
591 } catch (RemoteException ex) {
592 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
593 errPw.println("Exception: " + ex.getMessage());
594 return -1;
595 }
596 break;
597 }
598 default:
599 onHelpDataTestMode();
600 break;
601 }
602 return 0;
603 }
604
Shuo Qianccbaf742021-02-22 18:32:21 -0800605 private int handleEmergencyCallbackModeCommand() {
606 PrintWriter errPw = getErrPrintWriter();
607 try {
608 mInterface.startEmergencyCallbackMode();
609 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
610 } catch (RemoteException ex) {
611 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
612 errPw.println("Exception: " + ex.getMessage());
613 return -1;
614 }
615 return 0;
616 }
617
sqian9d4df8b2019-01-15 18:32:07 -0800618 private int handleEmergencyNumberTestModeCommand() {
619 PrintWriter errPw = getErrPrintWriter();
620 String opt = getNextOption();
621 if (opt == null) {
622 onHelpEmergencyNumber();
623 return 0;
624 }
625
626 switch (opt) {
627 case "-a": {
628 String emergencyNumberCmd = getNextArgRequired();
629 if (emergencyNumberCmd == null
630 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700631 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800632 + " to be specified after -a in the command ");
633 return -1;
634 }
635 try {
636 mInterface.updateEmergencyNumberListTestMode(
637 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
638 new EmergencyNumber(emergencyNumberCmd, "", "",
639 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
640 new ArrayList<String>(),
641 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
642 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
643 } catch (RemoteException ex) {
644 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
645 + ", error " + ex.getMessage());
646 errPw.println("Exception: " + ex.getMessage());
647 return -1;
648 }
649 break;
650 }
651 case "-c": {
652 try {
653 mInterface.updateEmergencyNumberListTestMode(
654 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
655 } catch (RemoteException ex) {
656 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
657 errPw.println("Exception: " + ex.getMessage());
658 return -1;
659 }
660 break;
661 }
662 case "-r": {
663 String emergencyNumberCmd = getNextArgRequired();
664 if (emergencyNumberCmd == null
665 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700666 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800667 + " to be specified after -r in the command ");
668 return -1;
669 }
670 try {
671 mInterface.updateEmergencyNumberListTestMode(
672 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
673 new EmergencyNumber(emergencyNumberCmd, "", "",
674 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
675 new ArrayList<String>(),
676 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
677 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
678 } catch (RemoteException ex) {
679 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
680 + ", error " + ex.getMessage());
681 errPw.println("Exception: " + ex.getMessage());
682 return -1;
683 }
684 break;
685 }
686 case "-p": {
687 try {
688 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
689 } catch (RemoteException ex) {
690 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
691 errPw.println("Exception: " + ex.getMessage());
692 return -1;
693 }
694 break;
695 }
696 default:
697 onHelpEmergencyNumber();
698 break;
699 }
700 return 0;
701 }
702
Hall Liud892bec2018-11-30 14:51:45 -0800703 private int handleNumberVerificationCommand() {
704 String arg = getNextArg();
705 if (arg == null) {
706 onHelpNumberVerification();
707 return 0;
708 }
709
Hall Liuca5af3a2018-12-04 16:58:23 -0800710 if (!checkShellUid()) {
711 return -1;
712 }
713
Hall Liud892bec2018-11-30 14:51:45 -0800714 switch (arg) {
715 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800716 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
717 return 0;
718 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800719 case NUMBER_VERIFICATION_FAKE_CALL: {
720 boolean val = NumberVerificationManager.getInstance()
721 .checkIncomingCall(getNextArg());
722 getOutPrintWriter().println(val ? "1" : "0");
723 return 0;
724 }
Hall Liud892bec2018-11-30 14:51:45 -0800725 }
726
727 return -1;
728 }
729
Tyler Gunn92479152021-01-20 16:30:10 -0800730 private int handleD2dCommand() {
731 String arg = getNextArg();
732 if (arg == null) {
733 onHelpD2D();
734 return 0;
735 }
736
737 switch (arg) {
738 case D2D_SEND: {
739 return handleD2dSendCommand();
740 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800741 case D2D_TRANSPORT: {
742 return handleD2dTransportCommand();
743 }
Tyler Gunn92479152021-01-20 16:30:10 -0800744 }
745
746 return -1;
747 }
748
749 private int handleD2dSendCommand() {
750 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800751 int messageType = -1;
752 int messageValue = -1;
753
Tyler Gunn92479152021-01-20 16:30:10 -0800754 String arg = getNextArg();
755 if (arg == null) {
756 onHelpD2D();
757 return 0;
758 }
759 try {
760 messageType = Integer.parseInt(arg);
761 } catch (NumberFormatException e) {
762 errPw.println("message type must be a valid integer");
763 return -1;
764 }
765
766 arg = getNextArg();
767 if (arg == null) {
768 onHelpD2D();
769 return 0;
770 }
771 try {
772 messageValue = Integer.parseInt(arg);
773 } catch (NumberFormatException e) {
774 errPw.println("message value must be a valid integer");
775 return -1;
776 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800777
Tyler Gunn92479152021-01-20 16:30:10 -0800778 try {
779 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
780 } catch (RemoteException e) {
781 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
782 errPw.println("Exception: " + e.getMessage());
783 return -1;
784 }
785
786 return 0;
787 }
788
Tyler Gunnbabbda02021-02-10 11:05:02 -0800789 private int handleD2dTransportCommand() {
790 PrintWriter errPw = getErrPrintWriter();
791
792 String arg = getNextArg();
793 if (arg == null) {
794 onHelpD2D();
795 return 0;
796 }
797
798 try {
799 mInterface.setActiveDeviceToDeviceTransport(arg);
800 } catch (RemoteException e) {
801 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
802 errPw.println("Exception: " + e.getMessage());
803 return -1;
804 }
805 return 0;
806 }
807
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700808 // ims set-ims-service
809 private int handleImsSetServiceCommand() {
810 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700811 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700812 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800813 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700814
815 String opt;
816 while ((opt = getNextOption()) != null) {
817 switch (opt) {
818 case "-s": {
819 try {
820 slotId = Integer.parseInt(getNextArgRequired());
821 } catch (NumberFormatException e) {
822 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
823 return -1;
824 }
825 break;
826 }
827 case "-c": {
828 isCarrierService = true;
829 break;
830 }
831 case "-d": {
832 isCarrierService = false;
833 break;
834 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800835 case "-f": {
836 String featureString = getNextArgRequired();
837 String[] features = featureString.split(",");
838 for (int i = 0; i < features.length; i++) {
839 try {
840 Integer result = Integer.parseInt(features[i]);
841 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
842 || result >= ImsFeature.FEATURE_MAX) {
843 errPw.println("ims set-ims-service -f " + result
844 + " is an invalid feature.");
845 return -1;
846 }
847 featuresList.add(result);
848 } catch (NumberFormatException e) {
849 errPw.println("ims set-ims-service -f tried to parse " + features[i]
850 + " as an integer.");
851 return -1;
852 }
853 }
854 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700855 }
856 }
857 // Mandatory param, either -c or -d
858 if (isCarrierService == null) {
859 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
860 return -1;
861 }
862
863 String packageName = getNextArg();
864
865 try {
866 if (packageName == null) {
867 packageName = "";
868 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800869 int[] featureArray = new int[featuresList.size()];
870 for (int i = 0; i < featuresList.size(); i++) {
871 featureArray[i] = featuresList.get(i);
872 }
873 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
874 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700875 if (VDBG) {
876 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800877 + (isCarrierService ? "-c " : "-d ")
878 + "-f " + featuresList + " "
879 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700880 }
881 getOutPrintWriter().println(result);
882 } catch (RemoteException e) {
883 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800884 + (isCarrierService ? "-c " : "-d ")
885 + "-f " + featuresList + " "
886 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700887 errPw.println("Exception: " + e.getMessage());
888 return -1;
889 }
890 return 0;
891 }
892
Brad Ebinger999d3302020-11-25 14:31:39 -0800893 // ims clear-ims-service-override
894 private int handleImsClearCarrierServiceCommand() {
895 PrintWriter errPw = getErrPrintWriter();
896 int slotId = getDefaultSlot();
897
898 String opt;
899 while ((opt = getNextOption()) != null) {
900 switch (opt) {
901 case "-s": {
902 try {
903 slotId = Integer.parseInt(getNextArgRequired());
904 } catch (NumberFormatException e) {
905 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
906 return -1;
907 }
908 break;
909 }
910 }
911 }
912
913 try {
914 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
915 if (VDBG) {
916 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
917 + ", result=" + result);
918 }
919 getOutPrintWriter().println(result);
920 } catch (RemoteException e) {
921 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
922 + ", error" + e.getMessage());
923 errPw.println("Exception: " + e.getMessage());
924 return -1;
925 }
926 return 0;
927 }
928
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700929 // ims get-ims-service
930 private int handleImsGetServiceCommand() {
931 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700932 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700933 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800934 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700935
936 String opt;
937 while ((opt = getNextOption()) != null) {
938 switch (opt) {
939 case "-s": {
940 try {
941 slotId = Integer.parseInt(getNextArgRequired());
942 } catch (NumberFormatException e) {
943 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
944 return -1;
945 }
946 break;
947 }
948 case "-c": {
949 isCarrierService = true;
950 break;
951 }
952 case "-d": {
953 isCarrierService = false;
954 break;
955 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800956 case "-f": {
957 try {
958 featureType = Integer.parseInt(getNextArg());
959 } catch (NumberFormatException e) {
960 errPw.println("ims get-ims-service -f requires valid integer as feature.");
961 return -1;
962 }
963 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
964 || featureType >= ImsFeature.FEATURE_MAX) {
965 errPw.println("ims get-ims-service -f invalid feature.");
966 return -1;
967 }
968 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700969 }
970 }
971 // Mandatory param, either -c or -d
972 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -0800973 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700974 return -1;
975 }
976
977 String result;
978 try {
Brad Ebinger24c29992019-12-05 13:03:21 -0800979 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700980 } catch (RemoteException e) {
981 return -1;
982 }
983 if (VDBG) {
984 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800985 + (isCarrierService ? "-c " : "-d ")
986 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
987 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700988 }
989 getOutPrintWriter().println(result);
990 return 0;
991 }
992
993 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700994 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700995 String opt;
996 while ((opt = getNextOption()) != null) {
997 switch (opt) {
998 case "-s": {
999 try {
1000 slotId = Integer.parseInt(getNextArgRequired());
1001 } catch (NumberFormatException e) {
1002 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1003 return -1;
1004 }
1005 break;
1006 }
1007 }
1008 }
1009 try {
1010 mInterface.enableIms(slotId);
1011 } catch (RemoteException e) {
1012 return -1;
1013 }
1014 if (VDBG) {
1015 Log.v(LOG_TAG, "ims enable -s " + slotId);
1016 }
1017 return 0;
1018 }
1019
1020 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001021 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001022 String opt;
1023 while ((opt = getNextOption()) != null) {
1024 switch (opt) {
1025 case "-s": {
1026 try {
1027 slotId = Integer.parseInt(getNextArgRequired());
1028 } catch (NumberFormatException e) {
1029 getErrPrintWriter().println(
1030 "ims disable requires an integer as a SLOT_ID.");
1031 return -1;
1032 }
1033 break;
1034 }
1035 }
1036 }
1037 try {
1038 mInterface.disableIms(slotId);
1039 } catch (RemoteException e) {
1040 return -1;
1041 }
1042 if (VDBG) {
1043 Log.v(LOG_TAG, "ims disable -s " + slotId);
1044 }
1045 return 0;
1046 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001047
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001048 private int handleCepChange() {
1049 Log.i(LOG_TAG, "handleCepChange");
1050 String opt = getNextArg();
1051 if (opt == null) {
1052 return -1;
1053 }
1054 boolean isCepEnabled = opt.equals("enable");
1055
1056 try {
1057 mInterface.setCepEnabled(isCepEnabled);
1058 } catch (RemoteException e) {
1059 return -1;
1060 }
1061 return 0;
1062 }
1063
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001064 private int getDefaultSlot() {
1065 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1066 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1067 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1068 // If there is no default, default to slot 0.
1069 slotId = DEFAULT_PHONE_ID;
1070 }
1071 return slotId;
1072 }
sqian2fff4a32018-11-05 14:18:37 -08001073
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001074 // Parse options related to Carrier Config Commands.
1075 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001076 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001077 CcOptionParseResult result = new CcOptionParseResult();
1078 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1079 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001080
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001081 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001082 while ((opt = getNextOption()) != null) {
1083 switch (opt) {
1084 case "-s": {
1085 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001086 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1087 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1088 errPw.println(tag + "No valid subscription found.");
1089 return null;
1090 }
1091
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001092 } catch (IllegalArgumentException e) {
1093 // Missing slot id
1094 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001095 return null;
1096 }
1097 break;
1098 }
1099 case "-p": {
1100 if (allowOptionPersistent) {
1101 result.mPersistent = true;
1102 } else {
1103 errPw.println(tag + "Unexpected option " + opt);
1104 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001105 }
1106 break;
1107 }
1108 default: {
1109 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001110 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001111 }
1112 }
1113 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001114 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001115 }
1116
1117 private int slotStringToSubId(String tag, String slotString) {
1118 int slotId = -1;
1119 try {
1120 slotId = Integer.parseInt(slotString);
1121 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001122 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1123 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1124 }
1125
1126 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001127 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1128 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1129 }
1130
Qiong Liuf25799b2020-09-10 10:13:46 +08001131 Phone phone = PhoneFactory.getPhone(slotId);
1132 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001133 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1134 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1135 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001136 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001137 }
1138
Hall Liud892bec2018-11-30 14:51:45 -08001139 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001140 // adb can run as root or as shell, depending on whether the device is rooted.
1141 return Binder.getCallingUid() == Process.SHELL_UID
1142 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001143 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001144
1145 private int handleCcCommand() {
1146 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1147 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001148 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001149 getErrPrintWriter().println("cc: Permission denied.");
1150 return -1;
1151 }
1152
1153 String arg = getNextArg();
1154 if (arg == null) {
1155 onHelpCc();
1156 return 0;
1157 }
1158
1159 switch (arg) {
1160 case CC_GET_VALUE: {
1161 return handleCcGetValue();
1162 }
1163 case CC_SET_VALUE: {
1164 return handleCcSetValue();
1165 }
1166 case CC_CLEAR_VALUES: {
1167 return handleCcClearValues();
1168 }
1169 default: {
1170 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1171 }
1172 }
1173 return -1;
1174 }
1175
1176 // cc get-value
1177 private int handleCcGetValue() {
1178 PrintWriter errPw = getErrPrintWriter();
1179 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1180 String key = null;
1181
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001182 // Parse all options
1183 CcOptionParseResult options = parseCcOptions(tag, false);
1184 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001185 return -1;
1186 }
1187
1188 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001189 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001190 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001191 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001192 return -1;
1193 }
1194
1195 // Get the key.
1196 key = getNextArg();
1197 if (key != null) {
1198 // A key was provided. Verify if it is a valid key
1199 if (!bundle.containsKey(key)) {
1200 errPw.println(tag + key + " is not a valid key.");
1201 return -1;
1202 }
1203
1204 // Print the carrier config value for key.
1205 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1206 } else {
1207 // No key provided. Show all values.
1208 // Iterate over a sorted list of all carrier config keys and print them.
1209 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1210 for (String k : sortedSet) {
1211 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1212 }
1213 }
1214 return 0;
1215 }
1216
1217 // cc set-value
1218 private int handleCcSetValue() {
1219 PrintWriter errPw = getErrPrintWriter();
1220 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1221
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001222 // Parse all options
1223 CcOptionParseResult options = parseCcOptions(tag, true);
1224 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001225 return -1;
1226 }
1227
1228 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001229 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001230 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001231 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001232 return -1;
1233 }
1234
1235 // Get the key.
1236 String key = getNextArg();
1237 if (key == null || key.equals("")) {
1238 errPw.println(tag + "KEY is missing");
1239 return -1;
1240 }
1241
1242 // Verify if the key is valid
1243 if (!originalValues.containsKey(key)) {
1244 errPw.println(tag + key + " is not a valid key.");
1245 return -1;
1246 }
1247
1248 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1249 ArrayList<String> valueList = new ArrayList<String>();
1250 while (peekNextArg() != null) {
1251 valueList.add(getNextArg());
1252 }
1253
1254 // Find the type of the carrier config value
1255 CcType type = getType(tag, key, originalValues);
1256 if (type == CcType.UNKNOWN) {
1257 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1258 return -1;
1259 }
1260
1261 // Create an override bundle containing the key and value that should be overriden.
1262 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1263 if (overrideBundle == null) {
1264 return -1;
1265 }
1266
1267 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001268 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001269
1270 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001271 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001272 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001273 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001274 return -1;
1275 }
1276
1277 // Print the original and new value.
1278 String originalValueString = ccValueToString(key, type, originalValues);
1279 String newValueString = ccValueToString(key, type, newValues);
1280 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1281 getOutPrintWriter().println("New value: \n" + newValueString);
1282
1283 return 0;
1284 }
1285
1286 // cc clear-values
1287 private int handleCcClearValues() {
1288 PrintWriter errPw = getErrPrintWriter();
1289 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1290
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001291 // Parse all options
1292 CcOptionParseResult options = parseCcOptions(tag, false);
1293 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001294 return -1;
1295 }
1296
1297 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001298 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001299 getOutPrintWriter()
1300 .println("All previously set carrier config override values has been cleared");
1301 return 0;
1302 }
1303
1304 private CcType getType(String tag, String key, PersistableBundle bundle) {
1305 // Find the type by checking the type of the current value stored in the bundle.
1306 Object value = bundle.get(key);
1307
1308 if (CC_TYPE_MAP.containsKey(key)) {
1309 return CC_TYPE_MAP.get(key);
1310 } else if (value != null) {
1311 if (value instanceof Boolean) {
1312 return CcType.BOOLEAN;
1313 } else if (value instanceof Double) {
1314 return CcType.DOUBLE;
1315 } else if (value instanceof double[]) {
1316 return CcType.DOUBLE_ARRAY;
1317 } else if (value instanceof Integer) {
1318 return CcType.INT;
1319 } else if (value instanceof int[]) {
1320 return CcType.INT_ARRAY;
1321 } else if (value instanceof Long) {
1322 return CcType.LONG;
1323 } else if (value instanceof long[]) {
1324 return CcType.LONG_ARRAY;
1325 } else if (value instanceof String) {
1326 return CcType.STRING;
1327 } else if (value instanceof String[]) {
1328 return CcType.STRING_ARRAY;
1329 }
1330 } else {
1331 // Current value was null and can therefore not be used in order to find the type.
1332 // Check the name of the key to infer the type. This check is not needed for primitive
1333 // data types (boolean, double, int and long), since they can not be null.
1334 if (key.endsWith("double_array")) {
1335 return CcType.DOUBLE_ARRAY;
1336 }
1337 if (key.endsWith("int_array")) {
1338 return CcType.INT_ARRAY;
1339 }
1340 if (key.endsWith("long_array")) {
1341 return CcType.LONG_ARRAY;
1342 }
1343 if (key.endsWith("string")) {
1344 return CcType.STRING;
1345 }
1346 if (key.endsWith("string_array") || key.endsWith("strings")) {
1347 return CcType.STRING_ARRAY;
1348 }
1349 }
1350
1351 // Not possible to infer the type by looking at the current value or the key.
1352 PrintWriter errPw = getErrPrintWriter();
1353 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1354 return CcType.UNKNOWN;
1355 }
1356
1357 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1358 String result;
1359 StringBuilder valueString = new StringBuilder();
1360 String typeString = type.toString();
1361 Object value = bundle.get(key);
1362
1363 if (value == null) {
1364 valueString.append("null");
1365 } else {
1366 switch (type) {
1367 case DOUBLE_ARRAY: {
1368 // Format the string representation of the int array as value1 value2......
1369 double[] valueArray = (double[]) value;
1370 for (int i = 0; i < valueArray.length; i++) {
1371 if (i != 0) {
1372 valueString.append(" ");
1373 }
1374 valueString.append(valueArray[i]);
1375 }
1376 break;
1377 }
1378 case INT_ARRAY: {
1379 // Format the string representation of the int array as value1 value2......
1380 int[] valueArray = (int[]) value;
1381 for (int i = 0; i < valueArray.length; i++) {
1382 if (i != 0) {
1383 valueString.append(" ");
1384 }
1385 valueString.append(valueArray[i]);
1386 }
1387 break;
1388 }
1389 case LONG_ARRAY: {
1390 // Format the string representation of the int array as value1 value2......
1391 long[] valueArray = (long[]) value;
1392 for (int i = 0; i < valueArray.length; i++) {
1393 if (i != 0) {
1394 valueString.append(" ");
1395 }
1396 valueString.append(valueArray[i]);
1397 }
1398 break;
1399 }
1400 case STRING: {
1401 valueString.append("\"" + value.toString() + "\"");
1402 break;
1403 }
1404 case STRING_ARRAY: {
1405 // Format the string representation of the string array as "value1" "value2"....
1406 String[] valueArray = (String[]) value;
1407 for (int i = 0; i < valueArray.length; i++) {
1408 if (i != 0) {
1409 valueString.append(" ");
1410 }
1411 if (valueArray[i] != null) {
1412 valueString.append("\"" + valueArray[i] + "\"");
1413 } else {
1414 valueString.append("null");
1415 }
1416 }
1417 break;
1418 }
1419 default: {
1420 valueString.append(value.toString());
1421 }
1422 }
1423 }
1424 return String.format("%-70s %-15s %s", key, typeString, valueString);
1425 }
1426
1427 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1428 ArrayList<String> valueList) {
1429 PrintWriter errPw = getErrPrintWriter();
1430 PersistableBundle bundle = new PersistableBundle();
1431
1432 // First verify that a valid number of values has been provided for the type.
1433 switch (type) {
1434 case BOOLEAN:
1435 case DOUBLE:
1436 case INT:
1437 case LONG: {
1438 if (valueList.size() != 1) {
1439 errPw.println(tag + "Expected 1 value for type " + type
1440 + ". Found: " + valueList.size());
1441 return null;
1442 }
1443 break;
1444 }
1445 case STRING: {
1446 if (valueList.size() > 1) {
1447 errPw.println(tag + "Expected 0 or 1 values for type " + type
1448 + ". Found: " + valueList.size());
1449 return null;
1450 }
1451 break;
1452 }
1453 }
1454
1455 // Parse the value according to type and add it to the Bundle.
1456 switch (type) {
1457 case BOOLEAN: {
1458 if ("true".equalsIgnoreCase(valueList.get(0))) {
1459 bundle.putBoolean(key, true);
1460 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1461 bundle.putBoolean(key, false);
1462 } else {
1463 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1464 return null;
1465 }
1466 break;
1467 }
1468 case DOUBLE: {
1469 try {
1470 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1471 } catch (NumberFormatException nfe) {
1472 // Not a valid double
1473 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1474 return null;
1475 }
1476 break;
1477 }
1478 case DOUBLE_ARRAY: {
1479 double[] valueDoubleArray = null;
1480 if (valueList.size() > 0) {
1481 valueDoubleArray = new double[valueList.size()];
1482 for (int i = 0; i < valueList.size(); i++) {
1483 try {
1484 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1485 } catch (NumberFormatException nfe) {
1486 // Not a valid double
1487 errPw.println(
1488 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1489 return null;
1490 }
1491 }
1492 }
1493 bundle.putDoubleArray(key, valueDoubleArray);
1494 break;
1495 }
1496 case INT: {
1497 try {
1498 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1499 } catch (NumberFormatException nfe) {
1500 // Not a valid integer
1501 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1502 return null;
1503 }
1504 break;
1505 }
1506 case INT_ARRAY: {
1507 int[] valueIntArray = null;
1508 if (valueList.size() > 0) {
1509 valueIntArray = new int[valueList.size()];
1510 for (int i = 0; i < valueList.size(); i++) {
1511 try {
1512 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1513 } catch (NumberFormatException nfe) {
1514 // Not a valid integer
1515 errPw.println(tag
1516 + "Unable to parse " + valueList.get(i) + " as an integer.");
1517 return null;
1518 }
1519 }
1520 }
1521 bundle.putIntArray(key, valueIntArray);
1522 break;
1523 }
1524 case LONG: {
1525 try {
1526 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1527 } catch (NumberFormatException nfe) {
1528 // Not a valid long
1529 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1530 return null;
1531 }
1532 break;
1533 }
1534 case LONG_ARRAY: {
1535 long[] valueLongArray = null;
1536 if (valueList.size() > 0) {
1537 valueLongArray = new long[valueList.size()];
1538 for (int i = 0; i < valueList.size(); i++) {
1539 try {
1540 valueLongArray[i] = Long.parseLong(valueList.get(i));
1541 } catch (NumberFormatException nfe) {
1542 // Not a valid long
1543 errPw.println(
1544 tag + "Unable to parse " + valueList.get(i) + " as a long");
1545 return null;
1546 }
1547 }
1548 }
1549 bundle.putLongArray(key, valueLongArray);
1550 break;
1551 }
1552 case STRING: {
1553 String value = null;
1554 if (valueList.size() > 0) {
1555 value = valueList.get(0);
1556 }
1557 bundle.putString(key, value);
1558 break;
1559 }
1560 case STRING_ARRAY: {
1561 String[] valueStringArray = null;
1562 if (valueList.size() > 0) {
1563 valueStringArray = new String[valueList.size()];
1564 valueList.toArray(valueStringArray);
1565 }
1566 bundle.putStringArray(key, valueStringArray);
1567 break;
1568 }
1569 }
1570 return bundle;
1571 }
Shuo Qian489d9282020-07-09 11:30:03 -07001572
1573 private int handleEndBlockSuppressionCommand() {
1574 if (!checkShellUid()) {
1575 return -1;
1576 }
1577
1578 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1579 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1580 }
1581 return 0;
1582 }
Hui Wang641e81c2020-10-12 12:14:23 -07001583
Michele Berionne54af4632020-12-28 20:23:16 +00001584 private int handleRestartModemCommand() {
1585 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1586 // non user build.
1587 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1588 getErrPrintWriter().println("RestartModem: Permission denied.");
1589 return -1;
1590 }
1591
1592 boolean result = TelephonyManager.getDefault().rebootRadio();
1593 getOutPrintWriter().println(result);
1594
1595 return result ? 0 : -1;
1596 }
1597
Michele Berionne5e411512020-11-13 02:36:59 +00001598 private int handleUnattendedReboot() {
1599 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1600 // non user build.
1601 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1602 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1603 return -1;
1604 }
1605
1606 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1607 getOutPrintWriter().println("result: " + result);
1608
1609 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1610 }
1611
Hui Wang641e81c2020-10-12 12:14:23 -07001612 private int handleGbaCommand() {
1613 String arg = getNextArg();
1614 if (arg == null) {
1615 onHelpGba();
1616 return 0;
1617 }
1618
1619 switch (arg) {
1620 case GBA_SET_SERVICE: {
1621 return handleGbaSetServiceCommand();
1622 }
1623 case GBA_GET_SERVICE: {
1624 return handleGbaGetServiceCommand();
1625 }
1626 case GBA_SET_RELEASE_TIME: {
1627 return handleGbaSetReleaseCommand();
1628 }
1629 case GBA_GET_RELEASE_TIME: {
1630 return handleGbaGetReleaseCommand();
1631 }
1632 }
1633
1634 return -1;
1635 }
1636
1637 private int getSubId(String cmd) {
1638 int slotId = getDefaultSlot();
1639 String opt = getNextOption();
1640 if (opt != null && opt.equals("-s")) {
1641 try {
1642 slotId = Integer.parseInt(getNextArgRequired());
1643 } catch (NumberFormatException e) {
1644 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1645 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1646 }
1647 }
1648 int[] subIds = SubscriptionManager.getSubId(slotId);
1649 return subIds[0];
1650 }
1651
1652 private int handleGbaSetServiceCommand() {
1653 int subId = getSubId("gba set-service");
1654 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1655 return -1;
1656 }
1657
1658 String packageName = getNextArg();
1659 try {
1660 if (packageName == null) {
1661 packageName = "";
1662 }
1663 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1664 if (VDBG) {
1665 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1666 + packageName + ", result=" + result);
1667 }
1668 getOutPrintWriter().println(result);
1669 } catch (RemoteException e) {
1670 Log.w(LOG_TAG, "gba set-service " + subId + " "
1671 + packageName + ", error" + e.getMessage());
1672 getErrPrintWriter().println("Exception: " + e.getMessage());
1673 return -1;
1674 }
1675 return 0;
1676 }
1677
1678 private int handleGbaGetServiceCommand() {
1679 String result;
1680
1681 int subId = getSubId("gba get-service");
1682 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1683 return -1;
1684 }
1685
1686 try {
1687 result = mInterface.getBoundGbaService(subId);
1688 } catch (RemoteException e) {
1689 return -1;
1690 }
1691 if (VDBG) {
1692 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1693 }
1694 getOutPrintWriter().println(result);
1695 return 0;
1696 }
1697
1698 private int handleGbaSetReleaseCommand() {
1699 //the release time value could be -1
1700 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1701 : SubscriptionManager.getDefaultSubscriptionId();
1702 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1703 return -1;
1704 }
1705
1706 String intervalStr = getNextArg();
1707 if (intervalStr == null) {
1708 return -1;
1709 }
1710
1711 try {
1712 int interval = Integer.parseInt(intervalStr);
1713 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1714 if (VDBG) {
1715 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1716 + intervalStr + ", result=" + result);
1717 }
1718 getOutPrintWriter().println(result);
1719 } catch (NumberFormatException | RemoteException e) {
1720 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1721 + intervalStr + ", error" + e.getMessage());
1722 getErrPrintWriter().println("Exception: " + e.getMessage());
1723 return -1;
1724 }
1725 return 0;
1726 }
1727
1728 private int handleGbaGetReleaseCommand() {
1729 int subId = getSubId("gba get-release");
1730 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1731 return -1;
1732 }
1733
1734 int result = 0;
1735 try {
1736 result = mInterface.getGbaReleaseTime(subId);
1737 } catch (RemoteException e) {
1738 return -1;
1739 }
1740 if (VDBG) {
1741 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1742 }
1743 getOutPrintWriter().println(result);
1744 return 0;
1745 }
Hui Wang761a6682020-10-31 05:12:53 +00001746
1747 private int handleSingleRegistrationConfigCommand() {
1748 String arg = getNextArg();
1749 if (arg == null) {
1750 onHelpSrc();
1751 return 0;
1752 }
1753
1754 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001755 case SRC_SET_TEST_ENABLED: {
1756 return handleSrcSetTestEnabledCommand();
1757 }
1758 case SRC_GET_TEST_ENABLED: {
1759 return handleSrcGetTestEnabledCommand();
1760 }
Hui Wang761a6682020-10-31 05:12:53 +00001761 case SRC_SET_DEVICE_ENABLED: {
1762 return handleSrcSetDeviceEnabledCommand();
1763 }
1764 case SRC_GET_DEVICE_ENABLED: {
1765 return handleSrcGetDeviceEnabledCommand();
1766 }
1767 case SRC_SET_CARRIER_ENABLED: {
1768 return handleSrcSetCarrierEnabledCommand();
1769 }
1770 case SRC_GET_CARRIER_ENABLED: {
1771 return handleSrcGetCarrierEnabledCommand();
1772 }
1773 }
1774
1775 return -1;
1776 }
1777
James.cf Linbcdf8b32021-01-14 16:44:13 +08001778 private int handleRcsUceCommand() {
1779 String arg = getNextArg();
1780 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00001781 onHelpUce();
1782 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001783 }
1784
1785 switch (arg) {
1786 case UCE_REMOVE_EAB_CONTACT:
1787 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001788 case UCE_GET_EAB_CONTACT:
1789 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001790 case UCE_GET_DEVICE_ENABLED:
1791 return handleUceGetDeviceEnabledCommand();
1792 case UCE_SET_DEVICE_ENABLED:
1793 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00001794 case UCE_OVERRIDE_PUBLISH_CAPS:
1795 return handleUceOverridePublishCaps();
1796 case UCE_GET_LAST_PIDF_XML:
1797 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001798 }
1799 return -1;
1800 }
1801
1802 private int handleRemovingEabContactCommand() {
1803 int subId = getSubId("uce remove-eab-contact");
1804 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1805 return -1;
1806 }
1807
1808 String phoneNumber = getNextArgRequired();
1809 if (TextUtils.isEmpty(phoneNumber)) {
1810 return -1;
1811 }
1812 int result = 0;
1813 try {
1814 result = mInterface.removeContactFromEab(subId, phoneNumber);
1815 } catch (RemoteException e) {
1816 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1817 getErrPrintWriter().println("Exception: " + e.getMessage());
1818 return -1;
1819 }
1820
1821 if (VDBG) {
1822 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1823 }
calvinpan293ea1b2021-02-04 17:52:13 +08001824 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001825 }
1826
calvinpane4a8a1d2021-01-25 13:51:18 +08001827 private int handleGettingEabContactCommand() {
1828 String phoneNumber = getNextArgRequired();
1829 if (TextUtils.isEmpty(phoneNumber)) {
1830 return -1;
1831 }
1832 String result = "";
1833 try {
1834 result = mInterface.getContactFromEab(phoneNumber);
1835
1836 } catch (RemoteException e) {
1837 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1838 getErrPrintWriter().println("Exception: " + e.getMessage());
1839 return -1;
1840 }
1841
1842 if (VDBG) {
1843 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1844 }
calvinpan293ea1b2021-02-04 17:52:13 +08001845 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001846 return 0;
1847 }
1848
1849 private int handleUceGetDeviceEnabledCommand() {
1850 boolean result = false;
1851 try {
1852 result = mInterface.getDeviceUceEnabled();
1853 } catch (RemoteException e) {
1854 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1855 return -1;
1856 }
1857 if (VDBG) {
1858 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1859 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001860 getOutPrintWriter().println(result);
1861 return 0;
1862 }
1863
James.cf Lin4b784aa2021-01-31 03:25:15 +08001864 private int handleUceSetDeviceEnabledCommand() {
1865 String enabledStr = getNextArg();
1866 if (TextUtils.isEmpty(enabledStr)) {
1867 return -1;
1868 }
1869
1870 try {
1871 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1872 mInterface.setDeviceUceEnabled(isEnabled);
1873 if (VDBG) {
1874 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1875 }
1876 } catch (NumberFormatException | RemoteException e) {
1877 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1878 getErrPrintWriter().println("Exception: " + e.getMessage());
1879 return -1;
1880 }
1881 return 0;
1882 }
1883
Hui Wangbaaee6a2021-02-19 20:45:36 -08001884 private int handleSrcSetTestEnabledCommand() {
1885 String enabledStr = getNextArg();
1886 if (enabledStr == null) {
1887 return -1;
1888 }
1889
1890 try {
1891 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1892 if (VDBG) {
1893 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1894 }
1895 getOutPrintWriter().println("Done");
1896 } catch (NumberFormatException | RemoteException e) {
1897 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1898 getErrPrintWriter().println("Exception: " + e.getMessage());
1899 return -1;
1900 }
1901 return 0;
1902 }
1903
1904 private int handleSrcGetTestEnabledCommand() {
1905 boolean result = false;
1906 try {
1907 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1908 } catch (RemoteException e) {
1909 return -1;
1910 }
1911 if (VDBG) {
1912 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1913 }
1914 getOutPrintWriter().println(result);
1915 return 0;
1916 }
1917
Brad Ebinger14d467f2021-02-12 06:18:28 +00001918 private int handleUceOverridePublishCaps() {
1919 int subId = getSubId("uce override-published-caps");
1920 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1921 return -1;
1922 }
1923 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
1924 String operation = getNextArgRequired();
1925 String caps = getNextArg();
1926 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
1927 && !"list".equals(operation)) {
1928 getErrPrintWriter().println("Invalid operation: " + operation);
1929 return -1;
1930 }
1931
1932 // add/remove requires capabilities to be specified.
1933 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
1934 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
1935 + "specified");
1936 return -1;
1937 }
1938
1939 ArraySet<String> capSet = new ArraySet<>();
1940 if (!TextUtils.isEmpty(caps)) {
1941 String[] capArray = caps.split(":");
1942 for (String cap : capArray) {
1943 // Allow unknown tags to be passed in as well.
1944 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
1945 }
1946 }
1947
1948 RcsContactUceCapability result = null;
1949 try {
1950 switch (operation) {
1951 case "add":
1952 result = mInterface.addUceRegistrationOverrideShell(subId,
1953 new ArrayList<>(capSet));
1954 break;
1955 case "remove":
1956 result = mInterface.removeUceRegistrationOverrideShell(subId,
1957 new ArrayList<>(capSet));
1958 break;
1959 case "clear":
1960 result = mInterface.clearUceRegistrationOverrideShell(subId);
1961 break;
1962 case "list":
1963 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
1964 break;
1965 }
1966 } catch (RemoteException e) {
1967 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
1968 getErrPrintWriter().println("Exception: " + e.getMessage());
1969 return -1;
1970 } catch (ServiceSpecificException sse) {
1971 // Reconstruct ImsException
1972 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
1973 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
1974 getErrPrintWriter().println("Exception: " + imsException);
1975 return -1;
1976 }
1977 if (result == null) {
1978 getErrPrintWriter().println("Service not available");
1979 return -1;
1980 }
1981 getOutPrintWriter().println(result);
1982 return 0;
1983 }
1984
1985 private int handleUceGetPidfXml() {
1986 int subId = getSubId("uce get-last-publish-pidf");
1987 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1988 return -1;
1989 }
1990
1991 String result;
1992 try {
1993 result = mInterface.getLastUcePidfXmlShell(subId);
1994 } catch (RemoteException e) {
1995 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
1996 getErrPrintWriter().println("Exception: " + e.getMessage());
1997 return -1;
1998 } catch (ServiceSpecificException sse) {
1999 // Reconstruct ImsException
2000 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2001 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2002 getErrPrintWriter().println("Exception: " + imsException);
2003 return -1;
2004 }
2005 if (result == null) {
2006 getErrPrintWriter().println("Service not available");
2007 return -1;
2008 }
2009 getOutPrintWriter().println(result);
2010 return 0;
2011 }
2012
Hui Wang761a6682020-10-31 05:12:53 +00002013 private int handleSrcSetDeviceEnabledCommand() {
2014 String enabledStr = getNextArg();
2015 if (enabledStr == null) {
2016 return -1;
2017 }
2018
2019 try {
2020 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2021 if (VDBG) {
2022 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2023 }
2024 getOutPrintWriter().println("Done");
2025 } catch (NumberFormatException | RemoteException e) {
2026 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2027 getErrPrintWriter().println("Exception: " + e.getMessage());
2028 return -1;
2029 }
2030 return 0;
2031 }
2032
2033 private int handleSrcGetDeviceEnabledCommand() {
2034 boolean result = false;
2035 try {
2036 result = mInterface.getDeviceSingleRegistrationEnabled();
2037 } catch (RemoteException e) {
2038 return -1;
2039 }
2040 if (VDBG) {
2041 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2042 }
2043 getOutPrintWriter().println(result);
2044 return 0;
2045 }
2046
2047 private int handleSrcSetCarrierEnabledCommand() {
2048 //the release time value could be -1
2049 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2050 : SubscriptionManager.getDefaultSubscriptionId();
2051 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2052 return -1;
2053 }
2054
2055 String enabledStr = getNextArg();
2056 if (enabledStr == null) {
2057 return -1;
2058 }
2059
2060 try {
2061 boolean result =
2062 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2063 if (VDBG) {
2064 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2065 + enabledStr + ", result=" + result);
2066 }
2067 getOutPrintWriter().println(result);
2068 } catch (NumberFormatException | RemoteException e) {
2069 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2070 + enabledStr + ", error" + e.getMessage());
2071 getErrPrintWriter().println("Exception: " + e.getMessage());
2072 return -1;
2073 }
2074 return 0;
2075 }
2076
2077 private int handleSrcGetCarrierEnabledCommand() {
2078 int subId = getSubId("src get-carrier-enabled");
2079 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2080 return -1;
2081 }
2082
2083 boolean result = false;
2084 try {
2085 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2086 } catch (RemoteException e) {
2087 return -1;
2088 }
2089 if (VDBG) {
2090 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2091 }
2092 getOutPrintWriter().println(result);
2093 return 0;
2094 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002095
2096 private void onHelpCallComposer() {
2097 PrintWriter pw = getOutPrintWriter();
2098 pw.println("Call composer commands");
2099 pw.println(" callcomposer test-mode enable|disable|query");
2100 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2101 pw.println(" upload/download from carrier servers is disabled, and operations are");
2102 pw.println(" performed using emulated local files instead.");
2103 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2104 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2105 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002106 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2107 pw.println(" Enables or disables the user setting for call composer, as set by");
2108 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002109 }
2110
2111 private int handleCallComposerCommand() {
2112 String arg = getNextArg();
2113 if (arg == null) {
2114 onHelpCallComposer();
2115 return 0;
2116 }
2117
2118 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2119 "MODIFY_PHONE_STATE required for call composer shell cmds");
2120 switch (arg) {
2121 case CALL_COMPOSER_TEST_MODE: {
2122 String enabledStr = getNextArg();
2123 if (ENABLE.equals(enabledStr)) {
2124 CallComposerPictureManager.sTestMode = true;
2125 } else if (DISABLE.equals(enabledStr)) {
2126 CallComposerPictureManager.sTestMode = false;
2127 } else if (QUERY.equals(enabledStr)) {
2128 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2129 } else {
2130 onHelpCallComposer();
2131 return 1;
2132 }
2133 break;
2134 }
2135 case CALL_COMPOSER_SIMULATE_CALL: {
2136 int subscriptionId = Integer.valueOf(getNextArg());
2137 String uuidString = getNextArg();
2138 UUID uuid = UUID.fromString(uuidString);
2139 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2140 Binder.withCleanCallingIdentity(() -> {
2141 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2142 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2143 });
2144 try {
2145 Uri uri = storageUriFuture.get();
2146 getOutPrintWriter().println(String.valueOf(uri));
2147 } catch (Exception e) {
2148 throw new RuntimeException(e);
2149 }
2150 break;
2151 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002152 case CALL_COMPOSER_USER_SETTING: {
2153 try {
2154 int subscriptionId = Integer.valueOf(getNextArg());
2155 String enabledStr = getNextArg();
2156 if (ENABLE.equals(enabledStr)) {
2157 mInterface.setCallComposerStatus(subscriptionId,
2158 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2159 } else if (DISABLE.equals(enabledStr)) {
2160 mInterface.setCallComposerStatus(subscriptionId,
2161 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2162 } else if (QUERY.equals(enabledStr)) {
2163 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2164 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2165 } else {
2166 onHelpCallComposer();
2167 return 1;
2168 }
2169 } catch (RemoteException e) {
2170 e.printStackTrace(getOutPrintWriter());
2171 return 1;
2172 }
2173 break;
2174 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002175 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002176 return 0;
2177 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002178
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002179 private int handleHasCarrierPrivilegesCommand() {
2180 String packageName = getNextArgRequired();
2181
2182 boolean hasCarrierPrivileges;
2183 try {
2184 hasCarrierPrivileges =
2185 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2186 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2187 } catch (RemoteException e) {
2188 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2189 getErrPrintWriter().println("Exception: " + e.getMessage());
2190 return -1;
2191 }
2192
2193 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002194 return 0;
2195 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002196}