| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 1 | /* | 
|  | 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 |  | 
|  | 17 | package com.android.phone; | 
|  | 18 |  | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 19 | import android.os.Binder; | 
|  | 20 | import android.os.Process; | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 21 | import android.os.RemoteException; | 
|  | 22 | import android.os.ShellCommand; | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 23 | import android.os.UserHandle; | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 24 | import android.telephony.SubscriptionManager; | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 25 | import android.telephony.emergency.EmergencyNumber; | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 26 | import android.util.Log; | 
|  | 27 |  | 
|  | 28 | import com.android.internal.telephony.ITelephony; | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 29 | import com.android.internal.telephony.emergency.EmergencyNumberTracker; | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 30 |  | 
|  | 31 | import java.io.PrintWriter; | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 32 | import java.util.ArrayList; | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 33 |  | 
|  | 34 | /** | 
|  | 35 | * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no | 
|  | 36 | * permission checks have been done before onCommand was called. Make sure any commands processed | 
|  | 37 | * here also contain the appropriate permissions checks. | 
|  | 38 | */ | 
|  | 39 |  | 
|  | 40 | public class TelephonyShellCommand extends ShellCommand { | 
|  | 41 |  | 
|  | 42 | private static final String LOG_TAG = "TelephonyShellCommand"; | 
|  | 43 | // Don't commit with this true. | 
|  | 44 | private static final boolean VDBG = true; | 
| Brad Ebinger | 0aa2f24 | 2018-04-12 09:49:23 -0700 | [diff] [blame] | 45 | private static final int DEFAULT_PHONE_ID = 0; | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 46 |  | 
|  | 47 | private static final String IMS_SUBCOMMAND = "ims"; | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 48 | private static final String SMS_SUBCOMMAND = "sms"; | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 49 | private static final String NUMBER_VERIFICATION_SUBCOMMAND = "numverify"; | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 50 | private static final String EMERGENCY_NUMBER_TEST_MODE = "emergency-number-test-mode"; | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 51 |  | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 52 | private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service"; | 
|  | 53 | private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service"; | 
|  | 54 | private static final String IMS_ENABLE = "enable"; | 
|  | 55 | private static final String IMS_DISABLE = "disable"; | 
|  | 56 |  | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 57 | private static final String SMS_GET_APPS = "get-apps"; | 
|  | 58 | private static final String SMS_GET_DEFAULT_APP = "get-default-app"; | 
|  | 59 | private static final String SMS_SET_DEFAULT_APP = "set-default-app"; | 
|  | 60 |  | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 61 | private static final String NUMBER_VERIFICATION_OVERRIDE_PACKAGE = "override-package"; | 
| Hall Liu | ca5af3a | 2018-12-04 16:58:23 -0800 | [diff] [blame] | 62 | private static final String NUMBER_VERIFICATION_FAKE_CALL = "fake-call"; | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 63 |  | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 64 | // Take advantage of existing methods that already contain permissions checks when possible. | 
|  | 65 | private final ITelephony mInterface; | 
|  | 66 |  | 
|  | 67 | public TelephonyShellCommand(ITelephony binder) { | 
|  | 68 | mInterface = binder; | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | @Override | 
|  | 72 | public int onCommand(String cmd) { | 
|  | 73 | if (cmd == null) { | 
|  | 74 | return handleDefaultCommands(null); | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | switch (cmd) { | 
|  | 78 | case IMS_SUBCOMMAND: { | 
|  | 79 | return handleImsCommand(); | 
|  | 80 | } | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 81 | case SMS_SUBCOMMAND: { | 
|  | 82 | return handleSmsCommand(); | 
|  | 83 | } | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 84 | case NUMBER_VERIFICATION_SUBCOMMAND: | 
|  | 85 | return handleNumberVerificationCommand(); | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 86 | case EMERGENCY_NUMBER_TEST_MODE: | 
|  | 87 | return handleEmergencyNumberTestModeCommand(); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 88 | default: { | 
|  | 89 | return handleDefaultCommands(cmd); | 
|  | 90 | } | 
|  | 91 | } | 
|  | 92 | } | 
|  | 93 |  | 
|  | 94 | @Override | 
|  | 95 | public void onHelp() { | 
|  | 96 | PrintWriter pw = getOutPrintWriter(); | 
|  | 97 | pw.println("Telephony Commands:"); | 
|  | 98 | pw.println("  help"); | 
|  | 99 | pw.println("    Print this help text."); | 
|  | 100 | pw.println("  ims"); | 
|  | 101 | pw.println("    IMS Commands."); | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 102 | pw.println("  sms"); | 
|  | 103 | pw.println("    SMS Commands."); | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 104 | pw.println("  emergency-number-test-mode"); | 
|  | 105 | pw.println("    Emergency Number Test Mode Commands."); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 106 | onHelpIms(); | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 107 | onHelpSms(); | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 108 | onHelpEmergencyNumber(); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 109 | } | 
|  | 110 |  | 
|  | 111 | private void onHelpIms() { | 
|  | 112 | PrintWriter pw = getOutPrintWriter(); | 
|  | 113 | pw.println("IMS Commands:"); | 
|  | 114 | pw.println("  ims set-ims-service [-s SLOT_ID] (-c | -d) PACKAGE_NAME"); | 
|  | 115 | pw.println("    Sets the ImsService defined in PACKAGE_NAME to to be the bound"); | 
|  | 116 | pw.println("    ImsService. Options are:"); | 
|  | 117 | pw.println("      -s: the slot ID that the ImsService should be bound for. If no option"); | 
|  | 118 | pw.println("          is specified, it will choose the default voice SIM slot."); | 
|  | 119 | pw.println("      -c: Override the ImsService defined in the carrier configuration."); | 
|  | 120 | pw.println("      -d: Override the ImsService defined in the device overlay."); | 
|  | 121 | pw.println("  ims get-ims-service [-s SLOT_ID] [-c | -d]"); | 
|  | 122 | pw.println("    Gets the package name of the currently defined ImsService."); | 
|  | 123 | pw.println("    Options are:"); | 
|  | 124 | pw.println("      -s: The SIM slot ID for the registered ImsService. If no option"); | 
|  | 125 | pw.println("          is specified, it will choose the default voice SIM slot."); | 
|  | 126 | pw.println("      -c: The ImsService defined as the carrier configured ImsService."); | 
|  | 127 | pw.println("      -c: The ImsService defined as the device default ImsService."); | 
|  | 128 | pw.println("  ims enable [-s SLOT_ID]"); | 
|  | 129 | pw.println("    enables IMS for the SIM slot specified, or for the default voice SIM slot"); | 
|  | 130 | pw.println("    if none is specified."); | 
|  | 131 | pw.println("  ims disable [-s SLOT_ID]"); | 
|  | 132 | pw.println("    disables IMS for the SIM slot specified, or for the default voice SIM"); | 
|  | 133 | pw.println("    slot if none is specified."); | 
|  | 134 | } | 
|  | 135 |  | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 136 | private void onHelpSms() { | 
|  | 137 | PrintWriter pw = getOutPrintWriter(); | 
|  | 138 | pw.println("SMS Commands:"); | 
|  | 139 | pw.println("  sms get-apps [--user USER_ID]"); | 
|  | 140 | pw.println("    Print all SMS apps on a user."); | 
|  | 141 | pw.println("  sms get-default-app [--user USER_ID]"); | 
|  | 142 | pw.println("    Get the default SMS app."); | 
|  | 143 | pw.println("  sms set-default-app [--user USER_ID] PACKAGE_NAME"); | 
|  | 144 | pw.println("    Set PACKAGE_NAME as the default SMS app."); | 
|  | 145 | } | 
|  | 146 |  | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 147 |  | 
|  | 148 | private void onHelpNumberVerification() { | 
|  | 149 | PrintWriter pw = getOutPrintWriter(); | 
|  | 150 | pw.println("Number verification commands"); | 
|  | 151 | pw.println("  numverify override-package PACKAGE_NAME;"); | 
|  | 152 | pw.println("    Set the authorized package for number verification."); | 
|  | 153 | pw.println("    Leave the package name blank to reset."); | 
| Hall Liu | ca5af3a | 2018-12-04 16:58:23 -0800 | [diff] [blame] | 154 | pw.println("  numverify fake-call NUMBER;"); | 
|  | 155 | pw.println("    Fake an incoming call from NUMBER. This is for testing. Output will be"); | 
|  | 156 | pw.println("    1 if the call would have been intercepted, 0 otherwise."); | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 157 | } | 
|  | 158 |  | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 159 | private void onHelpEmergencyNumber() { | 
|  | 160 | PrintWriter pw = getOutPrintWriter(); | 
|  | 161 | pw.println("Emergency Number Test Mode Commands:"); | 
|  | 162 | pw.println("  emergency-number-test-mode "); | 
|  | 163 | pw.println("    Add(-a), Clear(-c), Print (-p) or Remove(-r) the emergency number list in" | 
|  | 164 | + " the test mode"); | 
|  | 165 | pw.println("      -a <emergency number address>: add an emergency number address for the" | 
| sqian | 6321e6d | 2019-03-14 19:45:39 -0700 | [diff] [blame^] | 166 | + " test mode, only allows '0'-'9', '*', '#' or '+'."); | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 167 | pw.println("      -c: clear the emergency number list in the test mode."); | 
|  | 168 | pw.println("      -r <emergency number address>: remove an existing emergency number" | 
| sqian | 6321e6d | 2019-03-14 19:45:39 -0700 | [diff] [blame^] | 169 | + " address added by the test mode, only allows '0'-'9', '*', '#' or '+'."); | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 170 | pw.println("      -p: get the full emergency number list in the test mode."); | 
|  | 171 | } | 
|  | 172 |  | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 173 | private int handleImsCommand() { | 
|  | 174 | String arg = getNextArg(); | 
|  | 175 | if (arg == null) { | 
|  | 176 | onHelpIms(); | 
|  | 177 | return 0; | 
|  | 178 | } | 
|  | 179 |  | 
|  | 180 | switch (arg) { | 
|  | 181 | case IMS_SET_CARRIER_SERVICE: { | 
|  | 182 | return handleImsSetServiceCommand(); | 
|  | 183 | } | 
|  | 184 | case IMS_GET_CARRIER_SERVICE: { | 
|  | 185 | return handleImsGetServiceCommand(); | 
|  | 186 | } | 
|  | 187 | case IMS_ENABLE: { | 
|  | 188 | return handleEnableIms(); | 
|  | 189 | } | 
|  | 190 | case IMS_DISABLE: { | 
|  | 191 | return handleDisableIms(); | 
|  | 192 | } | 
|  | 193 | } | 
|  | 194 |  | 
|  | 195 | return -1; | 
|  | 196 | } | 
|  | 197 |  | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 198 | private int handleEmergencyNumberTestModeCommand() { | 
|  | 199 | PrintWriter errPw = getErrPrintWriter(); | 
|  | 200 | String opt = getNextOption(); | 
|  | 201 | if (opt == null) { | 
|  | 202 | onHelpEmergencyNumber(); | 
|  | 203 | return 0; | 
|  | 204 | } | 
|  | 205 |  | 
|  | 206 | switch (opt) { | 
|  | 207 | case "-a": { | 
|  | 208 | String emergencyNumberCmd = getNextArgRequired(); | 
|  | 209 | if (emergencyNumberCmd == null | 
|  | 210 | || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) { | 
| sqian | 6321e6d | 2019-03-14 19:45:39 -0700 | [diff] [blame^] | 211 | errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs" | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 212 | + " to be specified after -a in the command "); | 
|  | 213 | return -1; | 
|  | 214 | } | 
|  | 215 | try { | 
|  | 216 | mInterface.updateEmergencyNumberListTestMode( | 
|  | 217 | EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE, | 
|  | 218 | new EmergencyNumber(emergencyNumberCmd, "", "", | 
|  | 219 | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED, | 
|  | 220 | new ArrayList<String>(), | 
|  | 221 | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST, | 
|  | 222 | EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN)); | 
|  | 223 | } catch (RemoteException ex) { | 
|  | 224 | Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd | 
|  | 225 | + ", error " + ex.getMessage()); | 
|  | 226 | errPw.println("Exception: " + ex.getMessage()); | 
|  | 227 | return -1; | 
|  | 228 | } | 
|  | 229 | break; | 
|  | 230 | } | 
|  | 231 | case "-c": { | 
|  | 232 | try { | 
|  | 233 | mInterface.updateEmergencyNumberListTestMode( | 
|  | 234 | EmergencyNumberTracker.RESET_EMERGENCY_NUMBER_TEST_MODE, null); | 
|  | 235 | } catch (RemoteException ex) { | 
|  | 236 | Log.w(LOG_TAG, "emergency-number-test-mode -c " + "error " + ex.getMessage()); | 
|  | 237 | errPw.println("Exception: " + ex.getMessage()); | 
|  | 238 | return -1; | 
|  | 239 | } | 
|  | 240 | break; | 
|  | 241 | } | 
|  | 242 | case "-r": { | 
|  | 243 | String emergencyNumberCmd = getNextArgRequired(); | 
|  | 244 | if (emergencyNumberCmd == null | 
|  | 245 | || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) { | 
| sqian | 6321e6d | 2019-03-14 19:45:39 -0700 | [diff] [blame^] | 246 | errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs" | 
| sqian | f4ca7ed | 2019-01-15 18:32:07 -0800 | [diff] [blame] | 247 | + " to be specified after -r in the command "); | 
|  | 248 | return -1; | 
|  | 249 | } | 
|  | 250 | try { | 
|  | 251 | mInterface.updateEmergencyNumberListTestMode( | 
|  | 252 | EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE, | 
|  | 253 | new EmergencyNumber(emergencyNumberCmd, "", "", | 
|  | 254 | EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED, | 
|  | 255 | new ArrayList<String>(), | 
|  | 256 | EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST, | 
|  | 257 | EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN)); | 
|  | 258 | } catch (RemoteException ex) { | 
|  | 259 | Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd | 
|  | 260 | + ", error " + ex.getMessage()); | 
|  | 261 | errPw.println("Exception: " + ex.getMessage()); | 
|  | 262 | return -1; | 
|  | 263 | } | 
|  | 264 | break; | 
|  | 265 | } | 
|  | 266 | case "-p": { | 
|  | 267 | try { | 
|  | 268 | getOutPrintWriter().println(mInterface.getEmergencyNumberListTestMode()); | 
|  | 269 | } catch (RemoteException ex) { | 
|  | 270 | Log.w(LOG_TAG, "emergency-number-test-mode -p " + "error " + ex.getMessage()); | 
|  | 271 | errPw.println("Exception: " + ex.getMessage()); | 
|  | 272 | return -1; | 
|  | 273 | } | 
|  | 274 | break; | 
|  | 275 | } | 
|  | 276 | default: | 
|  | 277 | onHelpEmergencyNumber(); | 
|  | 278 | break; | 
|  | 279 | } | 
|  | 280 | return 0; | 
|  | 281 | } | 
|  | 282 |  | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 283 | private int handleNumberVerificationCommand() { | 
|  | 284 | String arg = getNextArg(); | 
|  | 285 | if (arg == null) { | 
|  | 286 | onHelpNumberVerification(); | 
|  | 287 | return 0; | 
|  | 288 | } | 
|  | 289 |  | 
| Hall Liu | ca5af3a | 2018-12-04 16:58:23 -0800 | [diff] [blame] | 290 | if (!checkShellUid()) { | 
|  | 291 | return -1; | 
|  | 292 | } | 
|  | 293 |  | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 294 | switch (arg) { | 
|  | 295 | case NUMBER_VERIFICATION_OVERRIDE_PACKAGE: { | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 296 | NumberVerificationManager.overrideAuthorizedPackage(getNextArg()); | 
|  | 297 | return 0; | 
|  | 298 | } | 
| Hall Liu | ca5af3a | 2018-12-04 16:58:23 -0800 | [diff] [blame] | 299 | case NUMBER_VERIFICATION_FAKE_CALL: { | 
|  | 300 | boolean val = NumberVerificationManager.getInstance() | 
|  | 301 | .checkIncomingCall(getNextArg()); | 
|  | 302 | getOutPrintWriter().println(val ? "1" : "0"); | 
|  | 303 | return 0; | 
|  | 304 | } | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 305 | } | 
|  | 306 |  | 
|  | 307 | return -1; | 
|  | 308 | } | 
|  | 309 |  | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 310 | // ims set-ims-service | 
|  | 311 | private int handleImsSetServiceCommand() { | 
|  | 312 | PrintWriter errPw = getErrPrintWriter(); | 
| Brad Ebinger | 0aa2f24 | 2018-04-12 09:49:23 -0700 | [diff] [blame] | 313 | int slotId = getDefaultSlot(); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 314 | Boolean isCarrierService = null; | 
|  | 315 |  | 
|  | 316 | String opt; | 
|  | 317 | while ((opt = getNextOption()) != null) { | 
|  | 318 | switch (opt) { | 
|  | 319 | case "-s": { | 
|  | 320 | try { | 
|  | 321 | slotId = Integer.parseInt(getNextArgRequired()); | 
|  | 322 | } catch (NumberFormatException e) { | 
|  | 323 | errPw.println("ims set-ims-service requires an integer as a SLOT_ID."); | 
|  | 324 | return -1; | 
|  | 325 | } | 
|  | 326 | break; | 
|  | 327 | } | 
|  | 328 | case "-c": { | 
|  | 329 | isCarrierService = true; | 
|  | 330 | break; | 
|  | 331 | } | 
|  | 332 | case "-d": { | 
|  | 333 | isCarrierService = false; | 
|  | 334 | break; | 
|  | 335 | } | 
|  | 336 | } | 
|  | 337 | } | 
|  | 338 | // Mandatory param, either -c or -d | 
|  | 339 | if (isCarrierService == null) { | 
|  | 340 | errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set."); | 
|  | 341 | return -1; | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | String packageName = getNextArg(); | 
|  | 345 |  | 
|  | 346 | try { | 
|  | 347 | if (packageName == null) { | 
|  | 348 | packageName = ""; | 
|  | 349 | } | 
|  | 350 | boolean result = mInterface.setImsService(slotId, isCarrierService, packageName); | 
|  | 351 | if (VDBG) { | 
|  | 352 | Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " " | 
|  | 353 | + (isCarrierService ? "-c " : "-d ") + packageName + ", result=" + result); | 
|  | 354 | } | 
|  | 355 | getOutPrintWriter().println(result); | 
|  | 356 | } catch (RemoteException e) { | 
|  | 357 | Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " " | 
|  | 358 | + (isCarrierService ? "-c " : "-d ") + packageName + ", error" | 
|  | 359 | + e.getMessage()); | 
|  | 360 | errPw.println("Exception: " + e.getMessage()); | 
|  | 361 | return -1; | 
|  | 362 | } | 
|  | 363 | return 0; | 
|  | 364 | } | 
|  | 365 |  | 
|  | 366 | // ims get-ims-service | 
|  | 367 | private int handleImsGetServiceCommand() { | 
|  | 368 | PrintWriter errPw = getErrPrintWriter(); | 
| Brad Ebinger | 0aa2f24 | 2018-04-12 09:49:23 -0700 | [diff] [blame] | 369 | int slotId = getDefaultSlot(); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 370 | Boolean isCarrierService = null; | 
|  | 371 |  | 
|  | 372 | String opt; | 
|  | 373 | while ((opt = getNextOption()) != null) { | 
|  | 374 | switch (opt) { | 
|  | 375 | case "-s": { | 
|  | 376 | try { | 
|  | 377 | slotId = Integer.parseInt(getNextArgRequired()); | 
|  | 378 | } catch (NumberFormatException e) { | 
|  | 379 | errPw.println("ims set-ims-service requires an integer as a SLOT_ID."); | 
|  | 380 | return -1; | 
|  | 381 | } | 
|  | 382 | break; | 
|  | 383 | } | 
|  | 384 | case "-c": { | 
|  | 385 | isCarrierService = true; | 
|  | 386 | break; | 
|  | 387 | } | 
|  | 388 | case "-d": { | 
|  | 389 | isCarrierService = false; | 
|  | 390 | break; | 
|  | 391 | } | 
|  | 392 | } | 
|  | 393 | } | 
|  | 394 | // Mandatory param, either -c or -d | 
|  | 395 | if (isCarrierService == null) { | 
|  | 396 | errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set."); | 
|  | 397 | return -1; | 
|  | 398 | } | 
|  | 399 |  | 
|  | 400 | String result; | 
|  | 401 | try { | 
|  | 402 | result = mInterface.getImsService(slotId, isCarrierService); | 
|  | 403 | } catch (RemoteException e) { | 
|  | 404 | return -1; | 
|  | 405 | } | 
|  | 406 | if (VDBG) { | 
|  | 407 | Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " " | 
|  | 408 | + (isCarrierService ? "-c " : "-d ") + ", returned: " + result); | 
|  | 409 | } | 
|  | 410 | getOutPrintWriter().println(result); | 
|  | 411 | return 0; | 
|  | 412 | } | 
|  | 413 |  | 
|  | 414 | private int handleEnableIms() { | 
| Brad Ebinger | 0aa2f24 | 2018-04-12 09:49:23 -0700 | [diff] [blame] | 415 | int slotId = getDefaultSlot(); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 416 | String opt; | 
|  | 417 | while ((opt = getNextOption()) != null) { | 
|  | 418 | switch (opt) { | 
|  | 419 | case "-s": { | 
|  | 420 | try { | 
|  | 421 | slotId = Integer.parseInt(getNextArgRequired()); | 
|  | 422 | } catch (NumberFormatException e) { | 
|  | 423 | getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID."); | 
|  | 424 | return -1; | 
|  | 425 | } | 
|  | 426 | break; | 
|  | 427 | } | 
|  | 428 | } | 
|  | 429 | } | 
|  | 430 | try { | 
|  | 431 | mInterface.enableIms(slotId); | 
|  | 432 | } catch (RemoteException e) { | 
|  | 433 | return -1; | 
|  | 434 | } | 
|  | 435 | if (VDBG) { | 
|  | 436 | Log.v(LOG_TAG, "ims enable -s " + slotId); | 
|  | 437 | } | 
|  | 438 | return 0; | 
|  | 439 | } | 
|  | 440 |  | 
|  | 441 | private int handleDisableIms() { | 
| Brad Ebinger | 0aa2f24 | 2018-04-12 09:49:23 -0700 | [diff] [blame] | 442 | int slotId = getDefaultSlot(); | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 443 | String opt; | 
|  | 444 | while ((opt = getNextOption()) != null) { | 
|  | 445 | switch (opt) { | 
|  | 446 | case "-s": { | 
|  | 447 | try { | 
|  | 448 | slotId = Integer.parseInt(getNextArgRequired()); | 
|  | 449 | } catch (NumberFormatException e) { | 
|  | 450 | getErrPrintWriter().println( | 
|  | 451 | "ims disable requires an integer as a SLOT_ID."); | 
|  | 452 | return -1; | 
|  | 453 | } | 
|  | 454 | break; | 
|  | 455 | } | 
|  | 456 | } | 
|  | 457 | } | 
|  | 458 | try { | 
|  | 459 | mInterface.disableIms(slotId); | 
|  | 460 | } catch (RemoteException e) { | 
|  | 461 | return -1; | 
|  | 462 | } | 
|  | 463 | if (VDBG) { | 
|  | 464 | Log.v(LOG_TAG, "ims disable -s " + slotId); | 
|  | 465 | } | 
|  | 466 | return 0; | 
|  | 467 | } | 
| Brad Ebinger | 0aa2f24 | 2018-04-12 09:49:23 -0700 | [diff] [blame] | 468 |  | 
|  | 469 | private int getDefaultSlot() { | 
|  | 470 | int slotId = SubscriptionManager.getDefaultVoicePhoneId(); | 
|  | 471 | if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX | 
|  | 472 | || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) { | 
|  | 473 | // If there is no default, default to slot 0. | 
|  | 474 | slotId = DEFAULT_PHONE_ID; | 
|  | 475 | } | 
|  | 476 | return slotId; | 
|  | 477 | } | 
| sqian | 2fff4a3 | 2018-11-05 14:18:37 -0800 | [diff] [blame] | 478 |  | 
|  | 479 | private int handleSmsCommand() { | 
|  | 480 | String arg = getNextArg(); | 
|  | 481 | if (arg == null) { | 
|  | 482 | onHelpSms(); | 
|  | 483 | return 0; | 
|  | 484 | } | 
|  | 485 |  | 
|  | 486 | try { | 
|  | 487 | switch (arg) { | 
|  | 488 | case SMS_GET_APPS: { | 
|  | 489 | return handleSmsGetApps(); | 
|  | 490 | } | 
|  | 491 | case SMS_GET_DEFAULT_APP: { | 
|  | 492 | return handleSmsGetDefaultApp(); | 
|  | 493 | } | 
|  | 494 | case SMS_SET_DEFAULT_APP: { | 
|  | 495 | return handleSmsSetDefaultApp(); | 
|  | 496 | } | 
|  | 497 | default: | 
|  | 498 | getErrPrintWriter().println("Unknown command " + arg); | 
|  | 499 | } | 
|  | 500 | } catch (RemoteException e) { | 
|  | 501 | getErrPrintWriter().println("RemoteException: " + e.getMessage()); | 
|  | 502 | } | 
|  | 503 |  | 
|  | 504 | return -1; | 
|  | 505 | } | 
|  | 506 |  | 
|  | 507 | private int maybeParseUserIdArg() { | 
|  | 508 | int userId = UserHandle.USER_SYSTEM; | 
|  | 509 | String opt; | 
|  | 510 | while ((opt = getNextOption()) != null) { | 
|  | 511 | switch (opt) { | 
|  | 512 | case "--user": { | 
|  | 513 | try { | 
|  | 514 | userId = Integer.parseInt(getNextArgRequired()); | 
|  | 515 | } catch (NumberFormatException e) { | 
|  | 516 | getErrPrintWriter().println("Invalid user ID for --user"); | 
|  | 517 | return -1; | 
|  | 518 | } | 
|  | 519 | break; | 
|  | 520 | } | 
|  | 521 | } | 
|  | 522 | } | 
|  | 523 | return userId; | 
|  | 524 | } | 
|  | 525 |  | 
|  | 526 | private int handleSmsGetApps() throws RemoteException { | 
|  | 527 | final int userId = maybeParseUserIdArg(); | 
|  | 528 | if (userId < 0) { | 
|  | 529 | return -1; | 
|  | 530 | } | 
|  | 531 |  | 
|  | 532 | for (String packageName : mInterface.getSmsApps(userId)) { | 
|  | 533 | getOutPrintWriter().println(packageName); | 
|  | 534 | } | 
|  | 535 | return 0; | 
|  | 536 | } | 
|  | 537 |  | 
|  | 538 | private int handleSmsGetDefaultApp() throws RemoteException { | 
|  | 539 | final int userId = maybeParseUserIdArg(); | 
|  | 540 | if (userId < 0) { | 
|  | 541 | return -1; | 
|  | 542 | } | 
|  | 543 |  | 
|  | 544 | getOutPrintWriter().println(mInterface.getDefaultSmsApp(userId)); | 
|  | 545 | return 0; | 
|  | 546 | } | 
|  | 547 |  | 
|  | 548 | private int handleSmsSetDefaultApp() throws RemoteException { | 
|  | 549 | final int userId = maybeParseUserIdArg(); | 
|  | 550 | if (userId < 0) { | 
|  | 551 | return -1; | 
|  | 552 | } | 
|  | 553 |  | 
|  | 554 | String packageName = getNextArgRequired(); | 
|  | 555 | mInterface.setDefaultSmsApp(userId, packageName); | 
|  | 556 | getOutPrintWriter().println("SMS app set to " + mInterface.getDefaultSmsApp(userId)); | 
|  | 557 | return 0; | 
|  | 558 | } | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 559 |  | 
|  | 560 | private boolean checkShellUid() { | 
| Hall Liu | 2ddfc7e | 2018-12-06 13:09:45 -0800 | [diff] [blame] | 561 | // adb can run as root or as shell, depending on whether the device is rooted. | 
|  | 562 | return Binder.getCallingUid() == Process.SHELL_UID | 
|  | 563 | || Binder.getCallingUid() == Process.ROOT_UID; | 
| Hall Liu | d892bec | 2018-11-30 14:51:45 -0800 | [diff] [blame] | 564 | } | 
| Brad Ebinger | 4dc095a | 2018-04-03 15:17:52 -0700 | [diff] [blame] | 565 | } |