From e62f703e4c22d54bdedcc595fd58d473cce790be Mon Sep 17 00:00:00 2001 From: rickyniu Date: Tue, 18 Feb 2020 22:17:42 +0800 Subject: Broadcast events for AOA handshake Broadcast intents on below control request Log both the request and response for 51 control request (Get Protocol) Log both the request and response for 52 control request (Identifying information) Log both the request and response for 53 control request (Start accessory mode) bug: 139264039 Test: Check the broadcast intent could be received Change-Id: I7c8db41ee05398200e235cf10dde96ba89b306e8 --- api/system-current.txt | 5 ++ core/java/android/hardware/usb/UsbAccessory.java | 1 - core/java/android/hardware/usb/UsbManager.java | 62 ++++++++++++++ core/res/AndroidManifest.xml | 1 + non-updatable-api/system-current.txt | 5 ++ .../com/android/server/usb/UsbDeviceManager.java | 99 ++++++++++++++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) diff --git a/api/system-current.txt b/api/system-current.txt index e931fe432ba4..1bd28fca0bfe 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3673,8 +3673,13 @@ package android.hardware.usb { method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbGadget(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long); + field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_ACCESSORY_HANDSHAKE = "android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE"; field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED"; field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; + field public static final String EXTRA_ACCESSORY_HANDSHAKE_END = "android.hardware.usb.extra.ACCESSORY_HANDSHAKE_END"; + field public static final String EXTRA_ACCESSORY_START = "android.hardware.usb.extra.ACCESSORY_START"; + field public static final String EXTRA_ACCESSORY_STRING_COUNT = "android.hardware.usb.extra.ACCESSORY_STRING_COUNT"; + field public static final String EXTRA_ACCESSORY_UEVENT_TIME = "android.hardware.usb.extra.ACCESSORY_UEVENT_TIME"; field public static final long FUNCTION_ACCESSORY = 2L; // 0x2L field public static final long FUNCTION_ADB = 1L; // 0x1L field public static final long FUNCTION_AUDIO_SOURCE = 64L; // 0x40L diff --git a/core/java/android/hardware/usb/UsbAccessory.java b/core/java/android/hardware/usb/UsbAccessory.java index a94266b811d5..f4cfc74aa77d 100644 --- a/core/java/android/hardware/usb/UsbAccessory.java +++ b/core/java/android/hardware/usb/UsbAccessory.java @@ -24,7 +24,6 @@ import android.os.Parcelable; import android.os.RemoteException; import com.android.internal.util.Preconditions; -import java.util.Objects; import java.util.Objects; diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index d16f070f7209..ef305e2c1867 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -159,6 +159,22 @@ public class UsbManager { public static final String ACTION_USB_ACCESSORY_DETACHED = "android.hardware.usb.action.USB_ACCESSORY_DETACHED"; + /** + * Broadcast Action: A broadcast for USB accessory handshaking information delivery + * + * This intent is sent when a USB accessory connect attempt + * + *

For more information about communicating with USB accessory handshake, refer to + * AOA developer guide.

+ * + * {@hide} + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + @SystemApi + @RequiresPermission(Manifest.permission.MANAGE_USB) + public static final String ACTION_USB_ACCESSORY_HANDSHAKE = + "android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE"; + /** * Boolean extra indicating whether USB is connected or disconnected. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. @@ -302,6 +318,52 @@ public class UsbManager { */ public static final String EXTRA_ACCESSORY = "accessory"; + /** + * A long extra indicating ms from boot to get get_protocol UEvent + * This is obtained with SystemClock.elapsedRealtime() + * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts. + * + * {@hide} + */ + @SystemApi + public static final String EXTRA_ACCESSORY_UEVENT_TIME = + "android.hardware.usb.extra.ACCESSORY_UEVENT_TIME"; + + /** + * An integer extra indicating numbers of send string during handshake + * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts + * + *

For more information about control request with identifying string information + * between communicating with USB accessory handshake, refer to + * AOA developer guide.

+ * + * {@hide} + */ + @SystemApi + public static final String EXTRA_ACCESSORY_STRING_COUNT = + "android.hardware.usb.extra.ACCESSORY_STRING_COUNT"; + + /** + * Boolean extra indicating whether got start accessory or not + * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts. + * + * {@hide} + */ + @SystemApi + public static final String EXTRA_ACCESSORY_START = + "android.hardware.usb.extra.ACCESSORY_START"; + + /** + * A long extra indicating ms from boot to sent {@link #ACTION_USB_ACCESSORY_HANDSHAKE} + * This is obtained with SystemClock.elapsedRealtime() + * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts. + * + * {@hide} + */ + @SystemApi + public static final String EXTRA_ACCESSORY_HANDSHAKE_END = + "android.hardware.usb.extra.ACCESSORY_HANDSHAKE_END"; + /** * Name of extra added to the {@link android.app.PendingIntent} * passed into {@link #requestPermission(UsbDevice, PendingIntent)} diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e87b82a0fd0f..2276252a4e8e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -263,6 +263,7 @@ + diff --git a/non-updatable-api/system-current.txt b/non-updatable-api/system-current.txt index 53499f8165a2..4a6a0ee92301 100644 --- a/non-updatable-api/system-current.txt +++ b/non-updatable-api/system-current.txt @@ -3613,8 +3613,13 @@ package android.hardware.usb { method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbGadget(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long); + field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_ACCESSORY_HANDSHAKE = "android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE"; field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED"; field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; + field public static final String EXTRA_ACCESSORY_HANDSHAKE_END = "android.hardware.usb.extra.ACCESSORY_HANDSHAKE_END"; + field public static final String EXTRA_ACCESSORY_START = "android.hardware.usb.extra.ACCESSORY_START"; + field public static final String EXTRA_ACCESSORY_STRING_COUNT = "android.hardware.usb.extra.ACCESSORY_STRING_COUNT"; + field public static final String EXTRA_ACCESSORY_UEVENT_TIME = "android.hardware.usb.extra.ACCESSORY_UEVENT_TIME"; field public static final long FUNCTION_ACCESSORY = 2L; // 0x2L field public static final long FUNCTION_ADB = 1L; // 0x1L field public static final long FUNCTION_AUDIO_SOURCE = 64L; // 0x40L diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 7595e3f249ce..57345f1c0e21 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -164,6 +164,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17; private static final int MSG_GADGET_HAL_REGISTERED = 18; private static final int MSG_RESET_USB_GADGET = 19; + private static final int MSG_ACCESSORY_HANDSHAKE_TIMEOUT = 20; + private static final int MSG_INCREASE_SENDSTRING_COUNT = 21; private static final int AUDIO_MODE_SOURCE = 1; @@ -176,6 +178,13 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser // Request is cancelled if host does not configure device within 10 seconds. private static final int ACCESSORY_REQUEST_TIMEOUT = 10 * 1000; + /** + * Timeout for receiving USB accessory request + * Reset when receive next control request + * Broadcast intent if not receive next control request or enter next step. + */ + private static final int ACCESSORY_HANDSHAKE_TIMEOUT = 10 * 1000; + private static final String BOOT_MODE_PROPERTY = "ro.bootmode"; private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv"; @@ -222,8 +231,19 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser String accessory = event.get("ACCESSORY"); if (state != null) { mHandler.updateState(state); + } else if ("GETPROTOCOL".equals(accessory)) { + if (DEBUG) Slog.d(TAG, "got accessory get protocol"); + long elapsedRealtime = SystemClock.elapsedRealtime(); + mHandler.setAccessoryUEventTime(elapsedRealtime); + resetAccessoryHandshakeTimeoutHandler(); + } else if ("SENDSTRING".equals(accessory)) { + if (DEBUG) Slog.d(TAG, "got accessory send string"); + mHandler.sendEmptyMessage(MSG_INCREASE_SENDSTRING_COUNT); + resetAccessoryHandshakeTimeoutHandler(); } else if ("START".equals(accessory)) { if (DEBUG) Slog.d(TAG, "got accessory start"); + mHandler.removeMessages(MSG_ACCESSORY_HANDSHAKE_TIMEOUT); + mHandler.setStartAccessoryTrue(); startAccessoryMode(); } } @@ -395,6 +415,23 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser mHandler.sendEmptyMessage(MSG_UPDATE_USER_RESTRICTIONS); } + /* + * Start the timeout-timer upon receiving "get_protocol" uevent. + * Restart the timer every time if any succeeding uevnet received. + * (Only when USB is under accessory mode) + *

About the details of the related control request and sequence ordering, refer to + * AOA developer guide.

+ */ + private void resetAccessoryHandshakeTimeoutHandler() { + long functions = getCurrentFunctions(); + // some accesories send get_protocol after start accessory + if ((functions & UsbManager.FUNCTION_ACCESSORY) == 0) { + mHandler.removeMessages(MSG_ACCESSORY_HANDSHAKE_TIMEOUT); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_HANDSHAKE_TIMEOUT), + ACCESSORY_HANDSHAKE_TIMEOUT); + } + } + private void startAccessoryMode() { if (!mHasUsbAccessory) return; @@ -416,6 +453,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser if (functions != UsbManager.FUNCTION_NONE) { mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_MODE_ENTER_TIMEOUT), ACCESSORY_REQUEST_TIMEOUT); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_ACCESSORY_HANDSHAKE_TIMEOUT), + ACCESSORY_HANDSHAKE_TIMEOUT); setCurrentFunctions(functions); } } @@ -468,6 +507,15 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private int mMidiCard; private int mMidiDevice; + /** + * mAccessoryConnectionStartTime record the timing of start_accessory + * mSendStringCount count the number of receiving uevent send_string + * mStartAccessory record whether start_accessory is received + */ + private long mAccessoryConnectionStartTime = 0L; + private int mSendStringCount = 0; + private boolean mStartAccessory = false; + private final Context mContext; private final UsbAlsaManager mUsbAlsaManager; private final UsbPermissionManager mPermissionManager; @@ -645,6 +693,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser // defer accessoryAttached if system is not ready if (mBootCompleted) { mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory); + removeMessages(MSG_ACCESSORY_HANDSHAKE_TIMEOUT); + broadcastUsbAccessoryHandshake(); } // else handle in boot completed } else { Slog.e(TAG, "nativeGetAccessoryStrings failed"); @@ -701,6 +751,30 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser return false; } + private void broadcastUsbAccessoryHandshake() { + long elapsedRealtime = SystemClock.elapsedRealtime(); + long accessoryHandShakeEnd = elapsedRealtime; + + // send a sticky broadcast containing USB accessory handshake information + Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_HANDSHAKE) + .putExtra(UsbManager.EXTRA_ACCESSORY_UEVENT_TIME, + mAccessoryConnectionStartTime) + .putExtra(UsbManager.EXTRA_ACCESSORY_STRING_COUNT, + mSendStringCount) + .putExtra(UsbManager.EXTRA_ACCESSORY_START, + mStartAccessory) + .putExtra(UsbManager.EXTRA_ACCESSORY_HANDSHAKE_END, + accessoryHandShakeEnd); + + if (DEBUG) { + Slog.d(TAG, "broadcasting " + intent + " extras: " + intent.getExtras()); + } + + sendStickyBroadcast(intent); + resetUsbAccessoryHandshakeDebuggingInfo(); + accessoryHandShakeEnd = 0L; + } + protected void updateUsbStateBroadcastIfNeeded(long functions) { // send a sticky broadcast containing current USB state Intent intent = new Intent(UsbManager.ACTION_USB_STATE); @@ -998,6 +1072,16 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser } break; } + case MSG_ACCESSORY_HANDSHAKE_TIMEOUT: { + if (DEBUG) { + Slog.v(TAG, "Accessory handshake timeout"); + } + broadcastUsbAccessoryHandshake(); + break; + } + case MSG_INCREASE_SENDSTRING_COUNT: { + mSendStringCount = mSendStringCount + 1; + } } } @@ -1015,6 +1099,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser } if (mCurrentAccessory != null) { mUsbDeviceManager.getCurrentSettings().accessoryAttached(mCurrentAccessory); + broadcastUsbAccessoryHandshake(); } updateUsbNotification(false); @@ -1301,6 +1386,20 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser * Evaluates USB function policies and applies the change accordingly. */ protected abstract void setEnabledFunctions(long functions, boolean forceRestart); + + public void setAccessoryUEventTime(long accessoryConnectionStartTime) { + mAccessoryConnectionStartTime = accessoryConnectionStartTime; + } + + public void setStartAccessoryTrue() { + mStartAccessory = true; + } + + public void resetUsbAccessoryHandshakeDebuggingInfo() { + mAccessoryConnectionStartTime = 0L; + mSendStringCount = 0; + mStartAccessory = false; + } } private static final class UsbHandlerLegacy extends UsbHandler { -- cgit v1.2.3-59-g8ed1b