aboutsummaryrefslogtreecommitdiff
path: root/service/java/com/android/server/bluetooth/BluetoothShellCommand.java
diff options
context:
space:
mode:
authorWilliam Escande <wescande@google.com>2022-12-19 17:54:08 -0800
committerCherrypicker Worker <android-build-cherrypicker-worker@google.com>2022-12-20 21:52:58 +0000
commit4ffb8eb23969457b49231a6809e549df7e3333fe (patch)
tree8d4489c0b182b3b13a6da94d0b95007799af9ab5 /service/java/com/android/server/bluetooth/BluetoothShellCommand.java
parentc33fdf19bd24d2b2ffd7b60e120bdf85dd69c8cb (diff)
Add wait-for-state command
Disable and enable are async shell command. This is creating flakyness in test that expect the bluetooth to be already enabled / disabled. Test: atest BluetoothInstrumentationTests Test: atest BluetoothShellCommandTest Test: atest 'BluetoothTest#AdapterEnableDisable' // net_test_bluetooth Fix: 261772749 Tag: #refactor Change-Id: I3ca29dde23a5182ede28eceaf1ac97e4668ab5d5 (cherry picked from commit ca23daa448294ebea1b5cfd421732e85440fe4b9) Merged-In: I3ca29dde23a5182ede28eceaf1ac97e4668ab5d5
Diffstat (limited to 'service/java/com/android/server/bluetooth/BluetoothShellCommand.java')
-rw-r--r--service/java/com/android/server/bluetooth/BluetoothShellCommand.java163
1 files changed, 119 insertions, 44 deletions
diff --git a/service/java/com/android/server/bluetooth/BluetoothShellCommand.java b/service/java/com/android/server/bluetooth/BluetoothShellCommand.java
index 32b88d209f..8beffa4245 100644
--- a/service/java/com/android/server/bluetooth/BluetoothShellCommand.java
+++ b/service/java/com/android/server/bluetooth/BluetoothShellCommand.java
@@ -16,6 +16,9 @@
package com.android.server.bluetooth;
+import static java.util.Objects.requireNonNull;
+
+import android.bluetooth.BluetoothAdapter;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Binder;
@@ -29,7 +32,7 @@ import com.android.modules.utils.BasicShellCommandHandler;
import java.io.PrintWriter;
class BluetoothShellCommand extends BasicShellCommandHandler {
- private static final String TAG = "BluetoothShellCommand";
+ private static final String TAG = BluetoothShellCommand.class.getSimpleName();
private final BluetoothManagerService mManagerService;
private final Context mContext;
@@ -38,49 +41,111 @@ class BluetoothShellCommand extends BasicShellCommandHandler {
final BluetoothCommand[] mBluetoothCommands = {
new Enable(),
new Disable(),
+ new WaitForAdapterState(),
};
@VisibleForTesting
abstract class BluetoothCommand {
- abstract String getName();
- // require root permission by default, can be override in command implementation
+ final boolean mIsPrivileged;
+ final String mName;
+
+ BluetoothCommand(boolean isPrivileged, String name) {
+ mIsPrivileged = isPrivileged;
+ mName = requireNonNull(name, "Command name cannot be null");
+ }
+
+ String getName() {
+ return mName;
+ }
+ boolean isMatch(String cmd) {
+ return mName.equals(cmd);
+ }
boolean isPrivileged() {
- return true;
+ return mIsPrivileged;
}
- abstract int exec(PrintWriter pw) throws RemoteException;
+
+ abstract int exec(String cmd) throws RemoteException;
+ abstract void onHelp(PrintWriter pw);
}
@VisibleForTesting
class Enable extends BluetoothCommand {
- @Override
- String getName() {
- return "enable";
+ Enable() {
+ super(false, "enable");
}
@Override
- boolean isPrivileged() {
- return false;
+ public int exec(String cmd) throws RemoteException {
+ return mManagerService.enable(AttributionSource.myAttributionSource()) ? 0 : -1;
}
@Override
- public int exec(PrintWriter pw) throws RemoteException {
- pw.println("Enabling Bluetooth");
- return mManagerService.enable(AttributionSource.myAttributionSource()) ? 0 : -1;
+ public void onHelp(PrintWriter pw) {
+ pw.println(" " + getName());
+ pw.println(" Enable Bluetooth on this device.");
}
}
@VisibleForTesting
class Disable extends BluetoothCommand {
+ Disable() {
+ super(false, "disable");
+ }
@Override
- String getName() {
- return "disable";
+ public int exec(String cmd) throws RemoteException {
+ return mManagerService.disable(AttributionSource.myAttributionSource(), true) ? 0 : -1;
}
@Override
- boolean isPrivileged() {
- return false;
+ public void onHelp(PrintWriter pw) {
+ pw.println(" " + getName());
+ pw.println(" Disable Bluetooth on this device.");
+ }
+ }
+
+ @VisibleForTesting
+ class WaitForAdapterState extends BluetoothCommand {
+ WaitForAdapterState() {
+ super(false, "wait-for-state");
+ }
+ private int getWaitingState(String in) {
+ if (!in.startsWith(getName() + ":")) return -1;
+ String[] split = in.split(":", 2);
+ if (split.length != 2 || !getName().equals(split[0])) {
+ String msg = getName() + ": Invalid state format: " + in;
+ Log.e(TAG, msg);
+ PrintWriter pw = getErrPrintWriter();
+ pw.println(TAG + ": " + msg);
+ printHelp(pw);
+ throw new IllegalArgumentException();
+ }
+ switch (split[1]) {
+ case "STATE_OFF":
+ return BluetoothAdapter.STATE_OFF;
+ case "STATE_ON":
+ return BluetoothAdapter.STATE_ON;
+ default:
+ String msg = getName() + ": Invalid state value: " + split[1] + ". From: " + in;
+ Log.e(TAG, msg);
+ PrintWriter pw = getErrPrintWriter();
+ pw.println(TAG + ": " + msg);
+ printHelp(pw);
+ throw new IllegalArgumentException();
+ }
}
@Override
- public int exec(PrintWriter pw) throws RemoteException {
- pw.println("Disabling Bluetooth");
- return mManagerService.disable(AttributionSource.myAttributionSource(), true) ? 0 : -1;
+ boolean isMatch(String cmd) {
+ return getWaitingState(cmd) != -1;
+ }
+ @Override
+ public int exec(String cmd) throws RemoteException {
+ int ret = mManagerService.waitForManagerState(getWaitingState(cmd)) ? 0 : -1;
+ Log.d(TAG, cmd + ": Return value is " + ret); // logging as this method can take time
+ return ret;
+ }
+ @Override
+ public void onHelp(PrintWriter pw) {
+ pw.println(" " + getName() + ":<STATE>");
+ pw.println(" Wait until the adapter state is <STATE>."
+ + " <STATE> can be one of STATE_OFF | STATE_ON");
+ pw.println(" Note: This command can timeout and failed");
}
}
@@ -91,40 +156,50 @@ class BluetoothShellCommand extends BasicShellCommandHandler {
@Override
public int onCommand(String cmd) {
- if (cmd == null) {
- return handleDefaultCommands(null);
- }
+ if (cmd == null) return handleDefaultCommands(null);
for (BluetoothCommand bt_cmd : mBluetoothCommands) {
- if (cmd.equals(bt_cmd.getName())) {
- if (bt_cmd.isPrivileged()) {
- final int uid = Binder.getCallingUid();
- if (uid != Process.ROOT_UID) {
- throw new SecurityException("Uid " + uid + " does not have access to "
- + cmd + " bluetooth command (or such command doesn't exist)");
- }
+ if (!bt_cmd.isMatch(cmd)) continue;
+ if (bt_cmd.isPrivileged()) {
+ final int uid = Binder.getCallingUid();
+ if (uid != Process.ROOT_UID) {
+ throw new SecurityException("Uid " + uid + " does not have access to "
+ + cmd + " bluetooth command");
}
- try {
- return bt_cmd.exec(getOutPrintWriter());
- } catch (RemoteException e) {
- Log.w(TAG, cmd + ": error\nException: " + e.getMessage());
- getErrPrintWriter().println(cmd + ": error\nException: " + e.getMessage());
- e.rethrowFromSystemServer();
+ }
+ try {
+ getOutPrintWriter().println(TAG + ": Exec" + cmd);
+ Log.d(TAG, "Exec " + cmd);
+ int ret = bt_cmd.exec(cmd);
+ if (ret == 0) {
+ String msg = cmd + ": Success";
+ Log.d(TAG, msg);
+ getOutPrintWriter().println(msg);
+ } else {
+ String msg = cmd + ": Failed with status=" + ret;
+ Log.e(TAG, msg);
+ getErrPrintWriter().println(TAG + ": " + msg);
}
+ return ret;
+ } catch (RemoteException e) {
+ Log.w(TAG, cmd + ": error\nException: " + e.getMessage());
+ getErrPrintWriter().println(cmd + ": error\nException: " + e.getMessage());
+ e.rethrowFromSystemServer();
}
}
return handleDefaultCommands(cmd);
}
- @Override
- public void onHelp() {
- PrintWriter pw = getOutPrintWriter();
- pw.println("Bluetooth Commands:");
+ private void printHelp(PrintWriter pw) {
+ pw.println("Bluetooth Manager Commands:");
pw.println(" help or -h");
pw.println(" Print this help text.");
- pw.println(" enable");
- pw.println(" Enable Bluetooth on this device.");
- pw.println(" disable");
- pw.println(" Disable Bluetooth on this device.");
+ for (BluetoothCommand bt_cmd : mBluetoothCommands) {
+ bt_cmd.onHelp(pw);
+ }
+ }
+ @Override
+ public void onHelp() {
+ printHelp(getOutPrintWriter());
}
}