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 19 import android.os.RemoteException; 20 import android.os.ShellCommand; 21 import android.telephony.SubscriptionManager; 22 import android.util.Log; 23 24 import com.android.internal.telephony.ITelephony; 25 26 import java.io.PrintWriter; 27 28 /** 29 * Takes actions based on the adb commands given by "adb shell cmd phone ...". Be careful, no 30 * permission checks have been done before onCommand was called. Make sure any commands processed 31 * here also contain the appropriate permissions checks. 32 */ 33 34 public class TelephonyShellCommand extends ShellCommand { 35 36 private static final String LOG_TAG = "TelephonyShellCommand"; 37 // Don't commit with this true. 38 private static final boolean VDBG = true; 39 private static final int DEFAULT_PHONE_ID = 0; 40 41 private static final String IMS_SUBCOMMAND = "ims"; 42 private static final String IMS_SET_CARRIER_SERVICE = "set-ims-service"; 43 private static final String IMS_GET_CARRIER_SERVICE = "get-ims-service"; 44 private static final String IMS_ENABLE = "enable"; 45 private static final String IMS_DISABLE = "disable"; 46 47 // Take advantage of existing methods that already contain permissions checks when possible. 48 private final ITelephony mInterface; 49 TelephonyShellCommand(ITelephony binder)50 public TelephonyShellCommand(ITelephony binder) { 51 mInterface = binder; 52 } 53 54 @Override onCommand(String cmd)55 public int onCommand(String cmd) { 56 if (cmd == null) { 57 return handleDefaultCommands(null); 58 } 59 60 switch (cmd) { 61 case IMS_SUBCOMMAND: { 62 return handleImsCommand(); 63 } 64 default: { 65 return handleDefaultCommands(cmd); 66 } 67 } 68 } 69 70 @Override onHelp()71 public void onHelp() { 72 PrintWriter pw = getOutPrintWriter(); 73 pw.println("Telephony Commands:"); 74 pw.println(" help"); 75 pw.println(" Print this help text."); 76 pw.println(" ims"); 77 pw.println(" IMS Commands."); 78 onHelpIms(); 79 } 80 onHelpIms()81 private void onHelpIms() { 82 PrintWriter pw = getOutPrintWriter(); 83 pw.println("IMS Commands:"); 84 pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d) PACKAGE_NAME"); 85 pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound"); 86 pw.println(" ImsService. Options are:"); 87 pw.println(" -s: the slot ID that the ImsService should be bound for. If no option"); 88 pw.println(" is specified, it will choose the default voice SIM slot."); 89 pw.println(" -c: Override the ImsService defined in the carrier configuration."); 90 pw.println(" -d: Override the ImsService defined in the device overlay."); 91 pw.println(" ims get-ims-service [-s SLOT_ID] [-c | -d]"); 92 pw.println(" Gets the package name of the currently defined ImsService."); 93 pw.println(" Options are:"); 94 pw.println(" -s: The SIM slot ID for the registered ImsService. If no option"); 95 pw.println(" is specified, it will choose the default voice SIM slot."); 96 pw.println(" -c: The ImsService defined as the carrier configured ImsService."); 97 pw.println(" -c: The ImsService defined as the device default ImsService."); 98 pw.println(" ims enable [-s SLOT_ID]"); 99 pw.println(" enables IMS for the SIM slot specified, or for the default voice SIM slot"); 100 pw.println(" if none is specified."); 101 pw.println(" ims disable [-s SLOT_ID]"); 102 pw.println(" disables IMS for the SIM slot specified, or for the default voice SIM"); 103 pw.println(" slot if none is specified."); 104 } 105 handleImsCommand()106 private int handleImsCommand() { 107 String arg = getNextArg(); 108 if (arg == null) { 109 onHelpIms(); 110 return 0; 111 } 112 113 switch (arg) { 114 case IMS_SET_CARRIER_SERVICE: { 115 return handleImsSetServiceCommand(); 116 } 117 case IMS_GET_CARRIER_SERVICE: { 118 return handleImsGetServiceCommand(); 119 } 120 case IMS_ENABLE: { 121 return handleEnableIms(); 122 } 123 case IMS_DISABLE: { 124 return handleDisableIms(); 125 } 126 } 127 128 return -1; 129 } 130 131 // ims set-ims-service handleImsSetServiceCommand()132 private int handleImsSetServiceCommand() { 133 PrintWriter errPw = getErrPrintWriter(); 134 int slotId = getDefaultSlot(); 135 Boolean isCarrierService = null; 136 137 String opt; 138 while ((opt = getNextOption()) != null) { 139 switch (opt) { 140 case "-s": { 141 try { 142 slotId = Integer.parseInt(getNextArgRequired()); 143 } catch (NumberFormatException e) { 144 errPw.println("ims set-ims-service requires an integer as a SLOT_ID."); 145 return -1; 146 } 147 break; 148 } 149 case "-c": { 150 isCarrierService = true; 151 break; 152 } 153 case "-d": { 154 isCarrierService = false; 155 break; 156 } 157 } 158 } 159 // Mandatory param, either -c or -d 160 if (isCarrierService == null) { 161 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set."); 162 return -1; 163 } 164 165 String packageName = getNextArg(); 166 167 try { 168 if (packageName == null) { 169 packageName = ""; 170 } 171 boolean result = mInterface.setImsService(slotId, isCarrierService, packageName); 172 if (VDBG) { 173 Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " " 174 + (isCarrierService ? "-c " : "-d ") + packageName + ", result=" + result); 175 } 176 getOutPrintWriter().println(result); 177 } catch (RemoteException e) { 178 Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " " 179 + (isCarrierService ? "-c " : "-d ") + packageName + ", error" 180 + e.getMessage()); 181 errPw.println("Exception: " + e.getMessage()); 182 return -1; 183 } 184 return 0; 185 } 186 187 // ims get-ims-service handleImsGetServiceCommand()188 private int handleImsGetServiceCommand() { 189 PrintWriter errPw = getErrPrintWriter(); 190 int slotId = getDefaultSlot(); 191 Boolean isCarrierService = null; 192 193 String opt; 194 while ((opt = getNextOption()) != null) { 195 switch (opt) { 196 case "-s": { 197 try { 198 slotId = Integer.parseInt(getNextArgRequired()); 199 } catch (NumberFormatException e) { 200 errPw.println("ims set-ims-service requires an integer as a SLOT_ID."); 201 return -1; 202 } 203 break; 204 } 205 case "-c": { 206 isCarrierService = true; 207 break; 208 } 209 case "-d": { 210 isCarrierService = false; 211 break; 212 } 213 } 214 } 215 // Mandatory param, either -c or -d 216 if (isCarrierService == null) { 217 errPw.println("ims set-ims-service requires either \"-c\" or \"-d\" to be set."); 218 return -1; 219 } 220 221 String result; 222 try { 223 result = mInterface.getImsService(slotId, isCarrierService); 224 } catch (RemoteException e) { 225 return -1; 226 } 227 if (VDBG) { 228 Log.v(LOG_TAG, "ims get-ims-service -s " + slotId + " " 229 + (isCarrierService ? "-c " : "-d ") + ", returned: " + result); 230 } 231 getOutPrintWriter().println(result); 232 return 0; 233 } 234 handleEnableIms()235 private int handleEnableIms() { 236 int slotId = getDefaultSlot(); 237 String opt; 238 while ((opt = getNextOption()) != null) { 239 switch (opt) { 240 case "-s": { 241 try { 242 slotId = Integer.parseInt(getNextArgRequired()); 243 } catch (NumberFormatException e) { 244 getErrPrintWriter().println("ims enable requires an integer as a SLOT_ID."); 245 return -1; 246 } 247 break; 248 } 249 } 250 } 251 try { 252 mInterface.enableIms(slotId); 253 } catch (RemoteException e) { 254 return -1; 255 } 256 if (VDBG) { 257 Log.v(LOG_TAG, "ims enable -s " + slotId); 258 } 259 return 0; 260 } 261 handleDisableIms()262 private int handleDisableIms() { 263 int slotId = getDefaultSlot(); 264 String opt; 265 while ((opt = getNextOption()) != null) { 266 switch (opt) { 267 case "-s": { 268 try { 269 slotId = Integer.parseInt(getNextArgRequired()); 270 } catch (NumberFormatException e) { 271 getErrPrintWriter().println( 272 "ims disable requires an integer as a SLOT_ID."); 273 return -1; 274 } 275 break; 276 } 277 } 278 } 279 try { 280 mInterface.disableIms(slotId); 281 } catch (RemoteException e) { 282 return -1; 283 } 284 if (VDBG) { 285 Log.v(LOG_TAG, "ims disable -s " + slotId); 286 } 287 return 0; 288 } 289 getDefaultSlot()290 private int getDefaultSlot() { 291 int slotId = SubscriptionManager.getDefaultVoicePhoneId(); 292 if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX 293 || slotId == SubscriptionManager.DEFAULT_PHONE_INDEX) { 294 // If there is no default, default to slot 0. 295 slotId = DEFAULT_PHONE_ID; 296 } 297 return slotId; 298 } 299 } 300