blob: dc1e7d1fd61d7e387758d5ddd806412b28beaa3e [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
Hall Liud892bec2018-11-30 14:51:45 -080019import android.os.Binder;
20import android.os.Process;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070021import android.os.RemoteException;
22import android.os.ShellCommand;
sqian2fff4a32018-11-05 14:18:37 -080023import android.os.UserHandle;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070024import android.telephony.SubscriptionManager;
25import android.util.Log;
26
27import com.android.internal.telephony.ITelephony;
28
29import java.io.PrintWriter;
30
31/**
32 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no
33 * permission checks have been done before onCommand was called. Make sure any commands processed
34 * here also contain the appropriate permissions checks.
35 */
36
37public class TelephonyShellCommand extends ShellCommand {
38
39 private static final String LOG_TAG = "TelephonyShellCommand";
40 // Don't commit with this true.
41 private static final boolean VDBG = true;
Brad Ebinger0aa2f242018-04-12 09:49:23 -070042 private static final int DEFAULT_PHONE_ID = 0;
Brad Ebinger4dc095a2018-04-03 15:17:52 -070043
44 private static final String IMS_SUBCOMMAND = "ims";
sqian2fff4a32018-11-05 14:18:37 -080045 private static final String SMS_SUBCOMMAND = "sms";
Hall Liud892bec2018-11-30 14:51:45 -080046 private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify";
47
Brad Ebinger4dc095a2018-04-03 15:17:52 -070048 private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service";
49 private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service";
50 private static final String IMS_ENABLE = "enable";
51 private static final String IMS_DISABLE = "disable";
52
sqian2fff4a32018-11-05 14:18:37 -080053 private static final String SMS_GET_APPS = "get-apps";
54 private static final String SMS_GET_DEFAULT_APP = "get-default-app";
55 private static final String SMS_SET_DEFAULT_APP = "set-default-app";
56
Hall Liud892bec2018-11-30 14:51:45 -080057 private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package";
58
Brad Ebinger4dc095a2018-04-03 15:17:52 -070059 // Take advantage of existing methods that already contain permissions checks when possible.
60 private final ITelephony mInterface;
61
62 public TelephonyShellCommand(ITelephony binder) {
63 mInterface = binder;
64 }
65
66 @Override
67 public int onCommand(String cmd) {
68 if (cmd == null) {
69 return handleDefaultCommands(null);
70 }
71
72 switch (cmd) {
73 case IMS_SUBCOMMAND: {
74 return handleImsCommand();
75 }
sqian2fff4a32018-11-05 14:18:37 -080076 case SMS_SUBCOMMAND: {
77 return handleSmsCommand();
78 }
Hall Liud892bec2018-11-30 14:51:45 -080079 case NUMBER_VERIFICATION_SUBCOMMAND:
80 return handleNumberVerificationCommand();
Brad Ebinger4dc095a2018-04-03 15:17:52 -070081 default: {
82 return handleDefaultCommands(cmd);
83 }
84 }
85 }
86
87 @Override
88 public void onHelp() {
89 PrintWriter pw = getOutPrintWriter();
90 pw.println("Telephony Commands:");
91 pw.println(" help");
92 pw.println(" Print this help text.");
93 pw.println(" ims");
94 pw.println(" IMS Commands.");
sqian2fff4a32018-11-05 14:18:37 -080095 pw.println(" sms");
96 pw.println(" SMS Commands.");
Brad Ebinger4dc095a2018-04-03 15:17:52 -070097 onHelpIms();
sqian2fff4a32018-11-05 14:18:37 -080098 onHelpSms();
Brad Ebinger4dc095a2018-04-03 15:17:52 -070099 }
100
101 private void onHelpIms() {
102 PrintWriter pw = getOutPrintWriter();
103 pw.println("IMS Commands:");
104 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d) PACKAGE_NAME");
105 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
106 pw.println(" ImsService. Options are:");
107 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
108 pw.println(" is specified, it will choose the default voice SIM slot.");
109 pw.println(" -c: Override the ImsService defined in the carrier configuration.");
110 pw.println(" -d: Override the ImsService defined in the device overlay.");
111 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]");
112 pw.println(" Gets the package name of the currently defined ImsService.");
113 pw.println(" Options are:");
114 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option");
115 pw.println(" is specified, it will choose the default voice SIM slot.");
116 pw.println(" -c: The ImsService defined as the carrier configured ImsService.");
117 pw.println(" -c: The ImsService defined as the device default ImsService.");
118 pw.println(" ims enable [-s SLOT_ID]");
119 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot");
120 pw.println(" if none is specified.");
121 pw.println(" ims disable [-s SLOT_ID]");
122 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM");
123 pw.println(" slot if none is specified.");
124 }
125
sqian2fff4a32018-11-05 14:18:37 -0800126 private void onHelpSms() {
127 PrintWriter pw = getOutPrintWriter();
128 pw.println("SMS Commands:");
129 pw.println(" sms get-apps [--user USER_ID]");
130 pw.println(" Print all SMS apps on a user.");
131 pw.println(" sms get-default-app [--user USER_ID]");
132 pw.println(" Get the default SMS app.");
133 pw.println(" sms set-default-app [--user USER_ID] PACKAGE_NAME");
134 pw.println(" Set PACKAGE_NAME as the default SMS app.");
135 }
136
Hall Liud892bec2018-11-30 14:51:45 -0800137
138 private void onHelpNumberVerification() {
139 PrintWriter pw = getOutPrintWriter();
140 pw.println("Number verification commands");
141 pw.println(" numverify override-package PACKAGE_NAME;");
142 pw.println(" Set the authorized package for number verification.");
143 pw.println(" Leave the package name blank to reset.");
144 }
145
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700146 private int handleImsCommand() {
147 String arg = getNextArg();
148 if (arg == null) {
149 onHelpIms();
150 return 0;
151 }
152
153 switch (arg) {
154 case IMS_SET_CARRIER_SERVICE: {
155 return handleImsSetServiceCommand();
156 }
157 case IMS_GET_CARRIER_SERVICE: {
158 return handleImsGetServiceCommand();
159 }
160 case IMS_ENABLE: {
161 return handleEnableIms();
162 }
163 case IMS_DISABLE: {
164 return handleDisableIms();
165 }
166 }
167
168 return -1;
169 }
170
Hall Liud892bec2018-11-30 14:51:45 -0800171 private int handleNumberVerificationCommand() {
172 String arg = getNextArg();
173 if (arg == null) {
174 onHelpNumberVerification();
175 return 0;
176 }
177
178 switch (arg) {
179 case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: {
180 if (!checkShellUid()) {
181 return -1;
182 }
183 NumberVerificationManager.overrideAuthorizedPackage(getNextArg());
184 return 0;
185 }
186 }
187
188 return -1;
189 }
190
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700191 // ims set-ims-service
192 private int handleImsSetServiceCommand() {
193 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700194 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700195 Boolean isCarrierService = null;
196
197 String opt;
198 while ((opt = getNextOption()) != null) {
199 switch (opt) {
200 case "-s": {
201 try {
202 slotId = Integer.parseInt(getNextArgRequired());
203 } catch (NumberFormatException e) {
204 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
205 return -1;
206 }
207 break;
208 }
209 case "-c": {
210 isCarrierService = true;
211 break;
212 }
213 case "-d": {
214 isCarrierService = false;
215 break;
216 }
217 }
218 }
219 // Mandatory param, either -c or -d
220 if (isCarrierService == null) {
221 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
222 return -1;
223 }
224
225 String packageName = getNextArg();
226
227 try {
228 if (packageName == null) {
229 packageName = "";
230 }
231 boolean result = mInterface.setImsService(slotId, isCarrierService, packageName);
232 if (VDBG) {
233 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
234 + (isCarrierService ? "-c " : "-d ") + packageName + ", result=" + result);
235 }
236 getOutPrintWriter().println(result);
237 } catch (RemoteException e) {
238 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
239 + (isCarrierService ? "-c " : "-d ") + packageName + ", error"
240 + e.getMessage());
241 errPw.println("Exception: " + e.getMessage());
242 return -1;
243 }
244 return 0;
245 }
246
247 // ims get-ims-service
248 private int handleImsGetServiceCommand() {
249 PrintWriter errPw = getErrPrintWriter();
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700250 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700251 Boolean isCarrierService = null;
252
253 String opt;
254 while ((opt = getNextOption()) != null) {
255 switch (opt) {
256 case "-s": {
257 try {
258 slotId = Integer.parseInt(getNextArgRequired());
259 } catch (NumberFormatException e) {
260 errPw.println("ims set-ims-service requires an integer as a SLOT_ID.");
261 return -1;
262 }
263 break;
264 }
265 case "-c": {
266 isCarrierService = true;
267 break;
268 }
269 case "-d": {
270 isCarrierService = false;
271 break;
272 }
273 }
274 }
275 // Mandatory param, either -c or -d
276 if (isCarrierService == null) {
277 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set.");
278 return -1;
279 }
280
281 String result;
282 try {
283 result = mInterface.getImsService(slotId, isCarrierService);
284 } catch (RemoteException e) {
285 return -1;
286 }
287 if (VDBG) {
288 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " "
289 + (isCarrierService ? "-c " : "-d ") + ", returned: " + result);
290 }
291 getOutPrintWriter().println(result);
292 return 0;
293 }
294
295 private int handleEnableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700296 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700297 String opt;
298 while ((opt = getNextOption()) != null) {
299 switch (opt) {
300 case "-s": {
301 try {
302 slotId = Integer.parseInt(getNextArgRequired());
303 } catch (NumberFormatException e) {
304 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID.");
305 return -1;
306 }
307 break;
308 }
309 }
310 }
311 try {
312 mInterface.enableIms(slotId);
313 } catch (RemoteException e) {
314 return -1;
315 }
316 if (VDBG) {
317 Log.v(LOG_TAG, "ims enable -s " + slotId);
318 }
319 return 0;
320 }
321
322 private int handleDisableIms() {
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700323 int slotId = getDefaultSlot();
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700324 String opt;
325 while ((opt = getNextOption()) != null) {
326 switch (opt) {
327 case "-s": {
328 try {
329 slotId = Integer.parseInt(getNextArgRequired());
330 } catch (NumberFormatException e) {
331 getErrPrintWriter().println(
332 "ims disable requires an integer as a SLOT_ID.");
333 return -1;
334 }
335 break;
336 }
337 }
338 }
339 try {
340 mInterface.disableIms(slotId);
341 } catch (RemoteException e) {
342 return -1;
343 }
344 if (VDBG) {
345 Log.v(LOG_TAG, "ims disable -s " + slotId);
346 }
347 return 0;
348 }
Brad Ebinger0aa2f242018-04-12 09:49:23 -0700349
350 private int getDefaultSlot() {
351 int slotId = SubscriptionManager.getDefaultVoicePhoneId();
352 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX
353 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) {
354 // If there is no default, default to slot 0.
355 slotId = DEFAULT_PHONE_ID;
356 }
357 return slotId;
358 }
sqian2fff4a32018-11-05 14:18:37 -0800359
360 private int handleSmsCommand() {
361 String arg = getNextArg();
362 if (arg == null) {
363 onHelpSms();
364 return 0;
365 }
366
367 try {
368 switch (arg) {
369 case SMS_GET_APPS: {
370 return handleSmsGetApps();
371 }
372 case SMS_GET_DEFAULT_APP: {
373 return handleSmsGetDefaultApp();
374 }
375 case SMS_SET_DEFAULT_APP: {
376 return handleSmsSetDefaultApp();
377 }
378 default:
379 getErrPrintWriter().println("Unknown command " + arg);
380 }
381 } catch (RemoteException e) {
382 getErrPrintWriter().println("RemoteException: " + e.getMessage());
383 }
384
385 return -1;
386 }
387
388 private int maybeParseUserIdArg() {
389 int userId = UserHandle.USER_SYSTEM;
390 String opt;
391 while ((opt = getNextOption()) != null) {
392 switch (opt) {
393 case "--user": {
394 try {
395 userId = Integer.parseInt(getNextArgRequired());
396 } catch (NumberFormatException e) {
397 getErrPrintWriter().println("Invalid user ID for --user");
398 return -1;
399 }
400 break;
401 }
402 }
403 }
404 return userId;
405 }
406
407 private int handleSmsGetApps() throws RemoteException {
408 final int userId = maybeParseUserIdArg();
409 if (userId < 0) {
410 return -1;
411 }
412
413 for (String packageName : mInterface.getSmsApps(userId)) {
414 getOutPrintWriter().println(packageName);
415 }
416 return 0;
417 }
418
419 private int handleSmsGetDefaultApp() throws RemoteException {
420 final int userId = maybeParseUserIdArg();
421 if (userId < 0) {
422 return -1;
423 }
424
425 getOutPrintWriter().println(mInterface.getDefaultSmsApp(userId));
426 return 0;
427 }
428
429 private int handleSmsSetDefaultApp() throws RemoteException {
430 final int userId = maybeParseUserIdArg();
431 if (userId < 0) {
432 return -1;
433 }
434
435 String packageName = getNextArgRequired();
436 mInterface.setDefaultSmsApp(userId, packageName);
437 getOutPrintWriter().println("SMS app set to " + mInterface.getDefaultSmsApp(userId));
438 return 0;
439 }
Hall Liud892bec2018-11-30 14:51:45 -0800440
441 private boolean checkShellUid() {
442 return Binder.getCallingUid() == Process.SHELL_UID;
443 }
Brad Ebinger4dc095a2018-04-03 15:17:52 -0700444}