blob: f5b6ad8b234a063d237a8bf778a418b9af0e4755 [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
Jack Nudelman644b91a2021-03-12 14:09:48 -0800144 private static final String THERMAL_MITIGATION_COMMAND = "thermal-mitigation";
145 private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
146 private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
147
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700148 // Take advantage of existing methods that already contain permissions checks when possible.
149 private final ITelephony mInterface;
150
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100151 private SubscriptionManager mSubscriptionManager;
152 private CarrierConfigManager mCarrierConfigManager;
Shuo Qian489d9282020-07-09 11:30:03 -0700153 private Context mContext;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100154
155 private enum CcType {
156 BOOLEAN, DOUBLE, DOUBLE_ARRAY, INT, INT_ARRAY, LONG, LONG_ARRAY, STRING,
157 STRING_ARRAY, UNKNOWN
158 }
159
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100160 private class CcOptionParseResult {
161 public int mSubId;
162 public boolean mPersistent;
163 }
164
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100165 // Maps carrier config keys to type. It is possible to infer the type for most carrier config
166 // keys by looking at the end of the string which usually tells the type.
167 // For instance: "xxxx_string", "xxxx_string_array", etc.
168 // The carrier config keys in this map does not follow this convention. It is therefore not
169 // possible to infer the type for these keys by looking at the string.
170 private static final Map<String, CcType> CC_TYPE_MAP = new HashMap<String, CcType>() {{
171 put(CarrierConfigManager.Gps.KEY_A_GLONASS_POS_PROTOCOL_SELECT_STRING, CcType.STRING);
172 put(CarrierConfigManager.Gps.KEY_ES_EXTENSION_SEC_STRING, CcType.STRING);
173 put(CarrierConfigManager.Gps.KEY_GPS_LOCK_STRING, CcType.STRING);
174 put(CarrierConfigManager.Gps.KEY_LPP_PROFILE_STRING, CcType.STRING);
175 put(CarrierConfigManager.Gps.KEY_NFW_PROXY_APPS_STRING, CcType.STRING);
176 put(CarrierConfigManager.Gps.KEY_SUPL_ES_STRING, CcType.STRING);
177 put(CarrierConfigManager.Gps.KEY_SUPL_HOST_STRING, CcType.STRING);
178 put(CarrierConfigManager.Gps.KEY_SUPL_MODE_STRING, CcType.STRING);
179 put(CarrierConfigManager.Gps.KEY_SUPL_PORT_STRING, CcType.STRING);
180 put(CarrierConfigManager.Gps.KEY_SUPL_VER_STRING, CcType.STRING);
181 put(CarrierConfigManager.Gps.KEY_USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL_STRING,
182 CcType.STRING);
183 put(CarrierConfigManager.KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
184 CcType.STRING_ARRAY);
185 put(CarrierConfigManager.KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
186 CcType.STRING_ARRAY);
187 put(CarrierConfigManager.KEY_CARRIER_CALL_SCREENING_APP_STRING, CcType.STRING);
188 put(CarrierConfigManager.KEY_MMS_EMAIL_GATEWAY_NUMBER_STRING, CcType.STRING);
189 put(CarrierConfigManager.KEY_MMS_HTTP_PARAMS_STRING, CcType.STRING);
190 put(CarrierConfigManager.KEY_MMS_NAI_SUFFIX_STRING, CcType.STRING);
191 put(CarrierConfigManager.KEY_MMS_UA_PROF_TAG_NAME_STRING, CcType.STRING);
192 put(CarrierConfigManager.KEY_MMS_UA_PROF_URL_STRING, CcType.STRING);
193 put(CarrierConfigManager.KEY_MMS_USER_AGENT_STRING, CcType.STRING);
194 put(CarrierConfigManager.KEY_RATCHET_RAT_FAMILIES, CcType.STRING_ARRAY);
195 }
196 };
197
Brad Ebinger14d467f2021-02-12 06:18:28 +0000198 /**
199 * Map from a shorthand string to the feature tags required in registration required in order
200 * for the RCS feature to be considered "capable".
201 */
202 private static final Map<String, Set<String>> TEST_FEATURE_TAG_MAP;
203 static {
204 ArrayMap<String, Set<String>> map = new ArrayMap<>(18);
205 map.put("chat_v1", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
206 map.put("chat_v2", Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_SESSION));
207 map.put("ft", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER));
208 map.put("ft_sms", Collections.singleton(FeatureTags.FEATURE_TAG_FILE_TRANSFER_VIA_SMS));
209 map.put("mmtel", Collections.singleton(FeatureTags.FEATURE_TAG_MMTEL));
210 map.put("mmtel_vt", new ArraySet<>(Arrays.asList(FeatureTags.FEATURE_TAG_MMTEL,
211 FeatureTags.FEATURE_TAG_VIDEO)));
212 map.put("geo_push", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH));
213 map.put("geo_push_sms", Collections.singleton(FeatureTags.FEATURE_TAG_GEO_PUSH_VIA_SMS));
214 map.put("call_comp",
215 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_ENRICHED_CALLING));
216 map.put("call_comp_mmtel",
217 Collections.singleton(FeatureTags.FEATURE_TAG_CALL_COMPOSER_VIA_TELEPHONY));
218 map.put("call_post", Collections.singleton(FeatureTags.FEATURE_TAG_POST_CALL));
219 map.put("map", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_MAP));
220 map.put("sketch", Collections.singleton(FeatureTags.FEATURE_TAG_SHARED_SKETCH));
221 // Feature tags defined twice for chatbot session because we want v1 and v2 based on bot
222 // version
223 map.put("chatbot", new ArraySet<>(Arrays.asList(
224 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
225 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
226 map.put("chatbot_v2", new ArraySet<>(Arrays.asList(
227 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_SESSION,
228 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
229 map.put("chatbot_sa", new ArraySet<>(Arrays.asList(
230 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
231 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
232 map.put("chatbot_sa_v2", new ArraySet<>(Arrays.asList(
233 FeatureTags.FEATURE_TAG_CHATBOT_COMMUNICATION_USING_STANDALONE_MSG,
234 FeatureTags.FEATURE_TAG_CHATBOT_VERSION_SUPPORTED)));
235 map.put("chatbot_role", Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
236 TEST_FEATURE_TAG_MAP = Collections.unmodifiableMap(map);
237 }
238
239
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100240 public TelephonyShellCommand(ITelephony binder, Context context) {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700241 mInterface = binder;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100242 mCarrierConfigManager =
243 (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
244 mSubscriptionManager = (SubscriptionManager)
245 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
Shuo Qian489d9282020-07-09 11:30:03 -0700246 mContext = context;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700247 }
248
249 @Override
250 public int onCommand(String cmd) {
251 if (cmd == null) {
252 return handleDefaultCommands(null);
253 }
254
255 switch (cmd) {
256 case IMS_SUBCOMMAND: {
257 return handleImsCommand();
258 }
James.cf Linbcdf8b32021-01-14 16:44:13 +0800259 case RCS_UCE_COMMAND:
260 return handleRcsUceCommand();
Hall Liud892bec2018-11-30 14:51:45 -0800261 case NUMBER_VERIFICATION_SUBCOMMAND:
262 return handleNumberVerificationCommand();
Shuo Qianccbaf742021-02-22 18:32:21 -0800263 case EMERGENCY_CALLBACK_MODE:
264 return handleEmergencyCallbackModeCommand();
sqian9d4df8b2019-01-15 18:32:07 -0800265 case EMERGENCY_NUMBER_TEST_MODE:
266 return handleEmergencyNumberTestModeCommand();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100267 case CARRIER_CONFIG_SUBCOMMAND: {
268 return handleCcCommand();
269 }
Shuo Qianf5125122019-12-16 17:03:07 -0800270 case DATA_TEST_MODE:
271 return handleDataTestModeCommand();
Shuo Qian489d9282020-07-09 11:30:03 -0700272 case END_BLOCK_SUPPRESSION:
273 return handleEndBlockSuppressionCommand();
Hui Wang641e81c2020-10-12 12:14:23 -0700274 case GBA_SUBCOMMAND:
275 return handleGbaCommand();
Tyler Gunn92479152021-01-20 16:30:10 -0800276 case D2D_SUBCOMMAND:
277 return handleD2dCommand();
Hui Wang761a6682020-10-31 05:12:53 +0000278 case SINGLE_REGISTATION_CONFIG:
279 return handleSingleRegistrationConfigCommand();
Michele Berionne54af4632020-12-28 20:23:16 +0000280 case RESTART_MODEM:
281 return handleRestartModemCommand();
Hall Liuaa4211e2021-01-20 15:43:39 -0800282 case CALL_COMPOSER_SUBCOMMAND:
283 return handleCallComposerCommand();
Michele Berionne5e411512020-11-13 02:36:59 +0000284 case UNATTENDED_REBOOT:
285 return handleUnattendedReboot();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800286 case HAS_CARRIER_PRIVILEGES_COMMAND:
287 return handleHasCarrierPrivilegesCommand();
Jack Nudelman644b91a2021-03-12 14:09:48 -0800288 case THERMAL_MITIGATION_COMMAND:
289 return handleThermalMitigationCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700290 default: {
291 return handleDefaultCommands(cmd);
292 }
293 }
294 }
295
296 @Override
297 public void onHelp() {
298 PrintWriter pw = getOutPrintWriter();
299 pw.println("Telephony Commands:");
300 pw.println(" help");
301 pw.println(" Print this help text.");
302 pw.println(" ims");
303 pw.println(" IMS Commands.");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800304 pw.println(" uce");
305 pw.println(" RCS User Capability Exchange Commands.");
sqian9d4df8b2019-01-15 18:32:07 -0800306 pw.println(" emergency-number-test-mode");
307 pw.println(" Emergency Number Test Mode Commands.");
Shuo Qian489d9282020-07-09 11:30:03 -0700308 pw.println(" end-block-suppression");
309 pw.println(" End Block Suppression command.");
Shuo Qianf5125122019-12-16 17:03:07 -0800310 pw.println(" data");
311 pw.println(" Data Test Mode Commands.");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100312 pw.println(" cc");
313 pw.println(" Carrier Config Commands.");
Hui Wang641e81c2020-10-12 12:14:23 -0700314 pw.println(" gba");
315 pw.println(" GBA Commands.");
Hui Wang761a6682020-10-31 05:12:53 +0000316 pw.println(" src");
317 pw.println(" RCS VoLTE Single Registration Config Commands.");
Michele Berionne54af4632020-12-28 20:23:16 +0000318 pw.println(" restart-modem");
319 pw.println(" Restart modem command.");
Michele Berionne5e411512020-11-13 02:36:59 +0000320 pw.println(" unattended-reboot");
321 pw.println(" Prepare for unattended reboot.");
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800322 pw.println(" has-carrier-privileges [package]");
323 pw.println(" Query carrier privilege status for a package. Prints true or false.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700324 onHelpIms();
James.cf Linbcdf8b32021-01-14 16:44:13 +0800325 onHelpUce();
sqian9d4df8b2019-01-15 18:32:07 -0800326 onHelpEmergencyNumber();
Shuo Qian489d9282020-07-09 11:30:03 -0700327 onHelpEndBlockSupperssion();
Shuo Qianf5125122019-12-16 17:03:07 -0800328 onHelpDataTestMode();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100329 onHelpCc();
Hui Wang641e81c2020-10-12 12:14:23 -0700330 onHelpGba();
Hui Wang761a6682020-10-31 05:12:53 +0000331 onHelpSrc();
Tyler Gunn92479152021-01-20 16:30:10 -0800332 onHelpD2D();
333 }
334
335 private void onHelpD2D() {
336 PrintWriter pw = getOutPrintWriter();
337 pw.println("D2D Comms Commands:");
338 pw.println(" d2d send TYPE VALUE");
339 pw.println(" Sends a D2D message of specified type and value.");
340 pw.println(" Type: " + MESSAGE_CALL_RADIO_ACCESS_TYPE + " - "
341 + Communicator.messageToString(MESSAGE_CALL_RADIO_ACCESS_TYPE));
342 pw.println(" Type: " + MESSAGE_CALL_AUDIO_CODEC + " - " + Communicator.messageToString(
343 MESSAGE_CALL_AUDIO_CODEC));
344 pw.println(" Type: " + MESSAGE_DEVICE_BATTERY_STATE + " - "
345 + Communicator.messageToString(
346 MESSAGE_DEVICE_BATTERY_STATE));
347 pw.println(" Type: " + MESSAGE_DEVICE_NETWORK_COVERAGE + " - "
348 + Communicator.messageToString(MESSAGE_DEVICE_NETWORK_COVERAGE));
Tyler Gunnbabbda02021-02-10 11:05:02 -0800349 pw.println(" d2d transport TYPE");
350 pw.println(" Forces the specified D2D transport TYPE to be active. Use the");
351 pw.println(" short class name of the transport; i.e. DtmfTransport or RtpTransport.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700352 }
353
354 private void onHelpIms() {
355 PrintWriter pw = getOutPrintWriter();
356 pw.println("IMS Commands:");
Brad Ebinger24c29992019-12-05 13:03:21 -0800357 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700358 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
359 pw.println(" ImsService. Options are:");
360 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
361 pw.println(" is specified, it will choose the default voice SIM slot.");
362 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
363 pw.println(" -d: Override the ImsService defined in the device overlay.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800364 pw.println(" -f: Set the feature that this override if for, if no option is");
365 pw.println(" specified, the new package name will be used for all features.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700366 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
367 pw.println(" Gets the package name of the currently defined ImsService.");
368 pw.println(" Options are:");
369 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
370 pw.println(" is specified, it will choose the default voice SIM slot.");
371 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
Peter Kalauskas1defdc32020-09-03 19:20:26 +0000372 pw.println(" -d: The ImsService defined as the device default ImsService.");
Brad Ebinger24c29992019-12-05 13:03:21 -0800373 pw.println(" -f: The feature type that the query will be requested for. If none is");
374 pw.println(" specified, the returned package name will correspond to MMTEL.");
Brad Ebinger999d3302020-11-25 14:31:39 -0800375 pw.println(" ims clear-ims-service-override [-s SLOT_ID]");
376 pw.println(" Clear all carrier ImsService overrides. This does not work for device ");
377 pw.println(" configuration overrides. Options are:");
378 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
379 pw.println(" is specified, it will choose the default voice SIM slot.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700380 pw.println(" ims enable [-s SLOT_ID]");
381 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
382 pw.println(" if none is specified.");
383 pw.println(" ims disable [-s SLOT_ID]");
384 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
385 pw.println(" slot if none is specified.");
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700386 pw.println(" ims conference-event-package [enable/disable]");
387 pw.println(" enables or disables handling or network conference event package data.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700388 }
389
James.cf Linbcdf8b32021-01-14 16:44:13 +0800390 private void onHelpUce() {
391 PrintWriter pw = getOutPrintWriter();
392 pw.println("User Capability Exchange Commands:");
calvinpane4a8a1d2021-01-25 13:51:18 +0800393 pw.println(" uce get-eab-contact [PHONE_NUMBER]");
394 pw.println(" Get the EAB contacts from the EAB database.");
395 pw.println(" Options are:");
396 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
397 pw.println(" Expected output format :");
398 pw.println(" [PHONE_NUMBER],[RAW_CONTACT_ID],[CONTACT_ID],[DATA_ID]");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800399 pw.println(" uce remove-eab-contact [-s SLOT_ID] [PHONE_NUMBER]");
400 pw.println(" Remove the EAB contacts from the EAB database.");
401 pw.println(" Options are:");
402 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
403 pw.println(" is specified, it will choose the default voice SIM slot.");
404 pw.println(" PHONE_NUMBER: The phone numbers to be removed from the EAB databases");
James.cf Lin4b784aa2021-01-31 03:25:15 +0800405 pw.println(" uce get-device-enabled");
406 pw.println(" Get the config to check whether the device supports RCS UCE or not.");
407 pw.println(" uce set-device-enabled true|false");
408 pw.println(" Set the device config for RCS User Capability Exchange to the value.");
409 pw.println(" The value could be true, false.");
Brad Ebinger14d467f2021-02-12 06:18:28 +0000410 pw.println(" uce override-published-caps [-s SLOT_ID] add|remove|clear [CAPABILITIES]");
411 pw.println(" Override the existing SIP PUBLISH with different capabilities.");
412 pw.println(" Options are:");
413 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
414 pw.println(" is specified, it will choose the default voice SIM slot.");
415 pw.println(" add [CAPABILITY]: add a new capability");
416 pw.println(" remove [CAPABILITY]: remove a capability");
417 pw.println(" clear: clear all capability overrides");
418 pw.println(" CAPABILITY: \":\" separated list of capabilities.");
419 pw.println(" Valid options are: [mmtel(_vt), chat_v1, chat_v2, ft, ft_sms,");
420 pw.println(" geo_push, geo_push_sms, call_comp, call_post, map, sketch, chatbot,");
421 pw.println(" chatbot_sa, chatbot_role] as well as full length");
422 pw.println(" featureTag=\"featureValue\" feature tags that are not defined here.");
423 pw.println(" uce get-last-publish-pidf [-s SLOT_ID]");
424 pw.println(" Get the PIDF XML included in the last SIP PUBLISH, or \"none\" if no ");
425 pw.println(" PUBLISH is active");
James.cf Linbcdf8b32021-01-14 16:44:13 +0800426 }
427
Hall Liud892bec2018-11-30 14:51:45 -0800428 private void onHelpNumberVerification() {
429 PrintWriter pw = getOutPrintWriter();
430 pw.println("Number verification commands");
431 pw.println(" numverify override-package PACKAGE_NAME;");
432 pw.println(" Set the authorized package for number verification.");
433 pw.println(" Leave the package name blank to reset.");
Hall Liuca5af3a2018-12-04 16:58:23 -0800434 pw.println(" numverify fake-call NUMBER;");
435 pw.println(" Fake an incoming call from NUMBER. This is for testing. Output will be");
436 pw.println(" 1 if the call would have been intercepted, 0 otherwise.");
Hall Liud892bec2018-11-30 14:51:45 -0800437 }
438
Jack Nudelman644b91a2021-03-12 14:09:48 -0800439 private void onHelpThermalMitigation() {
440 PrintWriter pw = getOutPrintWriter();
441 pw.println("Thermal mitigation commands");
442 pw.println(" thermal-mitigation allow-package PACKAGE_NAME");
443 pw.println(" Set the package as one of authorized packages for thermal mitigation.");
444 pw.println(" thermal-mitigation disallow-package PACKAGE_NAME");
445 pw.println(" Remove the package from one of the authorized packages for thermal "
446 + "mitigation.");
447 }
448
Shuo Qianf5125122019-12-16 17:03:07 -0800449 private void onHelpDataTestMode() {
450 PrintWriter pw = getOutPrintWriter();
451 pw.println("Mobile Data Test Mode Commands:");
452 pw.println(" data enable: enable mobile data connectivity");
453 pw.println(" data disable: disable mobile data connectivity");
454 }
455
sqian9d4df8b2019-01-15 18:32:07 -0800456 private void onHelpEmergencyNumber() {
457 PrintWriter pw = getOutPrintWriter();
458 pw.println("Emergency Number Test Mode Commands:");
459 pw.println(" emergency-number-test-mode ");
460 pw.println(" Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in"
461 + " the test mode");
462 pw.println(" -a <emergency number address>: add an emergency number address for the"
sqian9121f982019-03-14 19:45:39 -0700463 + " test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800464 pw.println(" -c: clear the emergency number list in the test mode.");
465 pw.println(" -r <emergency number address>: remove an existing emergency number"
sqian9121f982019-03-14 19:45:39 -0700466 + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'.");
sqian9d4df8b2019-01-15 18:32:07 -0800467 pw.println(" -p: get the full emergency number list in the test mode.");
468 }
469
Shuo Qian489d9282020-07-09 11:30:03 -0700470 private void onHelpEndBlockSupperssion() {
471 PrintWriter pw = getOutPrintWriter();
472 pw.println("End Block Suppression command:");
473 pw.println(" end-block-suppression: disable suppressing blocking by contact");
474 pw.println(" with emergency services.");
475 }
476
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100477 private void onHelpCc() {
478 PrintWriter pw = getOutPrintWriter();
479 pw.println("Carrier Config Commands:");
480 pw.println(" cc get-value [-s SLOT_ID] [KEY]");
481 pw.println(" Print carrier config values.");
482 pw.println(" Options are:");
483 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
484 pw.println(" is specified, it will choose the default voice SIM slot.");
485 pw.println(" KEY: The key to the carrier config value to print. All values are printed");
486 pw.println(" if KEY is not specified.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100487 pw.println(" cc set-value [-s SLOT_ID] [-p] KEY [NEW_VALUE]");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100488 pw.println(" Set carrier config KEY to NEW_VALUE.");
489 pw.println(" Options are:");
490 pw.println(" -s: The SIM slot ID to set carrier config value for. If no option");
491 pw.println(" is specified, it will choose the default voice SIM slot.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +0100492 pw.println(" -p: Value will be stored persistent");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +0100493 pw.println(" NEW_VALUE specifies the new value for carrier config KEY. Null will be");
494 pw.println(" used if NEW_VALUE is not set. Strings should be encapsulated with");
495 pw.println(" quotation marks. Spaces needs to be escaped. Example: \"Hello\\ World\"");
496 pw.println(" Separate items in arrays with space . Example: \"item1\" \"item2\"");
497 pw.println(" cc clear-values [-s SLOT_ID]");
498 pw.println(" Clear all carrier override values that has previously been set");
499 pw.println(" with set-value");
500 pw.println(" Options are:");
501 pw.println(" -s: The SIM slot ID to clear carrier config values for. If no option");
502 pw.println(" is specified, it will choose the default voice SIM slot.");
503 }
504
Hui Wang641e81c2020-10-12 12:14:23 -0700505 private void onHelpGba() {
506 PrintWriter pw = getOutPrintWriter();
507 pw.println("Gba Commands:");
508 pw.println(" gba set-service [-s SLOT_ID] PACKAGE_NAME");
509 pw.println(" Sets the GbaService defined in PACKAGE_NAME to to be the bound.");
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 pw.println(" gba get-service [-s SLOT_ID]");
514 pw.println(" Gets the package name of the currently defined GbaService.");
515 pw.println(" Options are:");
516 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
517 pw.println(" is specified, it will choose the default voice SIM slot.");
518 pw.println(" gba set-release [-s SLOT_ID] n");
519 pw.println(" Sets the time to release/unbind GbaService in n milli-second.");
520 pw.println(" Do not release/unbind if n is -1.");
521 pw.println(" Options are:");
522 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
523 pw.println(" is specified, it will choose the default voice SIM slot.");
524 pw.println(" gba get-release [-s SLOT_ID]");
525 pw.println(" Gets the time to release/unbind GbaService in n milli-sencond.");
526 pw.println(" Options are:");
527 pw.println(" -s: The SIM slot ID to read carrier config value for. If no option");
528 pw.println(" is specified, it will choose the default voice SIM slot.");
529 }
530
Hui Wang761a6682020-10-31 05:12:53 +0000531 private void onHelpSrc() {
532 PrintWriter pw = getOutPrintWriter();
533 pw.println("RCS VoLTE Single Registration Config Commands:");
Hui Wangbaaee6a2021-02-19 20:45:36 -0800534 pw.println(" src set-test-enabled true|false");
535 pw.println(" Sets the test mode enabled for RCS VoLTE single registration.");
536 pw.println(" The value could be true, false, or null(undefined).");
537 pw.println(" src get-test-enabled");
538 pw.println(" Gets the test mode for RCS VoLTE single registration.");
Hui Wang761a6682020-10-31 05:12:53 +0000539 pw.println(" src set-device-enabled true|false|null");
540 pw.println(" Sets the device config for RCS VoLTE single registration to the value.");
541 pw.println(" The value could be true, false, or null(undefined).");
542 pw.println(" src get-device-enabled");
543 pw.println(" Gets the device config for RCS VoLTE single registration.");
544 pw.println(" src set-carrier-enabled [-s SLOT_ID] true|false|null");
545 pw.println(" Sets the carrier config for RCS VoLTE single registration to the value.");
546 pw.println(" The value could be true, false, or null(undefined).");
547 pw.println(" Options are:");
548 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
549 pw.println(" is specified, it will choose the default voice SIM slot.");
550 pw.println(" src get-carrier-enabled [-s SLOT_ID]");
551 pw.println(" Gets the carrier config for RCS VoLTE single registration.");
552 pw.println(" Options are:");
553 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
554 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wangb647abe2021-02-26 09:33:38 -0800555 pw.println(" src set-feature-validation [-s SLOT_ID] true|false|null");
556 pw.println(" Sets ims feature validation result.");
557 pw.println(" The value could be true, false, or null(undefined).");
558 pw.println(" Options are:");
559 pw.println(" -s: The SIM slot ID to set the config value for. If no option");
560 pw.println(" is specified, it will choose the default voice SIM slot.");
561 pw.println(" src get-feature-validation [-s SLOT_ID]");
562 pw.println(" Gets ims feature validation override value.");
563 pw.println(" Options are:");
564 pw.println(" -s: The SIM slot ID to read the config value for. If no option");
565 pw.println(" is specified, it will choose the default voice SIM slot.");
Hui Wang761a6682020-10-31 05:12:53 +0000566 }
567
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700568 private int handleImsCommand() {
569 String arg = getNextArg();
570 if (arg == null) {
571 onHelpIms();
572 return 0;
573 }
574
575 switch (arg) {
Brad Ebinger999d3302020-11-25 14:31:39 -0800576 case IMS_SET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700577 return handleImsSetServiceCommand();
578 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800579 case IMS_GET_IMS_SERVICE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700580 return handleImsGetServiceCommand();
581 }
Brad Ebinger999d3302020-11-25 14:31:39 -0800582 case IMS_CLEAR_SERVICE_OVERRIDE: {
583 return handleImsClearCarrierServiceCommand();
584 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800585 case ENABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700586 return handleEnableIms();
587 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800588 case DISABLE: {
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700589 return handleDisableIms();
590 }
Tyler Gunn7bcdc742019-10-04 15:56:59 -0700591 case IMS_CEP: {
592 return handleCepChange();
593 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700594 }
595
596 return -1;
597 }
598
Shuo Qianf5125122019-12-16 17:03:07 -0800599 private int handleDataTestModeCommand() {
600 PrintWriter errPw = getErrPrintWriter();
601 String arg = getNextArgRequired();
602 if (arg == null) {
603 onHelpDataTestMode();
604 return 0;
605 }
606 switch (arg) {
Hall Liuaa4211e2021-01-20 15:43:39 -0800607 case ENABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800608 try {
609 mInterface.enableDataConnectivity();
610 } catch (RemoteException ex) {
611 Log.w(LOG_TAG, "data enable, error " + ex.getMessage());
612 errPw.println("Exception: " + ex.getMessage());
613 return -1;
614 }
615 break;
616 }
Hall Liuaa4211e2021-01-20 15:43:39 -0800617 case DISABLE: {
Shuo Qianf5125122019-12-16 17:03:07 -0800618 try {
619 mInterface.disableDataConnectivity();
620 } catch (RemoteException ex) {
621 Log.w(LOG_TAG, "data disable, error " + ex.getMessage());
622 errPw.println("Exception: " + ex.getMessage());
623 return -1;
624 }
625 break;
626 }
627 default:
628 onHelpDataTestMode();
629 break;
630 }
631 return 0;
632 }
633
Shuo Qianccbaf742021-02-22 18:32:21 -0800634 private int handleEmergencyCallbackModeCommand() {
635 PrintWriter errPw = getErrPrintWriter();
636 try {
637 mInterface.startEmergencyCallbackMode();
638 Log.d(LOG_TAG, "handleEmergencyCallbackModeCommand: triggered");
639 } catch (RemoteException ex) {
640 Log.w(LOG_TAG, "emergency-callback-mode error: " + ex.getMessage());
641 errPw.println("Exception: " + ex.getMessage());
642 return -1;
643 }
644 return 0;
645 }
646
sqian9d4df8b2019-01-15 18:32:07 -0800647 private int handleEmergencyNumberTestModeCommand() {
648 PrintWriter errPw = getErrPrintWriter();
649 String opt = getNextOption();
650 if (opt == null) {
651 onHelpEmergencyNumber();
652 return 0;
653 }
654
655 switch (opt) {
656 case "-a": {
657 String emergencyNumberCmd = getNextArgRequired();
658 if (emergencyNumberCmd == null
659 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700660 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800661 + " to be specified after -a in the command ");
662 return -1;
663 }
664 try {
665 mInterface.updateEmergencyNumberListTestMode(
666 EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
667 new EmergencyNumber(emergencyNumberCmd, "", "",
668 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
669 new ArrayList<String>(),
670 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
671 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
672 } catch (RemoteException ex) {
673 Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
674 + ", error " + ex.getMessage());
675 errPw.println("Exception: " + ex.getMessage());
676 return -1;
677 }
678 break;
679 }
680 case "-c": {
681 try {
682 mInterface.updateEmergencyNumberListTestMode(
683 EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null);
684 } catch (RemoteException ex) {
685 Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage());
686 errPw.println("Exception: " + ex.getMessage());
687 return -1;
688 }
689 break;
690 }
691 case "-r": {
692 String emergencyNumberCmd = getNextArgRequired();
693 if (emergencyNumberCmd == null
694 || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
sqian9121f982019-03-14 19:45:39 -0700695 errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
sqian9d4df8b2019-01-15 18:32:07 -0800696 + " to be specified after -r in the command ");
697 return -1;
698 }
699 try {
700 mInterface.updateEmergencyNumberListTestMode(
701 EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
702 new EmergencyNumber(emergencyNumberCmd, "", "",
703 EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
704 new ArrayList<String>(),
705 EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
706 EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
707 } catch (RemoteException ex) {
708 Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
709 + ", error " + ex.getMessage());
710 errPw.println("Exception: " + ex.getMessage());
711 return -1;
712 }
713 break;
714 }
715 case "-p": {
716 try {
717 getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode());
718 } catch (RemoteException ex) {
719 Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage());
720 errPw.println("Exception: " + ex.getMessage());
721 return -1;
722 }
723 break;
724 }
725 default:
726 onHelpEmergencyNumber();
727 break;
728 }
729 return 0;
730 }
731
Hall Liud892bec2018-11-30 14:51:45 -0800732 private int handleNumberVerificationCommand() {
733 String arg = getNextArg();
734 if (arg == null) {
735 onHelpNumberVerification();
736 return 0;
737 }
738
Hall Liuca5af3a2018-12-04 16:58:23 -0800739 if (!checkShellUid()) {
740 return -1;
741 }
742
Hall Liud892bec2018-11-30 14:51:45 -0800743 switch (arg) {
744 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
Hall Liud892bec2018-11-30 14:51:45 -0800745 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
746 return 0;
747 }
Hall Liuca5af3a2018-12-04 16:58:23 -0800748 case NUMBER_VERIFICATION_FAKE_CALL: {
749 boolean val = NumberVerificationManager.getInstance()
750 .checkIncomingCall(getNextArg());
751 getOutPrintWriter().println(val ? "1" : "0");
752 return 0;
753 }
Hall Liud892bec2018-11-30 14:51:45 -0800754 }
755
756 return -1;
757 }
758
Jack Nudelman644b91a2021-03-12 14:09:48 -0800759 private int handleThermalMitigationCommand() {
760 String arg = getNextArg();
761 String packageName = getNextArg();
762 if (arg == null || packageName == null) {
763 onHelpThermalMitigation();
764 return 0;
765 }
766
767 if (!checkShellUid()) {
768 return -1;
769 }
770
771 switch (arg) {
772 case ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
773 PhoneInterfaceManager.addPackageToThermalMitigationAllowlist(packageName, mContext);
774 return 0;
775 }
776 case DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND: {
777 PhoneInterfaceManager.removePackageFromThermalMitigationAllowlist(packageName,
778 mContext);
779 return 0;
780 }
781 default:
782 onHelpThermalMitigation();
783 }
784
785 return -1;
786
787 }
788
Tyler Gunn92479152021-01-20 16:30:10 -0800789 private int handleD2dCommand() {
790 String arg = getNextArg();
791 if (arg == null) {
792 onHelpD2D();
793 return 0;
794 }
795
796 switch (arg) {
797 case D2D_SEND: {
798 return handleD2dSendCommand();
799 }
Tyler Gunnbabbda02021-02-10 11:05:02 -0800800 case D2D_TRANSPORT: {
801 return handleD2dTransportCommand();
802 }
Tyler Gunn92479152021-01-20 16:30:10 -0800803 }
804
805 return -1;
806 }
807
808 private int handleD2dSendCommand() {
809 PrintWriter errPw = getErrPrintWriter();
Tyler Gunn92479152021-01-20 16:30:10 -0800810 int messageType = -1;
811 int messageValue = -1;
812
Tyler Gunn92479152021-01-20 16:30:10 -0800813 String arg = getNextArg();
814 if (arg == null) {
815 onHelpD2D();
816 return 0;
817 }
818 try {
819 messageType = Integer.parseInt(arg);
820 } catch (NumberFormatException e) {
821 errPw.println("message type must be a valid integer");
822 return -1;
823 }
824
825 arg = getNextArg();
826 if (arg == null) {
827 onHelpD2D();
828 return 0;
829 }
830 try {
831 messageValue = Integer.parseInt(arg);
832 } catch (NumberFormatException e) {
833 errPw.println("message value must be a valid integer");
834 return -1;
835 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -0800836
Tyler Gunn92479152021-01-20 16:30:10 -0800837 try {
838 mInterface.sendDeviceToDeviceMessage(messageType, messageValue);
839 } catch (RemoteException e) {
840 Log.w(LOG_TAG, "d2d send error: " + e.getMessage());
841 errPw.println("Exception: " + e.getMessage());
842 return -1;
843 }
844
845 return 0;
846 }
847
Tyler Gunnbabbda02021-02-10 11:05:02 -0800848 private int handleD2dTransportCommand() {
849 PrintWriter errPw = getErrPrintWriter();
850
851 String arg = getNextArg();
852 if (arg == null) {
853 onHelpD2D();
854 return 0;
855 }
856
857 try {
858 mInterface.setActiveDeviceToDeviceTransport(arg);
859 } catch (RemoteException e) {
860 Log.w(LOG_TAG, "d2d transport error: " + e.getMessage());
861 errPw.println("Exception: " + e.getMessage());
862 return -1;
863 }
864 return 0;
865 }
866
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700867 // ims set-ims-service
868 private int handleImsSetServiceCommand() {
869 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700870 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700871 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800872 List<Integer> featuresList = new ArrayList<>();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700873
874 String opt;
875 while ((opt = getNextOption()) != null) {
876 switch (opt) {
877 case "-s": {
878 try {
879 slotId = Integer.parseInt(getNextArgRequired());
880 } catch (NumberFormatException e) {
881 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
882 return -1;
883 }
884 break;
885 }
886 case "-c": {
887 isCarrierService = true;
888 break;
889 }
890 case "-d": {
891 isCarrierService = false;
892 break;
893 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800894 case "-f": {
895 String featureString = getNextArgRequired();
896 String[] features = featureString.split(",");
897 for (int i = 0; i < features.length; i++) {
898 try {
899 Integer result = Integer.parseInt(features[i]);
900 if (result < ImsFeature.FEATURE_EMERGENCY_MMTEL
901 || result >= ImsFeature.FEATURE_MAX) {
902 errPw.println("ims set-ims-service -f " + result
903 + " is an invalid feature.");
904 return -1;
905 }
906 featuresList.add(result);
907 } catch (NumberFormatException e) {
908 errPw.println("ims set-ims-service -f tried to parse " + features[i]
909 + " as an integer.");
910 return -1;
911 }
912 }
913 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700914 }
915 }
916 // Mandatory param, either -c or -d
917 if (isCarrierService == null) {
918 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
919 return -1;
920 }
921
922 String packageName = getNextArg();
923
924 try {
925 if (packageName == null) {
926 packageName = "";
927 }
Brad Ebinger24c29992019-12-05 13:03:21 -0800928 int[] featureArray = new int[featuresList.size()];
929 for (int i = 0; i < featuresList.size(); i++) {
930 featureArray[i] = featuresList.get(i);
931 }
932 boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
933 featureArray, packageName);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700934 if (VDBG) {
935 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800936 + (isCarrierService ? "-c " : "-d ")
937 + "-f " + featuresList + " "
938 + packageName + ", result=" + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700939 }
940 getOutPrintWriter().println(result);
941 } catch (RemoteException e) {
942 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -0800943 + (isCarrierService ? "-c " : "-d ")
944 + "-f " + featuresList + " "
945 + packageName + ", error" + e.getMessage());
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700946 errPw.println("Exception: " + e.getMessage());
947 return -1;
948 }
949 return 0;
950 }
951
Brad Ebinger999d3302020-11-25 14:31:39 -0800952 // ims clear-ims-service-override
953 private int handleImsClearCarrierServiceCommand() {
954 PrintWriter errPw = getErrPrintWriter();
955 int slotId = getDefaultSlot();
956
957 String opt;
958 while ((opt = getNextOption()) != null) {
959 switch (opt) {
960 case "-s": {
961 try {
962 slotId = Integer.parseInt(getNextArgRequired());
963 } catch (NumberFormatException e) {
964 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
965 return -1;
966 }
967 break;
968 }
969 }
970 }
971
972 try {
973 boolean result = mInterface.clearCarrierImsServiceOverride(slotId);
974 if (VDBG) {
975 Log.v(LOG_TAG, "ims clear-ims-service-override -s " + slotId
976 + ", result=" + result);
977 }
978 getOutPrintWriter().println(result);
979 } catch (RemoteException e) {
980 Log.w(LOG_TAG, "ims clear-ims-service-override -s " + slotId
981 + ", error" + e.getMessage());
982 errPw.println("Exception: " + e.getMessage());
983 return -1;
984 }
985 return 0;
986 }
987
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700988 // ims get-ims-service
989 private int handleImsGetServiceCommand() {
990 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700991 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700992 Boolean isCarrierService = null;
Brad Ebinger24c29992019-12-05 13:03:21 -0800993 Integer featureType = ImsFeature.FEATURE_MMTEL;
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700994
995 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 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
1003 return -1;
1004 }
1005 break;
1006 }
1007 case "-c": {
1008 isCarrierService = true;
1009 break;
1010 }
1011 case "-d": {
1012 isCarrierService = false;
1013 break;
1014 }
Brad Ebinger24c29992019-12-05 13:03:21 -08001015 case "-f": {
1016 try {
1017 featureType = Integer.parseInt(getNextArg());
1018 } catch (NumberFormatException e) {
1019 errPw.println("ims get-ims-service -f requires valid integer as feature.");
1020 return -1;
1021 }
1022 if (featureType < ImsFeature.FEATURE_EMERGENCY_MMTEL
1023 || featureType >= ImsFeature.FEATURE_MAX) {
1024 errPw.println("ims get-ims-service -f invalid feature.");
1025 return -1;
1026 }
1027 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001028 }
1029 }
1030 // Mandatory param, either -c or -d
1031 if (isCarrierService == null) {
Brad Ebinger24c29992019-12-05 13:03:21 -08001032 errPw.println("ims get-ims-service requires either \"-c\" or \"-d\" to be set.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001033 return -1;
1034 }
1035
1036 String result;
1037 try {
Brad Ebinger24c29992019-12-05 13:03:21 -08001038 result = mInterface.getBoundImsServicePackage(slotId, isCarrierService, featureType);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001039 } catch (RemoteException e) {
1040 return -1;
1041 }
1042 if (VDBG) {
1043 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
Brad Ebinger24c29992019-12-05 13:03:21 -08001044 + (isCarrierService ? "-c " : "-d ")
1045 + (featureType != null ? ("-f " + featureType) : "") + " , returned: "
1046 + result);
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001047 }
1048 getOutPrintWriter().println(result);
1049 return 0;
1050 }
1051
1052 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001053 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001054 String opt;
1055 while ((opt = getNextOption()) != null) {
1056 switch (opt) {
1057 case "-s": {
1058 try {
1059 slotId = Integer.parseInt(getNextArgRequired());
1060 } catch (NumberFormatException e) {
1061 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
1062 return -1;
1063 }
1064 break;
1065 }
1066 }
1067 }
1068 try {
1069 mInterface.enableIms(slotId);
1070 } catch (RemoteException e) {
1071 return -1;
1072 }
1073 if (VDBG) {
1074 Log.v(LOG_TAG, "ims enable -s " + slotId);
1075 }
1076 return 0;
1077 }
1078
1079 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001080 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -07001081 String opt;
1082 while ((opt = getNextOption()) != null) {
1083 switch (opt) {
1084 case "-s": {
1085 try {
1086 slotId = Integer.parseInt(getNextArgRequired());
1087 } catch (NumberFormatException e) {
1088 getErrPrintWriter().println(
1089 "ims disable requires an integer as a SLOT_ID.");
1090 return -1;
1091 }
1092 break;
1093 }
1094 }
1095 }
1096 try {
1097 mInterface.disableIms(slotId);
1098 } catch (RemoteException e) {
1099 return -1;
1100 }
1101 if (VDBG) {
1102 Log.v(LOG_TAG, "ims disable -s " + slotId);
1103 }
1104 return 0;
1105 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001106
Tyler Gunn7bcdc742019-10-04 15:56:59 -07001107 private int handleCepChange() {
1108 Log.i(LOG_TAG, "handleCepChange");
1109 String opt = getNextArg();
1110 if (opt == null) {
1111 return -1;
1112 }
1113 boolean isCepEnabled = opt.equals("enable");
1114
1115 try {
1116 mInterface.setCepEnabled(isCepEnabled);
1117 } catch (RemoteException e) {
1118 return -1;
1119 }
1120 return 0;
1121 }
1122
Brad Ebinger0aa2f242018-04-12 09:49:23 -07001123 private int getDefaultSlot() {
1124 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
1125 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
1126 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
1127 // If there is no default, default to slot 0.
1128 slotId = DEFAULT_PHONE_ID;
1129 }
1130 return slotId;
1131 }
sqian2fff4a32018-11-05 14:18:37 -08001132
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001133 // Parse options related to Carrier Config Commands.
1134 private CcOptionParseResult parseCcOptions(String tag, boolean allowOptionPersistent) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001135 PrintWriter errPw = getErrPrintWriter();
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001136 CcOptionParseResult result = new CcOptionParseResult();
1137 result.mSubId = SubscriptionManager.getDefaultSubscriptionId();
1138 result.mPersistent = false;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001139
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001140 String opt;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001141 while ((opt = getNextOption()) != null) {
1142 switch (opt) {
1143 case "-s": {
1144 try {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001145 result.mSubId = slotStringToSubId(tag, getNextArgRequired());
1146 if (!SubscriptionManager.isValidSubscriptionId(result.mSubId)) {
1147 errPw.println(tag + "No valid subscription found.");
1148 return null;
1149 }
1150
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001151 } catch (IllegalArgumentException e) {
1152 // Missing slot id
1153 errPw.println(tag + "SLOT_ID expected after -s.");
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001154 return null;
1155 }
1156 break;
1157 }
1158 case "-p": {
1159 if (allowOptionPersistent) {
1160 result.mPersistent = true;
1161 } else {
1162 errPw.println(tag + "Unexpected option " + opt);
1163 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001164 }
1165 break;
1166 }
1167 default: {
1168 errPw.println(tag + "Unknown option " + opt);
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001169 return null;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001170 }
1171 }
1172 }
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001173 return result;
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001174 }
1175
1176 private int slotStringToSubId(String tag, String slotString) {
1177 int slotId = -1;
1178 try {
1179 slotId = Integer.parseInt(slotString);
1180 } catch (NumberFormatException e) {
Qiong Liuf25799b2020-09-10 10:13:46 +08001181 getErrPrintWriter().println(tag + slotString + " is not a valid number for SLOT_ID.");
1182 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1183 }
1184
1185 if (!SubscriptionManager.isValidPhoneId(slotId)) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001186 getErrPrintWriter().println(tag + slotString + " is not a valid SLOT_ID.");
1187 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1188 }
1189
Qiong Liuf25799b2020-09-10 10:13:46 +08001190 Phone phone = PhoneFactory.getPhone(slotId);
1191 if (phone == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001192 getErrPrintWriter().println(tag + "No subscription found in slot " + slotId + ".");
1193 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1194 }
Qiong Liuf25799b2020-09-10 10:13:46 +08001195 return phone.getSubId();
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001196 }
1197
Hall Liud892bec2018-11-30 14:51:45 -08001198 private boolean checkShellUid() {
Hall Liu2ddfc7e2018-12-06 13:09:45 -08001199 // adb can run as root or as shell, depending on whether the device is rooted.
1200 return Binder.getCallingUid() == Process.SHELL_UID
1201 || Binder.getCallingUid() == Process.ROOT_UID;
Hall Liud892bec2018-11-30 14:51:45 -08001202 }
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001203
1204 private int handleCcCommand() {
1205 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1206 // non user build.
Meng Wangc4f61042019-11-21 10:51:05 -08001207 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001208 getErrPrintWriter().println("cc: Permission denied.");
1209 return -1;
1210 }
1211
1212 String arg = getNextArg();
1213 if (arg == null) {
1214 onHelpCc();
1215 return 0;
1216 }
1217
1218 switch (arg) {
1219 case CC_GET_VALUE: {
1220 return handleCcGetValue();
1221 }
1222 case CC_SET_VALUE: {
1223 return handleCcSetValue();
1224 }
1225 case CC_CLEAR_VALUES: {
1226 return handleCcClearValues();
1227 }
1228 default: {
1229 getErrPrintWriter().println("cc: Unknown argument: " + arg);
1230 }
1231 }
1232 return -1;
1233 }
1234
1235 // cc get-value
1236 private int handleCcGetValue() {
1237 PrintWriter errPw = getErrPrintWriter();
1238 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_GET_VALUE + ": ";
1239 String key = null;
1240
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001241 // Parse all options
1242 CcOptionParseResult options = parseCcOptions(tag, false);
1243 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001244 return -1;
1245 }
1246
1247 // Get bundle containing all carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001248 PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001249 if (bundle == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001250 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001251 return -1;
1252 }
1253
1254 // Get the key.
1255 key = getNextArg();
1256 if (key != null) {
1257 // A key was provided. Verify if it is a valid key
1258 if (!bundle.containsKey(key)) {
1259 errPw.println(tag + key + " is not a valid key.");
1260 return -1;
1261 }
1262
1263 // Print the carrier config value for key.
1264 getOutPrintWriter().println(ccValueToString(key, getType(tag, key, bundle), bundle));
1265 } else {
1266 // No key provided. Show all values.
1267 // Iterate over a sorted list of all carrier config keys and print them.
1268 TreeSet<String> sortedSet = new TreeSet<String>(bundle.keySet());
1269 for (String k : sortedSet) {
1270 getOutPrintWriter().println(ccValueToString(k, getType(tag, k, bundle), bundle));
1271 }
1272 }
1273 return 0;
1274 }
1275
1276 // cc set-value
1277 private int handleCcSetValue() {
1278 PrintWriter errPw = getErrPrintWriter();
1279 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_SET_VALUE + ": ";
1280
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001281 // Parse all options
1282 CcOptionParseResult options = parseCcOptions(tag, true);
1283 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001284 return -1;
1285 }
1286
1287 // Get bundle containing all current carrier configuration values.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001288 PersistableBundle originalValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001289 if (originalValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001290 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001291 return -1;
1292 }
1293
1294 // Get the key.
1295 String key = getNextArg();
1296 if (key == null || key.equals("")) {
1297 errPw.println(tag + "KEY is missing");
1298 return -1;
1299 }
1300
1301 // Verify if the key is valid
1302 if (!originalValues.containsKey(key)) {
1303 errPw.println(tag + key + " is not a valid key.");
1304 return -1;
1305 }
1306
1307 // Remaining arguments is a list of new values. Add them all into an ArrayList.
1308 ArrayList<String> valueList = new ArrayList<String>();
1309 while (peekNextArg() != null) {
1310 valueList.add(getNextArg());
1311 }
1312
1313 // Find the type of the carrier config value
1314 CcType type = getType(tag, key, originalValues);
1315 if (type == CcType.UNKNOWN) {
1316 errPw.println(tag + "ERROR: Not possible to override key with unknown type.");
1317 return -1;
1318 }
1319
1320 // Create an override bundle containing the key and value that should be overriden.
1321 PersistableBundle overrideBundle = getOverrideBundle(tag, type, key, valueList);
1322 if (overrideBundle == null) {
1323 return -1;
1324 }
1325
1326 // Override the value
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001327 mCarrierConfigManager.overrideConfig(options.mSubId, overrideBundle, options.mPersistent);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001328
1329 // Find bundle containing all new carrier configuration values after the override.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001330 PersistableBundle newValues = mCarrierConfigManager.getConfigForSubId(options.mSubId);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001331 if (newValues == null) {
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001332 errPw.println(tag + "No carrier config values found for subId " + options.mSubId + ".");
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001333 return -1;
1334 }
1335
1336 // Print the original and new value.
1337 String originalValueString = ccValueToString(key, type, originalValues);
1338 String newValueString = ccValueToString(key, type, newValues);
1339 getOutPrintWriter().println("Previous value: \n" + originalValueString);
1340 getOutPrintWriter().println("New value: \n" + newValueString);
1341
1342 return 0;
1343 }
1344
1345 // cc clear-values
1346 private int handleCcClearValues() {
1347 PrintWriter errPw = getErrPrintWriter();
1348 String tag = CARRIER_CONFIG_SUBCOMMAND + " " + CC_CLEAR_VALUES + ": ";
1349
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001350 // Parse all options
1351 CcOptionParseResult options = parseCcOptions(tag, false);
1352 if (options == null) {
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001353 return -1;
1354 }
1355
1356 // Clear all values that has previously been set.
Torbjorn Eklund723527a2019-02-13 11:16:25 +01001357 mCarrierConfigManager.overrideConfig(options.mSubId, null, true);
Torbjorn Eklund1050cb02018-11-16 14:05:38 +01001358 getOutPrintWriter()
1359 .println("All previously set carrier config override values has been cleared");
1360 return 0;
1361 }
1362
1363 private CcType getType(String tag, String key, PersistableBundle bundle) {
1364 // Find the type by checking the type of the current value stored in the bundle.
1365 Object value = bundle.get(key);
1366
1367 if (CC_TYPE_MAP.containsKey(key)) {
1368 return CC_TYPE_MAP.get(key);
1369 } else if (value != null) {
1370 if (value instanceof Boolean) {
1371 return CcType.BOOLEAN;
1372 } else if (value instanceof Double) {
1373 return CcType.DOUBLE;
1374 } else if (value instanceof double[]) {
1375 return CcType.DOUBLE_ARRAY;
1376 } else if (value instanceof Integer) {
1377 return CcType.INT;
1378 } else if (value instanceof int[]) {
1379 return CcType.INT_ARRAY;
1380 } else if (value instanceof Long) {
1381 return CcType.LONG;
1382 } else if (value instanceof long[]) {
1383 return CcType.LONG_ARRAY;
1384 } else if (value instanceof String) {
1385 return CcType.STRING;
1386 } else if (value instanceof String[]) {
1387 return CcType.STRING_ARRAY;
1388 }
1389 } else {
1390 // Current value was null and can therefore not be used in order to find the type.
1391 // Check the name of the key to infer the type. This check is not needed for primitive
1392 // data types (boolean, double, int and long), since they can not be null.
1393 if (key.endsWith("double_array")) {
1394 return CcType.DOUBLE_ARRAY;
1395 }
1396 if (key.endsWith("int_array")) {
1397 return CcType.INT_ARRAY;
1398 }
1399 if (key.endsWith("long_array")) {
1400 return CcType.LONG_ARRAY;
1401 }
1402 if (key.endsWith("string")) {
1403 return CcType.STRING;
1404 }
1405 if (key.endsWith("string_array") || key.endsWith("strings")) {
1406 return CcType.STRING_ARRAY;
1407 }
1408 }
1409
1410 // Not possible to infer the type by looking at the current value or the key.
1411 PrintWriter errPw = getErrPrintWriter();
1412 errPw.println(tag + "ERROR: " + key + " has unknown type.");
1413 return CcType.UNKNOWN;
1414 }
1415
1416 private String ccValueToString(String key, CcType type, PersistableBundle bundle) {
1417 String result;
1418 StringBuilder valueString = new StringBuilder();
1419 String typeString = type.toString();
1420 Object value = bundle.get(key);
1421
1422 if (value == null) {
1423 valueString.append("null");
1424 } else {
1425 switch (type) {
1426 case DOUBLE_ARRAY: {
1427 // Format the string representation of the int array as value1 value2......
1428 double[] valueArray = (double[]) value;
1429 for (int i = 0; i < valueArray.length; i++) {
1430 if (i != 0) {
1431 valueString.append(" ");
1432 }
1433 valueString.append(valueArray[i]);
1434 }
1435 break;
1436 }
1437 case INT_ARRAY: {
1438 // Format the string representation of the int array as value1 value2......
1439 int[] valueArray = (int[]) value;
1440 for (int i = 0; i < valueArray.length; i++) {
1441 if (i != 0) {
1442 valueString.append(" ");
1443 }
1444 valueString.append(valueArray[i]);
1445 }
1446 break;
1447 }
1448 case LONG_ARRAY: {
1449 // Format the string representation of the int array as value1 value2......
1450 long[] valueArray = (long[]) value;
1451 for (int i = 0; i < valueArray.length; i++) {
1452 if (i != 0) {
1453 valueString.append(" ");
1454 }
1455 valueString.append(valueArray[i]);
1456 }
1457 break;
1458 }
1459 case STRING: {
1460 valueString.append("\"" + value.toString() + "\"");
1461 break;
1462 }
1463 case STRING_ARRAY: {
1464 // Format the string representation of the string array as "value1" "value2"....
1465 String[] valueArray = (String[]) value;
1466 for (int i = 0; i < valueArray.length; i++) {
1467 if (i != 0) {
1468 valueString.append(" ");
1469 }
1470 if (valueArray[i] != null) {
1471 valueString.append("\"" + valueArray[i] + "\"");
1472 } else {
1473 valueString.append("null");
1474 }
1475 }
1476 break;
1477 }
1478 default: {
1479 valueString.append(value.toString());
1480 }
1481 }
1482 }
1483 return String.format("%-70s %-15s %s", key, typeString, valueString);
1484 }
1485
1486 private PersistableBundle getOverrideBundle(String tag, CcType type, String key,
1487 ArrayList<String> valueList) {
1488 PrintWriter errPw = getErrPrintWriter();
1489 PersistableBundle bundle = new PersistableBundle();
1490
1491 // First verify that a valid number of values has been provided for the type.
1492 switch (type) {
1493 case BOOLEAN:
1494 case DOUBLE:
1495 case INT:
1496 case LONG: {
1497 if (valueList.size() != 1) {
1498 errPw.println(tag + "Expected 1 value for type " + type
1499 + ". Found: " + valueList.size());
1500 return null;
1501 }
1502 break;
1503 }
1504 case STRING: {
1505 if (valueList.size() > 1) {
1506 errPw.println(tag + "Expected 0 or 1 values for type " + type
1507 + ". Found: " + valueList.size());
1508 return null;
1509 }
1510 break;
1511 }
1512 }
1513
1514 // Parse the value according to type and add it to the Bundle.
1515 switch (type) {
1516 case BOOLEAN: {
1517 if ("true".equalsIgnoreCase(valueList.get(0))) {
1518 bundle.putBoolean(key, true);
1519 } else if ("false".equalsIgnoreCase(valueList.get(0))) {
1520 bundle.putBoolean(key, false);
1521 } else {
1522 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1523 return null;
1524 }
1525 break;
1526 }
1527 case DOUBLE: {
1528 try {
1529 bundle.putDouble(key, Double.parseDouble(valueList.get(0)));
1530 } catch (NumberFormatException nfe) {
1531 // Not a valid double
1532 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1533 return null;
1534 }
1535 break;
1536 }
1537 case DOUBLE_ARRAY: {
1538 double[] valueDoubleArray = null;
1539 if (valueList.size() > 0) {
1540 valueDoubleArray = new double[valueList.size()];
1541 for (int i = 0; i < valueList.size(); i++) {
1542 try {
1543 valueDoubleArray[i] = Double.parseDouble(valueList.get(i));
1544 } catch (NumberFormatException nfe) {
1545 // Not a valid double
1546 errPw.println(
1547 tag + "Unable to parse " + valueList.get(i) + " as a double.");
1548 return null;
1549 }
1550 }
1551 }
1552 bundle.putDoubleArray(key, valueDoubleArray);
1553 break;
1554 }
1555 case INT: {
1556 try {
1557 bundle.putInt(key, Integer.parseInt(valueList.get(0)));
1558 } catch (NumberFormatException nfe) {
1559 // Not a valid integer
1560 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as an " + type);
1561 return null;
1562 }
1563 break;
1564 }
1565 case INT_ARRAY: {
1566 int[] valueIntArray = null;
1567 if (valueList.size() > 0) {
1568 valueIntArray = new int[valueList.size()];
1569 for (int i = 0; i < valueList.size(); i++) {
1570 try {
1571 valueIntArray[i] = Integer.parseInt(valueList.get(i));
1572 } catch (NumberFormatException nfe) {
1573 // Not a valid integer
1574 errPw.println(tag
1575 + "Unable to parse " + valueList.get(i) + " as an integer.");
1576 return null;
1577 }
1578 }
1579 }
1580 bundle.putIntArray(key, valueIntArray);
1581 break;
1582 }
1583 case LONG: {
1584 try {
1585 bundle.putLong(key, Long.parseLong(valueList.get(0)));
1586 } catch (NumberFormatException nfe) {
1587 // Not a valid long
1588 errPw.println(tag + "Unable to parse " + valueList.get(0) + " as a " + type);
1589 return null;
1590 }
1591 break;
1592 }
1593 case LONG_ARRAY: {
1594 long[] valueLongArray = null;
1595 if (valueList.size() > 0) {
1596 valueLongArray = new long[valueList.size()];
1597 for (int i = 0; i < valueList.size(); i++) {
1598 try {
1599 valueLongArray[i] = Long.parseLong(valueList.get(i));
1600 } catch (NumberFormatException nfe) {
1601 // Not a valid long
1602 errPw.println(
1603 tag + "Unable to parse " + valueList.get(i) + " as a long");
1604 return null;
1605 }
1606 }
1607 }
1608 bundle.putLongArray(key, valueLongArray);
1609 break;
1610 }
1611 case STRING: {
1612 String value = null;
1613 if (valueList.size() > 0) {
1614 value = valueList.get(0);
1615 }
1616 bundle.putString(key, value);
1617 break;
1618 }
1619 case STRING_ARRAY: {
1620 String[] valueStringArray = null;
1621 if (valueList.size() > 0) {
1622 valueStringArray = new String[valueList.size()];
1623 valueList.toArray(valueStringArray);
1624 }
1625 bundle.putStringArray(key, valueStringArray);
1626 break;
1627 }
1628 }
1629 return bundle;
1630 }
Shuo Qian489d9282020-07-09 11:30:03 -07001631
1632 private int handleEndBlockSuppressionCommand() {
1633 if (!checkShellUid()) {
1634 return -1;
1635 }
1636
1637 if (BlockedNumberContract.SystemContract.getBlockSuppressionStatus(mContext).isSuppressed) {
1638 BlockedNumberContract.SystemContract.endBlockSuppression(mContext);
1639 }
1640 return 0;
1641 }
Hui Wang641e81c2020-10-12 12:14:23 -07001642
Michele Berionne54af4632020-12-28 20:23:16 +00001643 private int handleRestartModemCommand() {
1644 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1645 // non user build.
1646 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1647 getErrPrintWriter().println("RestartModem: Permission denied.");
1648 return -1;
1649 }
1650
1651 boolean result = TelephonyManager.getDefault().rebootRadio();
1652 getOutPrintWriter().println(result);
1653
1654 return result ? 0 : -1;
1655 }
1656
Michele Berionne5e411512020-11-13 02:36:59 +00001657 private int handleUnattendedReboot() {
1658 // Verify that the user is allowed to run the command. Only allowed in rooted device in a
1659 // non user build.
1660 if (Binder.getCallingUid() != Process.ROOT_UID || TelephonyUtils.IS_USER) {
1661 getErrPrintWriter().println("UnattendedReboot: Permission denied.");
1662 return -1;
1663 }
1664
1665 int result = TelephonyManager.getDefault().prepareForUnattendedReboot();
1666 getOutPrintWriter().println("result: " + result);
1667
1668 return result != TelephonyManager.PREPARE_UNATTENDED_REBOOT_ERROR ? 0 : -1;
1669 }
1670
Hui Wang641e81c2020-10-12 12:14:23 -07001671 private int handleGbaCommand() {
1672 String arg = getNextArg();
1673 if (arg == null) {
1674 onHelpGba();
1675 return 0;
1676 }
1677
1678 switch (arg) {
1679 case GBA_SET_SERVICE: {
1680 return handleGbaSetServiceCommand();
1681 }
1682 case GBA_GET_SERVICE: {
1683 return handleGbaGetServiceCommand();
1684 }
1685 case GBA_SET_RELEASE_TIME: {
1686 return handleGbaSetReleaseCommand();
1687 }
1688 case GBA_GET_RELEASE_TIME: {
1689 return handleGbaGetReleaseCommand();
1690 }
1691 }
1692
1693 return -1;
1694 }
1695
1696 private int getSubId(String cmd) {
1697 int slotId = getDefaultSlot();
1698 String opt = getNextOption();
1699 if (opt != null && opt.equals("-s")) {
1700 try {
1701 slotId = Integer.parseInt(getNextArgRequired());
1702 } catch (NumberFormatException e) {
1703 getErrPrintWriter().println(cmd + " requires an integer as a SLOT_ID.");
1704 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
1705 }
1706 }
1707 int[] subIds = SubscriptionManager.getSubId(slotId);
1708 return subIds[0];
1709 }
1710
1711 private int handleGbaSetServiceCommand() {
1712 int subId = getSubId("gba set-service");
1713 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1714 return -1;
1715 }
1716
1717 String packageName = getNextArg();
1718 try {
1719 if (packageName == null) {
1720 packageName = "";
1721 }
1722 boolean result = mInterface.setBoundGbaServiceOverride(subId, packageName);
1723 if (VDBG) {
1724 Log.v(LOG_TAG, "gba set-service -s " + subId + " "
1725 + packageName + ", result=" + result);
1726 }
1727 getOutPrintWriter().println(result);
1728 } catch (RemoteException e) {
1729 Log.w(LOG_TAG, "gba set-service " + subId + " "
1730 + packageName + ", error" + e.getMessage());
1731 getErrPrintWriter().println("Exception: " + e.getMessage());
1732 return -1;
1733 }
1734 return 0;
1735 }
1736
1737 private int handleGbaGetServiceCommand() {
1738 String result;
1739
1740 int subId = getSubId("gba get-service");
1741 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1742 return -1;
1743 }
1744
1745 try {
1746 result = mInterface.getBoundGbaService(subId);
1747 } catch (RemoteException e) {
1748 return -1;
1749 }
1750 if (VDBG) {
1751 Log.v(LOG_TAG, "gba get-service -s " + subId + ", returned: " + result);
1752 }
1753 getOutPrintWriter().println(result);
1754 return 0;
1755 }
1756
1757 private int handleGbaSetReleaseCommand() {
1758 //the release time value could be -1
1759 int subId = getRemainingArgsCount() > 1 ? getSubId("gba set-release")
1760 : SubscriptionManager.getDefaultSubscriptionId();
1761 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1762 return -1;
1763 }
1764
1765 String intervalStr = getNextArg();
1766 if (intervalStr == null) {
1767 return -1;
1768 }
1769
1770 try {
1771 int interval = Integer.parseInt(intervalStr);
1772 boolean result = mInterface.setGbaReleaseTimeOverride(subId, interval);
1773 if (VDBG) {
1774 Log.v(LOG_TAG, "gba set-release -s " + subId + " "
1775 + intervalStr + ", result=" + result);
1776 }
1777 getOutPrintWriter().println(result);
1778 } catch (NumberFormatException | RemoteException e) {
1779 Log.w(LOG_TAG, "gba set-release -s " + subId + " "
1780 + intervalStr + ", error" + e.getMessage());
1781 getErrPrintWriter().println("Exception: " + e.getMessage());
1782 return -1;
1783 }
1784 return 0;
1785 }
1786
1787 private int handleGbaGetReleaseCommand() {
1788 int subId = getSubId("gba get-release");
1789 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1790 return -1;
1791 }
1792
1793 int result = 0;
1794 try {
1795 result = mInterface.getGbaReleaseTime(subId);
1796 } catch (RemoteException e) {
1797 return -1;
1798 }
1799 if (VDBG) {
1800 Log.v(LOG_TAG, "gba get-release -s " + subId + ", returned: " + result);
1801 }
1802 getOutPrintWriter().println(result);
1803 return 0;
1804 }
Hui Wang761a6682020-10-31 05:12:53 +00001805
1806 private int handleSingleRegistrationConfigCommand() {
1807 String arg = getNextArg();
1808 if (arg == null) {
1809 onHelpSrc();
1810 return 0;
1811 }
1812
1813 switch (arg) {
Hui Wangbaaee6a2021-02-19 20:45:36 -08001814 case SRC_SET_TEST_ENABLED: {
1815 return handleSrcSetTestEnabledCommand();
1816 }
1817 case SRC_GET_TEST_ENABLED: {
1818 return handleSrcGetTestEnabledCommand();
1819 }
Hui Wang761a6682020-10-31 05:12:53 +00001820 case SRC_SET_DEVICE_ENABLED: {
1821 return handleSrcSetDeviceEnabledCommand();
1822 }
1823 case SRC_GET_DEVICE_ENABLED: {
1824 return handleSrcGetDeviceEnabledCommand();
1825 }
1826 case SRC_SET_CARRIER_ENABLED: {
1827 return handleSrcSetCarrierEnabledCommand();
1828 }
1829 case SRC_GET_CARRIER_ENABLED: {
1830 return handleSrcGetCarrierEnabledCommand();
1831 }
Hui Wangb647abe2021-02-26 09:33:38 -08001832 case SRC_SET_FEATURE_ENABLED: {
1833 return handleSrcSetFeatureValidationCommand();
1834 }
1835 case SRC_GET_FEATURE_ENABLED: {
1836 return handleSrcGetFeatureValidationCommand();
1837 }
Hui Wang761a6682020-10-31 05:12:53 +00001838 }
1839
1840 return -1;
1841 }
1842
James.cf Linbcdf8b32021-01-14 16:44:13 +08001843 private int handleRcsUceCommand() {
1844 String arg = getNextArg();
1845 if (arg == null) {
Brad Ebinger14d467f2021-02-12 06:18:28 +00001846 onHelpUce();
1847 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001848 }
1849
1850 switch (arg) {
1851 case UCE_REMOVE_EAB_CONTACT:
1852 return handleRemovingEabContactCommand();
calvinpane4a8a1d2021-01-25 13:51:18 +08001853 case UCE_GET_EAB_CONTACT:
1854 return handleGettingEabContactCommand();
James.cf Lin4b784aa2021-01-31 03:25:15 +08001855 case UCE_GET_DEVICE_ENABLED:
1856 return handleUceGetDeviceEnabledCommand();
1857 case UCE_SET_DEVICE_ENABLED:
1858 return handleUceSetDeviceEnabledCommand();
Brad Ebinger14d467f2021-02-12 06:18:28 +00001859 case UCE_OVERRIDE_PUBLISH_CAPS:
1860 return handleUceOverridePublishCaps();
1861 case UCE_GET_LAST_PIDF_XML:
1862 return handleUceGetPidfXml();
James.cf Linbcdf8b32021-01-14 16:44:13 +08001863 }
1864 return -1;
1865 }
1866
1867 private int handleRemovingEabContactCommand() {
1868 int subId = getSubId("uce remove-eab-contact");
1869 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1870 return -1;
1871 }
1872
1873 String phoneNumber = getNextArgRequired();
1874 if (TextUtils.isEmpty(phoneNumber)) {
1875 return -1;
1876 }
1877 int result = 0;
1878 try {
1879 result = mInterface.removeContactFromEab(subId, phoneNumber);
1880 } catch (RemoteException e) {
1881 Log.w(LOG_TAG, "uce remove-eab-contact -s " + subId + ", error " + e.getMessage());
1882 getErrPrintWriter().println("Exception: " + e.getMessage());
1883 return -1;
1884 }
1885
1886 if (VDBG) {
1887 Log.v(LOG_TAG, "uce remove-eab-contact -s " + subId + ", result: " + result);
1888 }
calvinpan293ea1b2021-02-04 17:52:13 +08001889 return 0;
James.cf Linbcdf8b32021-01-14 16:44:13 +08001890 }
1891
calvinpane4a8a1d2021-01-25 13:51:18 +08001892 private int handleGettingEabContactCommand() {
1893 String phoneNumber = getNextArgRequired();
1894 if (TextUtils.isEmpty(phoneNumber)) {
1895 return -1;
1896 }
1897 String result = "";
1898 try {
1899 result = mInterface.getContactFromEab(phoneNumber);
1900
1901 } catch (RemoteException e) {
1902 Log.w(LOG_TAG, "uce get-eab-contact, error " + e.getMessage());
1903 getErrPrintWriter().println("Exception: " + e.getMessage());
1904 return -1;
1905 }
1906
1907 if (VDBG) {
1908 Log.v(LOG_TAG, "uce get-eab-contact, result: " + result);
1909 }
calvinpan293ea1b2021-02-04 17:52:13 +08001910 getOutPrintWriter().println(result);
James.cf Lin4b784aa2021-01-31 03:25:15 +08001911 return 0;
1912 }
1913
1914 private int handleUceGetDeviceEnabledCommand() {
1915 boolean result = false;
1916 try {
1917 result = mInterface.getDeviceUceEnabled();
1918 } catch (RemoteException e) {
1919 Log.w(LOG_TAG, "uce get-device-enabled, error " + e.getMessage());
1920 return -1;
1921 }
1922 if (VDBG) {
1923 Log.v(LOG_TAG, "uce get-device-enabled, returned: " + result);
1924 }
calvinpane4a8a1d2021-01-25 13:51:18 +08001925 getOutPrintWriter().println(result);
1926 return 0;
1927 }
1928
James.cf Lin4b784aa2021-01-31 03:25:15 +08001929 private int handleUceSetDeviceEnabledCommand() {
1930 String enabledStr = getNextArg();
1931 if (TextUtils.isEmpty(enabledStr)) {
1932 return -1;
1933 }
1934
1935 try {
1936 boolean isEnabled = Boolean.parseBoolean(enabledStr);
1937 mInterface.setDeviceUceEnabled(isEnabled);
1938 if (VDBG) {
1939 Log.v(LOG_TAG, "uce set-device-enabled " + enabledStr + ", done");
1940 }
1941 } catch (NumberFormatException | RemoteException e) {
1942 Log.w(LOG_TAG, "uce set-device-enabled " + enabledStr + ", error " + e.getMessage());
1943 getErrPrintWriter().println("Exception: " + e.getMessage());
1944 return -1;
1945 }
1946 return 0;
1947 }
1948
Hui Wangbaaee6a2021-02-19 20:45:36 -08001949 private int handleSrcSetTestEnabledCommand() {
1950 String enabledStr = getNextArg();
1951 if (enabledStr == null) {
1952 return -1;
1953 }
1954
1955 try {
1956 mInterface.setRcsSingleRegistrationTestModeEnabled(Boolean.parseBoolean(enabledStr));
1957 if (VDBG) {
1958 Log.v(LOG_TAG, "src set-test-enabled " + enabledStr + ", done");
1959 }
1960 getOutPrintWriter().println("Done");
1961 } catch (NumberFormatException | RemoteException e) {
1962 Log.w(LOG_TAG, "src set-test-enabled " + enabledStr + ", error" + e.getMessage());
1963 getErrPrintWriter().println("Exception: " + e.getMessage());
1964 return -1;
1965 }
1966 return 0;
1967 }
1968
1969 private int handleSrcGetTestEnabledCommand() {
1970 boolean result = false;
1971 try {
1972 result = mInterface.getRcsSingleRegistrationTestModeEnabled();
1973 } catch (RemoteException e) {
1974 return -1;
1975 }
1976 if (VDBG) {
1977 Log.v(LOG_TAG, "src get-test-enabled, returned: " + result);
1978 }
1979 getOutPrintWriter().println(result);
1980 return 0;
1981 }
1982
Brad Ebinger14d467f2021-02-12 06:18:28 +00001983 private int handleUceOverridePublishCaps() {
1984 int subId = getSubId("uce override-published-caps");
1985 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
1986 return -1;
1987 }
1988 //uce override-published-caps [-s SLOT_ID] add|remove|clear|list [CAPABILITIES]
1989 String operation = getNextArgRequired();
1990 String caps = getNextArg();
1991 if (!"add".equals(operation) && !"remove".equals(operation) && !"clear".equals(operation)
1992 && !"list".equals(operation)) {
1993 getErrPrintWriter().println("Invalid operation: " + operation);
1994 return -1;
1995 }
1996
1997 // add/remove requires capabilities to be specified.
1998 if ((!"clear".equals(operation) && !"list".equals(operation)) && TextUtils.isEmpty(caps)) {
1999 getErrPrintWriter().println("\"" + operation + "\" requires capabilities to be "
2000 + "specified");
2001 return -1;
2002 }
2003
2004 ArraySet<String> capSet = new ArraySet<>();
2005 if (!TextUtils.isEmpty(caps)) {
2006 String[] capArray = caps.split(":");
2007 for (String cap : capArray) {
2008 // Allow unknown tags to be passed in as well.
2009 capSet.addAll(TEST_FEATURE_TAG_MAP.getOrDefault(cap, Collections.singleton(cap)));
2010 }
2011 }
2012
2013 RcsContactUceCapability result = null;
2014 try {
2015 switch (operation) {
2016 case "add":
2017 result = mInterface.addUceRegistrationOverrideShell(subId,
2018 new ArrayList<>(capSet));
2019 break;
2020 case "remove":
2021 result = mInterface.removeUceRegistrationOverrideShell(subId,
2022 new ArrayList<>(capSet));
2023 break;
2024 case "clear":
2025 result = mInterface.clearUceRegistrationOverrideShell(subId);
2026 break;
2027 case "list":
2028 result = mInterface.getLatestRcsContactUceCapabilityShell(subId);
2029 break;
2030 }
2031 } catch (RemoteException e) {
2032 Log.w(LOG_TAG, "uce override-published-caps, error " + e.getMessage());
2033 getErrPrintWriter().println("Exception: " + e.getMessage());
2034 return -1;
2035 } catch (ServiceSpecificException sse) {
2036 // Reconstruct ImsException
2037 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2038 Log.w(LOG_TAG, "uce override-published-caps, error " + imsException);
2039 getErrPrintWriter().println("Exception: " + imsException);
2040 return -1;
2041 }
2042 if (result == null) {
2043 getErrPrintWriter().println("Service not available");
2044 return -1;
2045 }
2046 getOutPrintWriter().println(result);
2047 return 0;
2048 }
2049
2050 private int handleUceGetPidfXml() {
2051 int subId = getSubId("uce get-last-publish-pidf");
2052 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2053 return -1;
2054 }
2055
2056 String result;
2057 try {
2058 result = mInterface.getLastUcePidfXmlShell(subId);
2059 } catch (RemoteException e) {
2060 Log.w(LOG_TAG, "uce get-last-publish-pidf, error " + e.getMessage());
2061 getErrPrintWriter().println("Exception: " + e.getMessage());
2062 return -1;
2063 } catch (ServiceSpecificException sse) {
2064 // Reconstruct ImsException
2065 ImsException imsException = new ImsException(sse.getMessage(), sse.errorCode);
2066 Log.w(LOG_TAG, "uce get-last-publish-pidf error " + imsException);
2067 getErrPrintWriter().println("Exception: " + imsException);
2068 return -1;
2069 }
2070 if (result == null) {
2071 getErrPrintWriter().println("Service not available");
2072 return -1;
2073 }
2074 getOutPrintWriter().println(result);
2075 return 0;
2076 }
2077
Hui Wang761a6682020-10-31 05:12:53 +00002078 private int handleSrcSetDeviceEnabledCommand() {
2079 String enabledStr = getNextArg();
2080 if (enabledStr == null) {
2081 return -1;
2082 }
2083
2084 try {
2085 mInterface.setDeviceSingleRegistrationEnabledOverride(enabledStr);
2086 if (VDBG) {
2087 Log.v(LOG_TAG, "src set-device-enabled " + enabledStr + ", done");
2088 }
2089 getOutPrintWriter().println("Done");
2090 } catch (NumberFormatException | RemoteException e) {
2091 Log.w(LOG_TAG, "src set-device-enabled " + enabledStr + ", error" + e.getMessage());
2092 getErrPrintWriter().println("Exception: " + e.getMessage());
2093 return -1;
2094 }
2095 return 0;
2096 }
2097
2098 private int handleSrcGetDeviceEnabledCommand() {
2099 boolean result = false;
2100 try {
2101 result = mInterface.getDeviceSingleRegistrationEnabled();
2102 } catch (RemoteException e) {
2103 return -1;
2104 }
2105 if (VDBG) {
2106 Log.v(LOG_TAG, "src get-device-enabled, returned: " + result);
2107 }
2108 getOutPrintWriter().println(result);
2109 return 0;
2110 }
2111
2112 private int handleSrcSetCarrierEnabledCommand() {
2113 //the release time value could be -1
2114 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-carrier-enabled")
2115 : SubscriptionManager.getDefaultSubscriptionId();
2116 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2117 return -1;
2118 }
2119
2120 String enabledStr = getNextArg();
2121 if (enabledStr == null) {
2122 return -1;
2123 }
2124
2125 try {
2126 boolean result =
2127 mInterface.setCarrierSingleRegistrationEnabledOverride(subId, enabledStr);
2128 if (VDBG) {
2129 Log.v(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2130 + enabledStr + ", result=" + result);
2131 }
2132 getOutPrintWriter().println(result);
2133 } catch (NumberFormatException | RemoteException e) {
2134 Log.w(LOG_TAG, "src set-carrier-enabled -s " + subId + " "
2135 + enabledStr + ", error" + e.getMessage());
2136 getErrPrintWriter().println("Exception: " + e.getMessage());
2137 return -1;
2138 }
2139 return 0;
2140 }
2141
2142 private int handleSrcGetCarrierEnabledCommand() {
2143 int subId = getSubId("src get-carrier-enabled");
2144 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2145 return -1;
2146 }
2147
2148 boolean result = false;
2149 try {
2150 result = mInterface.getCarrierSingleRegistrationEnabled(subId);
2151 } catch (RemoteException e) {
2152 return -1;
2153 }
2154 if (VDBG) {
2155 Log.v(LOG_TAG, "src get-carrier-enabled -s " + subId + ", returned: " + result);
2156 }
2157 getOutPrintWriter().println(result);
2158 return 0;
2159 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002160
Hui Wangb647abe2021-02-26 09:33:38 -08002161 private int handleSrcSetFeatureValidationCommand() {
2162 //the release time value could be -1
2163 int subId = getRemainingArgsCount() > 1 ? getSubId("src set-feature-validation")
2164 : SubscriptionManager.getDefaultSubscriptionId();
2165 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2166 return -1;
2167 }
2168
2169 String enabledStr = getNextArg();
2170 if (enabledStr == null) {
2171 return -1;
2172 }
2173
2174 try {
2175 boolean result =
2176 mInterface.setImsFeatureValidationOverride(subId, enabledStr);
2177 if (VDBG) {
2178 Log.v(LOG_TAG, "src set-feature-validation -s " + subId + " "
2179 + enabledStr + ", result=" + result);
2180 }
2181 getOutPrintWriter().println(result);
2182 } catch (NumberFormatException | RemoteException e) {
2183 Log.w(LOG_TAG, "src set-feature-validation -s " + subId + " "
2184 + enabledStr + ", error" + e.getMessage());
2185 getErrPrintWriter().println("Exception: " + e.getMessage());
2186 return -1;
2187 }
2188 return 0;
2189 }
2190
2191 private int handleSrcGetFeatureValidationCommand() {
2192 int subId = getSubId("src get-feature-validation");
2193 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
2194 return -1;
2195 }
2196
2197 Boolean result = false;
2198 try {
2199 result = mInterface.getImsFeatureValidationOverride(subId);
2200 } catch (RemoteException e) {
2201 return -1;
2202 }
2203 if (VDBG) {
2204 Log.v(LOG_TAG, "src get-feature-validation -s " + subId + ", returned: " + result);
2205 }
2206 getOutPrintWriter().println(result);
2207 return 0;
2208 }
2209
2210
Hall Liuaa4211e2021-01-20 15:43:39 -08002211 private void onHelpCallComposer() {
2212 PrintWriter pw = getOutPrintWriter();
2213 pw.println("Call composer commands");
2214 pw.println(" callcomposer test-mode enable|disable|query");
2215 pw.println(" Enables or disables test mode for call composer. In test mode, picture");
2216 pw.println(" upload/download from carrier servers is disabled, and operations are");
2217 pw.println(" performed using emulated local files instead.");
2218 pw.println(" callcomposer simulate-outgoing-call [subId] [UUID]");
2219 pw.println(" Simulates an outgoing call being placed with the picture ID as");
2220 pw.println(" the provided UUID. This triggers storage to the call log.");
Hall Liu7917ecf2021-02-23 12:22:31 -08002221 pw.println(" callcomposer user-setting [subId] enable|disable|query");
2222 pw.println(" Enables or disables the user setting for call composer, as set by");
2223 pw.println(" TelephonyManager#setCallComposerStatus.");
Hall Liuaa4211e2021-01-20 15:43:39 -08002224 }
2225
2226 private int handleCallComposerCommand() {
2227 String arg = getNextArg();
2228 if (arg == null) {
2229 onHelpCallComposer();
2230 return 0;
2231 }
2232
2233 mContext.enforceCallingPermission(Manifest.permission.MODIFY_PHONE_STATE,
2234 "MODIFY_PHONE_STATE required for call composer shell cmds");
2235 switch (arg) {
2236 case CALL_COMPOSER_TEST_MODE: {
2237 String enabledStr = getNextArg();
2238 if (ENABLE.equals(enabledStr)) {
2239 CallComposerPictureManager.sTestMode = true;
2240 } else if (DISABLE.equals(enabledStr)) {
2241 CallComposerPictureManager.sTestMode = false;
2242 } else if (QUERY.equals(enabledStr)) {
2243 getOutPrintWriter().println(CallComposerPictureManager.sTestMode);
2244 } else {
2245 onHelpCallComposer();
2246 return 1;
2247 }
2248 break;
2249 }
2250 case CALL_COMPOSER_SIMULATE_CALL: {
2251 int subscriptionId = Integer.valueOf(getNextArg());
2252 String uuidString = getNextArg();
2253 UUID uuid = UUID.fromString(uuidString);
2254 CompletableFuture<Uri> storageUriFuture = new CompletableFuture<>();
2255 Binder.withCleanCallingIdentity(() -> {
2256 CallComposerPictureManager.getInstance(mContext, subscriptionId)
2257 .storeUploadedPictureToCallLog(uuid, storageUriFuture::complete);
2258 });
2259 try {
2260 Uri uri = storageUriFuture.get();
2261 getOutPrintWriter().println(String.valueOf(uri));
2262 } catch (Exception e) {
2263 throw new RuntimeException(e);
2264 }
2265 break;
2266 }
Hall Liu7917ecf2021-02-23 12:22:31 -08002267 case CALL_COMPOSER_USER_SETTING: {
2268 try {
2269 int subscriptionId = Integer.valueOf(getNextArg());
2270 String enabledStr = getNextArg();
2271 if (ENABLE.equals(enabledStr)) {
2272 mInterface.setCallComposerStatus(subscriptionId,
2273 TelephonyManager.CALL_COMPOSER_STATUS_ON);
2274 } else if (DISABLE.equals(enabledStr)) {
2275 mInterface.setCallComposerStatus(subscriptionId,
2276 TelephonyManager.CALL_COMPOSER_STATUS_OFF);
2277 } else if (QUERY.equals(enabledStr)) {
2278 getOutPrintWriter().println(mInterface.getCallComposerStatus(subscriptionId)
2279 == TelephonyManager.CALL_COMPOSER_STATUS_ON);
2280 } else {
2281 onHelpCallComposer();
2282 return 1;
2283 }
2284 } catch (RemoteException e) {
2285 e.printStackTrace(getOutPrintWriter());
2286 return 1;
2287 }
2288 break;
2289 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002290 }
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002291 return 0;
2292 }
Hall Liuaa4211e2021-01-20 15:43:39 -08002293
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002294 private int handleHasCarrierPrivilegesCommand() {
2295 String packageName = getNextArgRequired();
2296
2297 boolean hasCarrierPrivileges;
Nazanin1adf4562021-03-29 15:35:30 -07002298 final long token = Binder.clearCallingIdentity();
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002299 try {
2300 hasCarrierPrivileges =
2301 mInterface.checkCarrierPrivilegesForPackageAnyPhone(packageName)
2302 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
2303 } catch (RemoteException e) {
2304 Log.w(LOG_TAG, HAS_CARRIER_PRIVILEGES_COMMAND + " exception", e);
2305 getErrPrintWriter().println("Exception: " + e.getMessage());
2306 return -1;
Nazanin1adf4562021-03-29 15:35:30 -07002307 } finally {
2308 Binder.restoreCallingIdentity(token);
Hunter Knepshieldb6907bd2021-03-02 13:07:53 -08002309 }
2310
2311 getOutPrintWriter().println(hasCarrierPrivileges);
Hall Liuaa4211e2021-01-20 15:43:39 -08002312 return 0;
2313 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -07002314}