blob: fe270a480d83f4d3a40a4f2e782c8cf3e99ecc37 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.commands.telecom;
import android.app.ActivityThread;
import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.IUserManager;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.sysprop.TelephonyProperties;
import android.telecom.Log;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import com.android.internal.os.BaseCommand;
import com.android.internal.telecom.ITelecomService;
import java.io.PrintStream;
public final class Telecom extends BaseCommand {
/**
* Command-line entry point.
*
* @param args The command-line arguments
*/
public static void main(String[] args) {
// Initialize the telephony module.
// TODO: Do it in zygote and RuntimeInit. b/148897549
ActivityThread.initializeMainlineModules();
(new Telecom()).run(args);
}
private static final String COMMAND_SET_PHONE_ACCOUNT_ENABLED = "set-phone-account-enabled";
private static final String COMMAND_SET_PHONE_ACCOUNT_DISABLED = "set-phone-account-disabled";
private static final String COMMAND_REGISTER_PHONE_ACCOUNT = "register-phone-account";
private static final String COMMAND_SET_USER_SELECTED_OUTGOING_PHONE_ACCOUNT =
"set-user-selected-outgoing-phone-account";
private static final String COMMAND_REGISTER_SIM_PHONE_ACCOUNT = "register-sim-phone-account";
private static final String COMMAND_SET_TEST_CALL_REDIRECTION_APP = "set-test-call-redirection-app";
private static final String COMMAND_SET_TEST_CALL_SCREENING_APP = "set-test-call-screening-app";
private static final String COMMAND_ADD_OR_REMOVE_CALL_COMPANION_APP =
"add-or-remove-call-companion-app";
private static final String COMMAND_SET_PHONE_ACCOUNT_SUGGESTION_COMPONENT =
"set-phone-acct-suggestion-component";
private static final String COMMAND_UNREGISTER_PHONE_ACCOUNT = "unregister-phone-account";
private static final String COMMAND_SET_DEFAULT_DIALER = "set-default-dialer";
private static final String COMMAND_GET_DEFAULT_DIALER = "get-default-dialer";
/**
* Change the system dialer package name if a package name was specified,
* Example: adb shell telecom set-system-dialer <PACKAGE>
*
* Restore it to the default if if argument is "default" or no argument is passed.
* Example: adb shell telecom set-system-dialer default
*/
private static final String COMMAND_SET_SYSTEM_DIALER = "set-system-dialer";
private static final String COMMAND_GET_SYSTEM_DIALER = "get-system-dialer";
private static final String COMMAND_WAIT_ON_HANDLERS = "wait-on-handlers";
private static final String COMMAND_SET_SIM_COUNT = "set-sim-count";
private static final String COMMAND_GET_SIM_CONFIG = "get-sim-config";
private static final String COMMAND_GET_MAX_PHONES = "get-max-phones";
private static final String COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_FILTER =
"set-test-emergency-phone-account-package-filter";
private ComponentName mComponent;
private String mAccountId;
private ITelecomService mTelecomService;
private TelephonyManager mTelephonyManager;
private IUserManager mUserManager;
@Override
public void onShowUsage(PrintStream out) {
out.println("usage: telecom [subcommand] [options]\n"
+ "usage: telecom set-phone-account-enabled <COMPONENT> <ID> <USER_SN>\n"
+ "usage: telecom set-phone-account-disabled <COMPONENT> <ID> <USER_SN>\n"
+ "usage: telecom register-phone-account <COMPONENT> <ID> <USER_SN> <LABEL>\n"
+ "usage: telecom register-sim-phone-account [-e] <COMPONENT> <ID> <USER_SN>"
+ " <LABEL>: registers a PhoneAccount with CAPABILITY_SIM_SUBSCRIPTION"
+ " and optionally CAPABILITY_PLACE_EMERGENCY_CALLS if \"-e\" is provided\n"
+ "usage: telecom set-user-selected-outgoing-phone-account [-e] <COMPONENT> <ID> "
+ "<USER_SN>\n"
+ "usage: telecom set-test-call-redirection-app <PACKAGE>\n"
+ "usage: telecom set-test-call-screening-app <PACKAGE>\n"
+ "usage: telecom set-phone-acct-suggestion-component <COMPONENT>\n"
+ "usage: telecom add-or-remove-call-companion-app <PACKAGE> <1/0>\n"
+ "usage: telecom register-sim-phone-account <COMPONENT> <ID> <USER_SN>"
+ " <LABEL> <ADDRESS>\n"
+ "usage: telecom unregister-phone-account <COMPONENT> <ID> <USER_SN>\n"
+ "usage: telecom set-default-dialer <PACKAGE>\n"
+ "usage: telecom get-default-dialer\n"
+ "usage: telecom get-system-dialer\n"
+ "usage: telecom wait-on-handlers\n"
+ "usage: telecom set-sim-count <COUNT>\n"
+ "usage: telecom get-sim-config\n"
+ "usage: telecom get-max-phones\n"
+ "usage: telecom set-emer-phone-account-filter <PACKAGE>\n"
+ "\n"
+ "telecom set-phone-account-enabled: Enables the given phone account, if it has"
+ " already been registered with Telecom.\n"
+ "\n"
+ "telecom set-phone-account-disabled: Disables the given phone account, if it"
+ " has already been registered with telecom.\n"
+ "\n"
+ "telecom set-default-dialer: Sets the override default dialer to the given"
+ " component; this will override whatever the dialer role is set to.\n"
+ "\n"
+ "telecom get-default-dialer: Displays the current default dialer.\n"
+ "\n"
+ "telecom get-system-dialer: Displays the current system dialer.\n"
+ "telecom set-system-dialer: Set the override system dialer to the given"
+ " component. To remove the override, send \"default\"\n"
+ "\n"
+ "telecom wait-on-handlers: Wait until all handlers finish their work.\n"
+ "\n"
+ "telecom set-sim-count: Set num SIMs (2 for DSDS, 1 for single SIM."
+ " This may restart the device.\n"
+ "\n"
+ "telecom get-sim-config: Get the mSIM config string. \"DSDS\" for DSDS mode,"
+ " or \"\" for single SIM\n"
+ "\n"
+ "telecom get-max-phones: Get the max supported phones from the modem.\n"
+ "telecom set-test-emergency-phone-account-package-filter <PACKAGE>: sets a"
+ " package name that will be used for test emergency calls. To clear,"
+ " send an empty package name. Real emergency calls will still be placed"
+ " over Telephony.\n"
);
}
@Override
public void onRun() throws Exception {
mTelecomService = ITelecomService.Stub.asInterface(
ServiceManager.getService(Context.TELECOM_SERVICE));
if (mTelecomService == null) {
Log.w(this, "onRun: Can't access telecom manager.");
showError("Error: Could not access the Telecom Manager. Is the system running?");
return;
}
Looper.prepareMainLooper();
Context context = ActivityThread.systemMain().getSystemContext();
mTelephonyManager = context.getSystemService(TelephonyManager.class);
if (mTelephonyManager == null) {
Log.w(this, "onRun: Can't access telephony service.");
showError("Error: Could not access the Telephony Service. Is the system running?");
return;
}
mUserManager = IUserManager.Stub
.asInterface(ServiceManager.getService(Context.USER_SERVICE));
if (mUserManager == null) {
Log.w(this, "onRun: Can't access user manager.");
showError("Error: Could not access the User Manager. Is the system running?");
return;
}
Log.i(this, "onRun: parsing command.");
String command = nextArgRequired();
switch (command) {
case COMMAND_SET_PHONE_ACCOUNT_ENABLED:
runSetPhoneAccountEnabled(true);
break;
case COMMAND_SET_PHONE_ACCOUNT_DISABLED:
runSetPhoneAccountEnabled(false);
break;
case COMMAND_REGISTER_PHONE_ACCOUNT:
runRegisterPhoneAccount();
break;
case COMMAND_SET_TEST_CALL_REDIRECTION_APP:
runSetTestCallRedirectionApp();
break;
case COMMAND_SET_TEST_CALL_SCREENING_APP:
runSetTestCallScreeningApp();
break;
case COMMAND_ADD_OR_REMOVE_CALL_COMPANION_APP:
runAddOrRemoveCallCompanionApp();
break;
case COMMAND_SET_PHONE_ACCOUNT_SUGGESTION_COMPONENT:
runSetTestPhoneAcctSuggestionComponent();
break;
case COMMAND_REGISTER_SIM_PHONE_ACCOUNT:
runRegisterSimPhoneAccount();
break;
case COMMAND_SET_USER_SELECTED_OUTGOING_PHONE_ACCOUNT:
runSetUserSelectedOutgoingPhoneAccount();
break;
case COMMAND_UNREGISTER_PHONE_ACCOUNT:
runUnregisterPhoneAccount();
break;
case COMMAND_SET_DEFAULT_DIALER:
runSetDefaultDialer();
break;
case COMMAND_GET_DEFAULT_DIALER:
runGetDefaultDialer();
break;
case COMMAND_SET_SYSTEM_DIALER:
runSetSystemDialer();
break;
case COMMAND_GET_SYSTEM_DIALER:
runGetSystemDialer();
break;
case COMMAND_WAIT_ON_HANDLERS:
runWaitOnHandler();
break;
case COMMAND_SET_SIM_COUNT:
runSetSimCount();
break;
case COMMAND_GET_SIM_CONFIG:
runGetSimConfig();
break;
case COMMAND_GET_MAX_PHONES:
runGetMaxPhones();
break;
case COMMAND_SET_TEST_EMERGENCY_PHONE_ACCOUNT_PACKAGE_FILTER:
runSetEmergencyPhoneAccountPackageFilter();
break;
default:
Log.w(this, "onRun: unknown command: %s", command);
throw new IllegalArgumentException ("unknown command '" + command + "'");
}
}
private void runSetPhoneAccountEnabled(boolean enabled) throws RemoteException {
final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs();
final boolean success = mTelecomService.enablePhoneAccount(handle, enabled);
if (success) {
System.out.println("Success - " + handle + (enabled ? " enabled." : " disabled."));
} else {
System.out.println("Error - is " + handle + " a valid PhoneAccount?");
}
}
private void runRegisterPhoneAccount() throws RemoteException {
final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs();
final String label = nextArgRequired();
PhoneAccount account = PhoneAccount.builder(handle, label)
.setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER).build();
mTelecomService.registerPhoneAccount(account);
System.out.println("Success - " + handle + " registered.");
}
private void runRegisterSimPhoneAccount() throws RemoteException {
boolean isEmergencyAccount = false;
String opt;
while ((opt = nextOption()) != null) {
switch (opt) {
case "-e": {
isEmergencyAccount = true;
break;
}
}
}
final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs();
final String label = nextArgRequired();
final String address = nextArgRequired();
int capabilities = PhoneAccount.CAPABILITY_CALL_PROVIDER
| PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION
| (isEmergencyAccount ? PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS : 0);
PhoneAccount account = PhoneAccount.builder(
handle, label)
.setAddress(Uri.parse(address))
.setSubscriptionAddress(Uri.parse(address))
.setCapabilities(capabilities)
.setShortDescription(label)
.addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
.addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
.build();
mTelecomService.registerPhoneAccount(account);
System.out.println("Success - " + handle + " registered.");
}
private void runSetTestCallRedirectionApp() throws RemoteException {
final String packageName = nextArg();
mTelecomService.setTestDefaultCallRedirectionApp(packageName);
}
private void runSetTestCallScreeningApp() throws RemoteException {
final String packageName = nextArg();
mTelecomService.setTestDefaultCallScreeningApp(packageName);
}
private void runAddOrRemoveCallCompanionApp() throws RemoteException {
final String packageName = nextArgRequired();
String isAdded = nextArgRequired();
boolean isAddedBool = "1".equals(isAdded);
mTelecomService.addOrRemoveTestCallCompanionApp(packageName, isAddedBool);
}
private void runSetTestPhoneAcctSuggestionComponent() throws RemoteException {
final String componentName = nextArg();
mTelecomService.setTestPhoneAcctSuggestionComponent(componentName);
}
private void runSetUserSelectedOutgoingPhoneAccount() throws RemoteException {
Log.i(this, "runSetUserSelectedOutgoingPhoneAccount");
final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs();
mTelecomService.setUserSelectedOutgoingPhoneAccount(handle);
System.out.println("Success - " + handle + " set as default outgoing account.");
}
private void runUnregisterPhoneAccount() throws RemoteException {
final PhoneAccountHandle handle = getPhoneAccountHandleFromArgs();
mTelecomService.unregisterPhoneAccount(handle);
System.out.println("Success - " + handle + " unregistered.");
}
private void runSetDefaultDialer() throws RemoteException {
final String packageName = nextArgRequired();
mTelecomService.setTestDefaultDialer(packageName);
System.out.println("Success - " + packageName + " set as override default dialer.");
}
private void runSetSystemDialer() throws RemoteException {
final String flatComponentName = nextArg();
final ComponentName componentName = (flatComponentName.equals("default")
? null : parseComponentName(flatComponentName));
mTelecomService.setSystemDialer(componentName);
System.out.println("Success - " + componentName + " set as override system dialer.");
}
private void runGetDefaultDialer() throws RemoteException {
System.out.println(mTelecomService.getDefaultDialerPackage());
}
private void runGetSystemDialer() throws RemoteException {
System.out.println(mTelecomService.getSystemDialerPackage());
}
private void runWaitOnHandler() throws RemoteException {
}
private void runSetSimCount() throws RemoteException {
if (!callerIsRoot()) {
System.out.println("set-sim-count requires adb root");
return;
}
int numSims = Integer.parseInt(nextArgRequired());
System.out.println("Setting sim count to " + numSims + ". Device may reboot");
mTelephonyManager.switchMultiSimConfig(numSims);
}
/**
* Prints the mSIM config to the console.
* "DSDS" for a phone in DSDS mode
* "" (empty string) for a phone in SS mode
*/
private void runGetSimConfig() throws RemoteException {
System.out.println(TelephonyProperties.multi_sim_config().orElse(""));
}
private void runGetMaxPhones() throws RemoteException {
// how many logical modems can be potentially active simultaneously
System.out.println(mTelephonyManager.getSupportedModemCount());
}
private void runSetEmergencyPhoneAccountPackageFilter() throws RemoteException {
String packageName = mArgs.getNextArg();
if (TextUtils.isEmpty(packageName)) {
mTelecomService.setTestEmergencyPhoneAccountPackageNameFilter(null);
System.out.println("Success - filter cleared");
} else {
mTelecomService.setTestEmergencyPhoneAccountPackageNameFilter(packageName);
System.out.println("Success = filter set to " + packageName);
}
}
private PhoneAccountHandle getPhoneAccountHandleFromArgs() throws RemoteException {
if (TextUtils.isEmpty(mArgs.peekNextArg())) {
return null;
}
final ComponentName component = parseComponentName(nextArgRequired());
final String accountId = nextArgRequired();
final String userSnInStr = nextArgRequired();
UserHandle userHandle;
try {
final int userSn = Integer.parseInt(userSnInStr);
userHandle = UserHandle.of(mUserManager.getUserHandle(userSn));
} catch (NumberFormatException ex) {
Log.w(this, "getPhoneAccountHandleFromArgs - invalid user %s", userSnInStr);
throw new IllegalArgumentException ("Invalid user serial number " + userSnInStr);
}
return new PhoneAccountHandle(component, accountId, userHandle);
}
private boolean callerIsRoot() {
return Process.ROOT_UID == Process.myUid();
}
private ComponentName parseComponentName(String component) {
ComponentName cn = ComponentName.unflattenFromString(component);
if (cn == null) {
throw new IllegalArgumentException ("Invalid component " + component);
}
return cn;
}
}