From 9de2881d5c56135307204f8616937886e3eef79d Mon Sep 17 00:00:00 2001 From: RD Babiera Date: Mon, 19 Dec 2022 23:26:13 +0000 Subject: [PATCH] Usb DisplayPort alt mode frameworks api Adds getDisplayPortAltModeInfo() to UsbPortStatus as well as implementation for DisplayPortAltModeInfo. Adds registerDisplayPortAltModeListener() to UsbManager in addition to DisplayPortAltModeInfoListener and DisplayPortAltModeInfoListener.aidl Adds isAltModeSupported() to UsbPort. Provides necessary pipeline to bubble up information from HAL layer to frameworks level. Adds AltMode support to simulated ports within UsbService. Bug: 253534975 Test: atest CtsUsbManagerTestCases Change-Id: Ie0b302ea79d0870b95f600cf3077023302a04a1d --- core/api/system-current.txt | 28 +++ .../hardware/usb/DisplayPortAltModeInfo.aidl | 19 ++ .../hardware/usb/DisplayPortAltModeInfo.java | 206 ++++++++++++++++++ .../usb/IDisplayPortAltModeInfoListener.aidl | 27 +++ .../android/hardware/usb/IUsbManager.aidl | 12 + .../hardware/usb/ParcelableUsbPort.java | 16 +- .../java/android/hardware/usb/UsbManager.java | 164 ++++++++++++++ core/java/android/hardware/usb/UsbPort.java | 60 ++++- .../android/hardware/usb/UsbPortStatus.java | 139 +++++++++++- .../android/server/usb/UsbPortManager.java | 204 +++++++++++++++-- .../com/android/server/usb/UsbService.java | 84 ++++++- .../server/usb/hal/port/RawPortInfo.java | 36 ++- .../server/usb/hal/port/UsbPortAidl.java | 50 ++++- .../server/usb/hal/port/UsbPortHidl.java | 18 +- 14 files changed, 1017 insertions(+), 46 deletions(-) create mode 100644 core/java/android/hardware/usb/DisplayPortAltModeInfo.aidl create mode 100644 core/java/android/hardware/usb/DisplayPortAltModeInfo.java create mode 100644 core/java/android/hardware/usb/IDisplayPortAltModeInfoListener.aidl diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 6d42bb8676f6b..ba25cdb968acb 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -5766,6 +5766,19 @@ package android.hardware.soundtrigger { package android.hardware.usb { + public final class DisplayPortAltModeInfo implements android.os.Parcelable { + method public int describeContents(); + method public int getCableStatus(); + method public int getNumberOfLanes(); + method public int getPartnerSinkStatus(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator CREATOR; + field public static final int DISPLAYPORT_ALT_MODE_STATUS_CAPABLE = 2; // 0x2 + field public static final int DISPLAYPORT_ALT_MODE_STATUS_ENABLED = 3; // 0x3 + field public static final int DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE = 1; // 0x1 + field public static final int DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN = 0; // 0x0 + } + public class UsbDeviceConnection { method public boolean resetDevice(); } @@ -5774,8 +5787,10 @@ package android.hardware.usb { method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions(); method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List getPorts(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String); + method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean registerDisplayPortAltModeInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.usb.UsbManager.DisplayPortAltModeInfoListener); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbGadget(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long); + method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void unregisterDisplayPortAltModeInfoListener(@NonNull android.hardware.usb.UsbManager.DisplayPortAltModeInfoListener); 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 @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_COMPLIANCE_CHANGED = "android.hardware.usb.action.USB_PORT_COMPLIANCE_CHANGED"; @@ -5799,11 +5814,16 @@ package android.hardware.usb { field public static final String USB_FUNCTION_RNDIS = "rndis"; } + public static interface UsbManager.DisplayPortAltModeInfoListener { + method public void onDisplayPortAltModeInfoChanged(@NonNull String, @NonNull android.hardware.usb.DisplayPortAltModeInfo); + } + public final class UsbPort { method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableLimitPowerTransfer(boolean); method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbData(boolean); method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbDataWhileDocked(); method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus(); + method public boolean isAltModeSupported(int); method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbPort(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int); method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean supportsComplianceWarnings(); @@ -5823,6 +5843,7 @@ package android.hardware.usb { field public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_OTHER = 5; // 0x5 field public static final int ENABLE_USB_DATA_WHILE_DOCKED_ERROR_PORT_MISMATCH = 3; // 0x3 field public static final int ENABLE_USB_DATA_WHILE_DOCKED_SUCCESS = 0; // 0x0 + field public static final int FLAG_ALT_MODE_TYPE_DISPLAYPORT = 1; // 0x1 field public static final int RESET_USB_PORT_ERROR_INTERNAL = 1; // 0x1 field public static final int RESET_USB_PORT_ERROR_NOT_SUPPORTED = 2; // 0x2 field public static final int RESET_USB_PORT_ERROR_OTHER = 4; // 0x4 @@ -5836,6 +5857,8 @@ package android.hardware.usb { method public int getCurrentDataRole(); method public int getCurrentMode(); method public int getCurrentPowerRole(); + method @Nullable public android.hardware.usb.DisplayPortAltModeInfo getDisplayPortAltModeInfo(); + method public int getPlugState(); method public int getPowerBrickConnectionStatus(); method public int getSupportedRoleCombinations(); method public int getUsbDataStatus(); @@ -5865,6 +5888,11 @@ package android.hardware.usb { field public static final int MODE_DFP = 2; // 0x2 field public static final int MODE_NONE = 0; // 0x0 field public static final int MODE_UFP = 1; // 0x1 + field public static final int PLUG_STATE_PLUGGED_ORIENTATION_FLIPPED = 4; // 0x4 + field public static final int PLUG_STATE_PLUGGED_ORIENTATION_NORMAL = 3; // 0x3 + field public static final int PLUG_STATE_PLUGGED_ORIENTATION_UNKNOWN = 2; // 0x2 + field public static final int PLUG_STATE_UNKNOWN = 0; // 0x0 + field public static final int PLUG_STATE_UNPLUGGED = 1; // 0x1 field public static final int POWER_BRICK_STATUS_CONNECTED = 1; // 0x1 field public static final int POWER_BRICK_STATUS_DISCONNECTED = 2; // 0x2 field public static final int POWER_BRICK_STATUS_UNKNOWN = 0; // 0x0 diff --git a/core/java/android/hardware/usb/DisplayPortAltModeInfo.aidl b/core/java/android/hardware/usb/DisplayPortAltModeInfo.aidl new file mode 100644 index 0000000000000..14986d0de6bc2 --- /dev/null +++ b/core/java/android/hardware/usb/DisplayPortAltModeInfo.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2022 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 android.hardware.usb; + +parcelable DisplayPortAltModeInfo; \ No newline at end of file diff --git a/core/java/android/hardware/usb/DisplayPortAltModeInfo.java b/core/java/android/hardware/usb/DisplayPortAltModeInfo.java new file mode 100644 index 0000000000000..febc643339930 --- /dev/null +++ b/core/java/android/hardware/usb/DisplayPortAltModeInfo.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2022 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 android.hardware.usb; + +import android.Manifest; +import android.annotation.CheckResult; +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.RequiresPermission; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** + * Holds information related to DisplayPort Alt Mode statuses + * + * @hide + */ +@SystemApi +public final class DisplayPortAltModeInfo implements Parcelable { + private final @DisplayPortAltModeStatus int mPartnerSinkStatus; + private final @DisplayPortAltModeStatus int mCableStatus; + private final int mNumLanes; + + /** + * Port Partners: + * The port partner status is currently unknown for one of the following reasons: + *
    + *
  • No port partner is connected to the device + *
  • The USB Power Delivery Discover Identity command has not been issued to the port + * partner via SOP messaging. + *
+ *

+ * Cables: + * The cable’s capabilities are not yet known to the device, or no cable is plugged in. + */ + public static final int DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN = 0; + + /** + * Port Partners: + * The current port partner does not list DisplayPort as one of its Alt Modes, or does not list + * the capability to act as a DisplayPort Source or Sink device, or a compatible configuration + * could not be established. + *

+ * Cables: + * The cable/adapter’s capabilities do not list DisplayPort as one of its Alt Modes, or a + * compatible configuration could not be established. + */ + public static final int DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE = 1; + + /** + * Port Partners: + * The current port partner lists compatible DisplayPort capabilities with the device, however + * may not yet have entered DisplayPort Alt Mode or has configured its port for data + * transmission. + *

+ * Cables: + * The Type-C cable/adapter’s capabilities have been discovered and list DisplayPort Alt Mode + * as one of its capabilities, however may not yet have entered DisplayPort Alt Mode or has been + * configured for data transmission. + */ + public static final int DISPLAYPORT_ALT_MODE_STATUS_CAPABLE = 2; + + /** + * Port Partners: + * The port partner and device are both configured for DisplayPort Alt Mode. + *

+ * Cables: + * The Type-C cable/adapter is configured for DisplayPort Alt Mode. + */ + public static final int DISPLAYPORT_ALT_MODE_STATUS_ENABLED = 3; + + /** @hide */ + @IntDef(prefix = { "DISPLAYPORT_ALT_MODE_STATUS_" }, value = { + DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN, + DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE, + DISPLAYPORT_ALT_MODE_STATUS_CAPABLE, + DISPLAYPORT_ALT_MODE_STATUS_ENABLED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface DisplayPortAltModeStatus {} + + /** @hide */ + public DisplayPortAltModeInfo() { + mPartnerSinkStatus = DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN; + mCableStatus = DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN; + mNumLanes = 0; + } + + /** @hide */ + public DisplayPortAltModeInfo(int partnerSinkStatus, int cableStatus, + int numLanes) { + mPartnerSinkStatus = partnerSinkStatus; + mCableStatus = cableStatus; + mNumLanes = numLanes; + } + + /** + * Returns the DisplayPort Alt Mode Status for a port partner acting as a sink. + * + * @return {@link #DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN} + * or {@link #DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE} + * or {@link #DISPLAYPORT_ALT_MODE_STATUS_CAPABLE} + * or {@link #DISPLAYPORT_ALT_MODE_STATUS_ENABLED} + */ + public @DisplayPortAltModeStatus int getPartnerSinkStatus() { + return mPartnerSinkStatus; + } + + /** + * Returns the DisplayPort Alt Mode Status for the attached cable + * + * @return {@link #DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN} + * or {@link #DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE} + * or {@link #DISPLAYPORT_ALT_MODE_STATUS_CAPABLE} + * or {@link #DISPLAYPORT_ALT_MODE_STATUS_ENABLED} + */ + public @DisplayPortAltModeStatus int getCableStatus() { + return mCableStatus; + } + + /** + * Returns the number of lanes used to transmit display data. + * + */ + public int getNumberOfLanes() { + return mNumLanes; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(mPartnerSinkStatus); + dest.writeInt(mCableStatus); + dest.writeInt(mNumLanes); + } + + @NonNull + @Override + public String toString() { + return "DisplayPortAltModeInfo{partnerSink=" + + mPartnerSinkStatus + + " cable=" + + mCableStatus + + " numLanes=" + + mNumLanes + + "}"; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof DisplayPortAltModeInfo)) { + return false; + } + DisplayPortAltModeInfo other = (DisplayPortAltModeInfo) o; + return this.mPartnerSinkStatus == other.mPartnerSinkStatus + && this.mCableStatus == other.mCableStatus + && this.mNumLanes == other.mNumLanes; + } + + @Override + public int hashCode() { + return Objects.hash(mPartnerSinkStatus, mCableStatus, mNumLanes); + } + + public static final @NonNull Parcelable.Creator CREATOR = + new Parcelable.Creator() { + @Override + public DisplayPortAltModeInfo createFromParcel(Parcel in) { + int partnerSinkStatus = in.readInt(); + int cableStatus = in.readInt(); + int numLanes = in.readInt(); + return new DisplayPortAltModeInfo(partnerSinkStatus, cableStatus, numLanes); + } + + @Override + public DisplayPortAltModeInfo[] newArray(int size) { + return new DisplayPortAltModeInfo[size]; + } + }; +} diff --git a/core/java/android/hardware/usb/IDisplayPortAltModeInfoListener.aidl b/core/java/android/hardware/usb/IDisplayPortAltModeInfoListener.aidl new file mode 100644 index 0000000000000..e93e0fbb67de2 --- /dev/null +++ b/core/java/android/hardware/usb/IDisplayPortAltModeInfoListener.aidl @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2022 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 android.hardware.usb; + +import android.hardware.usb.DisplayPortAltModeInfo; + +/** + * @hide + */ +oneway interface IDisplayPortAltModeInfoListener { + void onDisplayPortAltModeInfoChanged(in String portId, + in DisplayPortAltModeInfo DisplayPortAltModeInfo); +} \ No newline at end of file diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index 248b5d0398f6f..21b00e31054dd 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -18,6 +18,7 @@ package android.hardware.usb; import android.app.PendingIntent; import android.content.ComponentName; +import android.hardware.usb.IDisplayPortAltModeInfoListener; import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; @@ -184,4 +185,15 @@ interface IUsbManager /* Sets USB device connection handler. */ void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler); + + /* Registers callback for Usb events */ + @JavaPassthrough(annotation= + "@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_USB)") + boolean registerForDisplayPortEvents(IDisplayPortAltModeInfoListener listener); + + /* Unregisters Usb event callback */ + @JavaPassthrough(annotation= + "@android.annotation.RequiresPermission(android.Manifest.permission.MANAGE_USB)") + void unregisterForDisplayPortEvents(IDisplayPortAltModeInfoListener listener); + } diff --git a/core/java/android/hardware/usb/ParcelableUsbPort.java b/core/java/android/hardware/usb/ParcelableUsbPort.java index 7fc282c141ba5..eb6501ad228be 100644 --- a/core/java/android/hardware/usb/ParcelableUsbPort.java +++ b/core/java/android/hardware/usb/ParcelableUsbPort.java @@ -35,12 +35,14 @@ public final class ParcelableUsbPort implements Parcelable { private final boolean mSupportsEnableContaminantPresenceProtection; private final boolean mSupportsEnableContaminantPresenceDetection; private final boolean mSupportsComplianceWarnings; + private final int mSupportedAltModesMask; private ParcelableUsbPort(@NonNull String id, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection, - boolean supportsComplianceWarnings) { + boolean supportsComplianceWarnings, + int supportedAltModesMask) { mId = id; mSupportedModes = supportedModes; mSupportedContaminantProtectionModes = supportedContaminantProtectionModes; @@ -50,6 +52,7 @@ public final class ParcelableUsbPort implements Parcelable { supportsEnableContaminantPresenceDetection; mSupportsComplianceWarnings = supportsComplianceWarnings; + mSupportedAltModesMask = supportedAltModesMask; } /** @@ -64,7 +67,8 @@ public final class ParcelableUsbPort implements Parcelable { port.getSupportedContaminantProtectionModes(), port.supportsEnableContaminantPresenceProtection(), port.supportsEnableContaminantPresenceDetection(), - port.supportsComplianceWarnings()); + port.supportsComplianceWarnings(), + port.getSupportedAltModesMask()); } /** @@ -78,7 +82,8 @@ public final class ParcelableUsbPort implements Parcelable { return new UsbPort(usbManager, mId, mSupportedModes, mSupportedContaminantProtectionModes, mSupportsEnableContaminantPresenceProtection, mSupportsEnableContaminantPresenceDetection, - mSupportsComplianceWarnings); + mSupportsComplianceWarnings, + mSupportedAltModesMask); } @Override @@ -94,6 +99,7 @@ public final class ParcelableUsbPort implements Parcelable { dest.writeBoolean(mSupportsEnableContaminantPresenceProtection); dest.writeBoolean(mSupportsEnableContaminantPresenceDetection); dest.writeBoolean(mSupportsComplianceWarnings); + dest.writeInt(mSupportedAltModesMask); } public static final @android.annotation.NonNull Creator CREATOR = @@ -106,12 +112,14 @@ public final class ParcelableUsbPort implements Parcelable { boolean supportsEnableContaminantPresenceProtection = in.readBoolean(); boolean supportsEnableContaminantPresenceDetection = in.readBoolean(); boolean supportsComplianceWarnings = in.readBoolean(); + int supportedAltModesMask = in.readInt(); return new ParcelableUsbPort(id, supportedModes, supportedContaminantProtectionModes, supportsEnableContaminantPresenceProtection, supportsEnableContaminantPresenceDetection, - supportsComplianceWarnings); + supportsComplianceWarnings, + supportedAltModesMask); } @Override diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 7a8117c1b684b..909d147412cf9 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -20,6 +20,7 @@ package android.hardware.usb; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE; import android.Manifest; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.LongDef; import android.annotation.NonNull; @@ -44,16 +45,24 @@ import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; +import android.util.ArrayMap; import android.util.Log; +import android.util.Slog; + +import com.android.internal.annotations.GuardedBy; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.StringJoiner; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.Executor; +import java.util.function.BiConsumer; +import java.util.function.Consumer; /** * This class allows you to access the state of USB and communicate with USB devices. @@ -724,8 +733,60 @@ public class UsbManager { }) public @interface UsbHalVersion {} + /** + * Listener to register for when the {@link DisplayPortAltModeInfo} changes on a + * {@link UsbPort}. + * + * @hide + */ + @SystemApi + public interface DisplayPortAltModeInfoListener { + /** + * Callback to be executed when the {@link DisplayPortAltModeInfo} changes on a + * {@link UsbPort}. + * + * @param portId String describing the {@link UsbPort} that was changed. + * @param info New {@link DisplayPortAltModeInfo} for the corresponding portId. + */ + public void onDisplayPortAltModeInfoChanged(@NonNull String portId, + @NonNull DisplayPortAltModeInfo info); + } + + /** + * Holds callback and executor data to be passed across UsbService. + */ + private class DisplayPortAltModeInfoDispatchingListener extends + IDisplayPortAltModeInfoListener.Stub { + + public void onDisplayPortAltModeInfoChanged(String portId, + DisplayPortAltModeInfo displayPortAltModeInfo) { + synchronized (mDisplayPortListenersLock) { + for (Map.Entry entry : + mDisplayPortListeners.entrySet()) { + Executor executor = entry.getValue(); + DisplayPortAltModeInfoListener callback = entry.getKey(); + final long token = Binder.clearCallingIdentity(); + try { + executor.execute(() -> callback.onDisplayPortAltModeInfoChanged(portId, + displayPortAltModeInfo)); + } catch (Exception e) { + Slog.e(TAG, "Exception during onDisplayPortAltModeInfoChanged from " + + "executor: " + executor, e); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + } + } + private final Context mContext; private final IUsbManager mService; + private final Object mDisplayPortListenersLock = new Object(); + @GuardedBy("mDisplayPortListenersLock") + private ArrayMap mDisplayPortListeners; + @GuardedBy("mDisplayPortListenersLock") + private DisplayPortAltModeInfoDispatchingListener mDisplayPortServiceListener; /** * @hide @@ -1524,6 +1585,109 @@ public class UsbManager { } } + @GuardedBy("mDisplayPortListenersLock") + @RequiresPermission(Manifest.permission.MANAGE_USB) + private boolean registerDisplayPortAltModeEventsIfNeededLocked() { + DisplayPortAltModeInfoDispatchingListener displayPortDispatchingListener = + new DisplayPortAltModeInfoDispatchingListener(); + try { + if (mService.registerForDisplayPortEvents(displayPortDispatchingListener)) { + mDisplayPortServiceListener = displayPortDispatchingListener; + return true; + } + return false; + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Registers the given listener to listen for DisplayPort Alt Mode changes. + *

+ * If this method returns true, the caller should ensure to call + * {@link #unregisterDisplayPortAltModeListener} when it no longer requires updates. + * + * @param executor Executor on which to run the listener. + * @param listener DisplayPortAltModeInfoListener invoked on DisplayPortAltModeInfo + * changes. See {@link #DisplayPortAltModeInfoListener} for listener + * details. + * + * @return true on successful register, false on failed register due to listener already being + * registered or an internal error. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.MANAGE_USB) + public boolean registerDisplayPortAltModeInfoListener( + @NonNull @CallbackExecutor Executor executor, + @NonNull DisplayPortAltModeInfoListener listener) { + Objects.requireNonNull(executor, "registerDisplayPortAltModeInfoListener: " + + "executor must not be null."); + Objects.requireNonNull(listener, "registerDisplayPortAltModeInfoListener: " + + "listener must not be null."); + + synchronized (mDisplayPortListenersLock) { + if (mDisplayPortListeners == null) { + mDisplayPortListeners = new ArrayMap(); + } + + if (mDisplayPortServiceListener == null) { + if (!registerDisplayPortAltModeEventsIfNeededLocked()) { + return false; + } + } + if (mDisplayPortListeners.containsKey(listener)) { + return false; + } + + mDisplayPortListeners.put(listener, executor); + return true; + } + } + + @GuardedBy("mDisplayPortListenersLock") + @RequiresPermission(Manifest.permission.MANAGE_USB) + private void unregisterDisplayPortAltModeEventsLocked() { + if (mDisplayPortServiceListener != null) { + try { + mService.unregisterForDisplayPortEvents(mDisplayPortServiceListener); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } finally { + // If there was a RemoteException, the system server may have died, + // and this listener probably became unregistered, so clear it for re-registration. + mDisplayPortServiceListener = null; + } + } + } + + /** + * Unregisters the given listener if it was previously passed to + * registerDisplayPortAltModeInfoListener. + * + * @param listener DisplayPortAltModeInfoListener used to register the listener + * in registerDisplayPortAltModeInfoListener. + * + * @hide + */ + @SystemApi + @RequiresPermission(Manifest.permission.MANAGE_USB) + public void unregisterDisplayPortAltModeInfoListener( + @NonNull DisplayPortAltModeInfoListener listener) { + synchronized (mDisplayPortListenersLock) { + if (mDisplayPortListeners == null) { + return; + } + mDisplayPortListeners.remove(listener); + if (mDisplayPortListeners.isEmpty()) { + unregisterDisplayPortAltModeEventsLocked(); + } + } + return; + } + /** * Sets the component that will handle USB device connection. *

diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java index cdd67b7c35477..73dcb362f3839 100644 --- a/core/java/android/hardware/usb/UsbPort.java +++ b/core/java/android/hardware/usb/UsbPort.java @@ -52,6 +52,10 @@ import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESS import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_BC_1_2; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP; import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_OTHER; +import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN; +import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE; +import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_CAPABLE; +import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_ENABLED; import android.Manifest; import android.annotation.CallbackExecutor; @@ -90,6 +94,7 @@ public final class UsbPort { private final boolean mSupportsEnableContaminantPresenceProtection; private final boolean mSupportsEnableContaminantPresenceDetection; private final boolean mSupportsComplianceWarnings; + private final @AltModeType int mSupportedAltModes; private static final int NUM_DATA_ROLES = Constants.PortDataRole.NUM_DATA_ROLES; /** @@ -252,6 +257,18 @@ public final class UsbPort { @Retention(RetentionPolicy.SOURCE) @interface EnableUsbDataWhileDockedStatus{} + /** + * Indicates that the Alt Mode being described is DisplayPort. + */ + public static final int FLAG_ALT_MODE_TYPE_DISPLAYPORT = 1 << 0; + + /** @hide */ + @IntDef(prefix = { "FLAG_ALT_MODE_TYPE_" }, flag = true, value = { + FLAG_ALT_MODE_TYPE_DISPLAYPORT, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface AltModeType {} + /** @hide */ public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes, int supportedContaminantProtectionModes, @@ -260,7 +277,7 @@ public final class UsbPort { this(usbManager, id, supportedModes, supportedContaminantProtectionModes, supportsEnableContaminantPresenceProtection, supportsEnableContaminantPresenceDetection, - false); + false, 0); } /** @hide */ @@ -268,7 +285,8 @@ public final class UsbPort { int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceProtection, boolean supportsEnableContaminantPresenceDetection, - boolean supportsComplianceWarnings) { + boolean supportsComplianceWarnings, + int supportedAltModes) { Objects.requireNonNull(id); Preconditions.checkFlagsArgument(supportedModes, MODE_DFP | MODE_UFP | MODE_AUDIO_ACCESSORY | MODE_DEBUG_ACCESSORY); @@ -282,6 +300,7 @@ public final class UsbPort { mSupportsEnableContaminantPresenceDetection = supportsEnableContaminantPresenceDetection; mSupportsComplianceWarnings = supportsComplianceWarnings; + mSupportedAltModes = supportedAltModes; } /** @@ -365,6 +384,27 @@ public final class UsbPort { return mSupportsComplianceWarnings; } + /** + * Returns all Alt Modes supported by the port. + * + * @hide + */ + public @AltModeType int getSupportedAltModesMask() { + return mSupportedAltModes; + } + + /** + * Returns whether all Alt Mode types in a given mask are supported + * by the port. + * + * @return true if all given Alt Modes are supported, false otherwise. + * + */ + public boolean isAltModeSupported(@AltModeType int typeMask) { + return (mSupportedAltModes & typeMask) == typeMask; + } + + /** * Sets the desired role combination of the port. *

@@ -760,6 +800,22 @@ public final class UsbPort { return complianceWarningString.toString().replaceAll(", ]$", "]"); } + /** @hide */ + public static String dpAltModeStatusToString(int dpAltModeStatus) { + switch (dpAltModeStatus) { + case DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN: + return "Unknown"; + case DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE: + return "Not Capable"; + case DISPLAYPORT_ALT_MODE_STATUS_CAPABLE: + return "Capable"; + case DISPLAYPORT_ALT_MODE_STATUS_ENABLED: + return "Enabled"; + default: + return Integer.toString(dpAltModeStatus); + } + } + /** @hide */ public static void checkMode(int powerRole) { Preconditions.checkArgumentInRange(powerRole, Constants.PortMode.NONE, diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java index e61703d1c3ff4..8c133079a70a1 100644 --- a/core/java/android/hardware/usb/UsbPortStatus.java +++ b/core/java/android/hardware/usb/UsbPortStatus.java @@ -20,6 +20,7 @@ import android.Manifest; import android.annotation.CheckResult; import android.annotation.IntDef; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.os.Parcel; @@ -27,6 +28,7 @@ import android.os.Parcelable; import com.android.internal.annotations.Immutable; +import java.lang.StringBuilder; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -49,6 +51,13 @@ public final class UsbPortStatus implements Parcelable { private final @UsbDataStatus int mUsbDataStatus; private final @PowerBrickConnectionStatus int mPowerBrickConnectionStatus; private final @NonNull @ComplianceWarning int[] mComplianceWarnings; + private final @PlugState int mPlugState; + /** + * Holds the DisplayPort Alt Mode info for the Port. This field + * is null if the device does not support DisplayPort Alt Mode. + */ + private final @Nullable DisplayPortAltModeInfo mDisplayPortAltModeInfo; + /** * Power role: This USB port does not have a power role. @@ -300,6 +309,35 @@ public final class UsbPortStatus implements Parcelable { */ public static final int COMPLIANCE_WARNING_MISSING_RP = 4; + /** + * Indicates that the Type-C plug orientation cannot be + * determined. + */ + public static final int PLUG_STATE_UNKNOWN = 0; + + /** + * Indicates no Type-C plug is inserted into the device. + */ + public static final int PLUG_STATE_UNPLUGGED = 1; + + /** + * Indicates a Type-C plug is inserted into the device, but + * the orientation cannot be determined. + */ + public static final int PLUG_STATE_PLUGGED_ORIENTATION_UNKNOWN = 2; + + /** + * Indicates that the connected plug uses its CC1 + * pin to manage the Source-to-Sink connection. + */ + public static final int PLUG_STATE_PLUGGED_ORIENTATION_NORMAL = 3; + + /** + * Indicates that the connected plug uses its CC2 + * pin to manage the Source-to-Sink connection. + */ + public static final int PLUG_STATE_PLUGGED_ORIENTATION_FLIPPED = 4; + @IntDef(prefix = { "CONTAMINANT_DETECTION_" }, value = { CONTAMINANT_DETECTION_NOT_SUPPORTED, CONTAMINANT_DETECTION_DISABLED, @@ -338,6 +376,16 @@ public final class UsbPortStatus implements Parcelable { @Retention(RetentionPolicy.SOURCE) @interface ComplianceWarning{} + @IntDef(prefix = { "PLUG_STATE_" }, value = { + PLUG_STATE_UNKNOWN, + PLUG_STATE_UNPLUGGED, + PLUG_STATE_PLUGGED_ORIENTATION_UNKNOWN, + PLUG_STATE_PLUGGED_ORIENTATION_NORMAL, + PLUG_STATE_PLUGGED_ORIENTATION_FLIPPED, + }) + @Retention(RetentionPolicy.SOURCE) + @interface PlugState{} + /** @hide */ @IntDef(prefix = { "DATA_STATUS_" }, flag = true, value = { DATA_STATUS_UNKNOWN, @@ -348,7 +396,7 @@ public final class UsbPortStatus implements Parcelable { DATA_STATUS_DISABLED_DOCK_HOST_MODE, DATA_STATUS_DISABLED_DOCK_DEVICE_MODE, DATA_STATUS_DISABLED_FORCE, - DATA_STATUS_DISABLED_DEBUG + DATA_STATUS_DISABLED_DEBUG, }) @Retention(RetentionPolicy.SOURCE) @interface UsbDataStatus{} @@ -368,7 +416,9 @@ public final class UsbPortStatus implements Parcelable { int contaminantDetectionStatus, @UsbDataStatus int usbDataStatus, boolean powerTransferLimited, @PowerBrickConnectionStatus int powerBrickConnectionStatus, - @NonNull @ComplianceWarning int[] complianceWarnings) { + @NonNull @ComplianceWarning int[] complianceWarnings, + int plugState, + @Nullable DisplayPortAltModeInfo displayPortAltModeInfo) { mCurrentMode = currentMode; mCurrentPowerRole = currentPowerRole; mCurrentDataRole = currentDataRole; @@ -393,6 +443,8 @@ public final class UsbPortStatus implements Parcelable { mPowerTransferLimited = powerTransferLimited; mPowerBrickConnectionStatus = powerBrickConnectionStatus; mComplianceWarnings = complianceWarnings; + mPlugState = plugState; + mDisplayPortAltModeInfo = displayPortAltModeInfo; } /** @hide */ @@ -404,7 +456,7 @@ public final class UsbPortStatus implements Parcelable { this(currentMode, currentPowerRole, currentDataRole, supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - new int[] {}); + new int[] {}, PLUG_STATE_UNKNOWN, null); } /** @hide */ @@ -414,7 +466,7 @@ public final class UsbPortStatus implements Parcelable { this(currentMode, currentPowerRole, currentDataRole, supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, DATA_STATUS_UNKNOWN, false, POWER_BRICK_STATUS_UNKNOWN, - new int[] {}); + new int[] {}, PLUG_STATE_UNKNOWN, null); } /** @@ -547,10 +599,34 @@ public final class UsbPortStatus implements Parcelable { return mComplianceWarnings; } + /** + * Returns the orientation state of the attached cable/adapter. + * + * @return one of {@link #PLUG_STATE_UNKNOWN}, + * {@link #PLUG_STATE_UNPLUGGED}, + * {@link #PLUG_STATE_PLUGGED_ORIENTATION_UNKNOWN}, + * {@link #PLUG_STATE_PLUGGED_ORIENTATION_NORMAL}, + * {@link #PLUG_STATE_PLUGGED_ORIENTATION_FLIPPED}, + */ + public @PlugState int getPlugState() { + return mPlugState; + } + + /** + * Returns the DisplayPortInfo of the USB Port, if applicable. + * + * @return an instance of type DisplayPortInfo + * or null if not applicable. + */ + @Nullable + public DisplayPortAltModeInfo getDisplayPortAltModeInfo() { + return (mDisplayPortAltModeInfo == null) ? null : mDisplayPortAltModeInfo; + } + @NonNull @Override public String toString() { - return "UsbPortStatus{connected=" + isConnected() + StringBuilder mString = new StringBuilder("UsbPortStatus{connected=" + isConnected() + ", currentMode=" + UsbPort.modeToString(mCurrentMode) + ", currentPowerRole=" + UsbPort.powerRoleToString(mCurrentPowerRole) + ", currentDataRole=" + UsbPort.dataRoleToString(mCurrentDataRole) @@ -569,7 +645,12 @@ public final class UsbPortStatus implements Parcelable { .powerBrickConnectionStatusToString(getPowerBrickConnectionStatus()) + ", complianceWarnings=" + UsbPort.complianceWarningsToString(getComplianceWarnings()) - + "}"; + + ", plugState=" + + getPlugState() + + ", displayPortAltModeInfo=" + + mDisplayPortAltModeInfo + + "}"); + return mString.toString(); } @Override @@ -589,6 +670,13 @@ public final class UsbPortStatus implements Parcelable { dest.writeBoolean(mPowerTransferLimited); dest.writeInt(mPowerBrickConnectionStatus); dest.writeIntArray(mComplianceWarnings); + dest.writeInt(mPlugState); + if (mDisplayPortAltModeInfo == null) { + dest.writeBoolean(false); + } else { + dest.writeBoolean(true); + mDisplayPortAltModeInfo.writeToParcel(dest, 0); + } } public static final @NonNull Parcelable.Creator CREATOR = @@ -605,11 +693,19 @@ public final class UsbPortStatus implements Parcelable { boolean powerTransferLimited = in.readBoolean(); int powerBrickConnectionStatus = in.readInt(); @ComplianceWarning int[] complianceWarnings = in.createIntArray(); + int plugState = in.readInt(); + boolean supportsDisplayPortAltMode = in.readBoolean(); + DisplayPortAltModeInfo displayPortAltModeInfo; + if (supportsDisplayPortAltMode) { + displayPortAltModeInfo = DisplayPortAltModeInfo.CREATOR.createFromParcel(in); + } else { + displayPortAltModeInfo = null; + } return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole, supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - complianceWarnings); + complianceWarnings, plugState, displayPortAltModeInfo); } @Override @@ -634,6 +730,8 @@ public final class UsbPortStatus implements Parcelable { private @UsbDataStatus int mUsbDataStatus; private @PowerBrickConnectionStatus int mPowerBrickConnectionStatus; private @ComplianceWarning int[] mComplianceWarnings; + private @PlugState int mPlugState; + private @Nullable DisplayPortAltModeInfo mDisplayPortAltModeInfo; public Builder() { mCurrentMode = MODE_NONE; @@ -644,6 +742,8 @@ public final class UsbPortStatus implements Parcelable { mUsbDataStatus = DATA_STATUS_UNKNOWN; mPowerBrickConnectionStatus = POWER_BRICK_STATUS_UNKNOWN; mComplianceWarnings = new int[] {}; + mPlugState = PLUG_STATE_UNKNOWN; + mDisplayPortAltModeInfo = null; } /** @@ -742,6 +842,28 @@ public final class UsbPortStatus implements Parcelable { return this; } + /** + * Sets the plug orientation of {@link UsbPortStatus} + * + * @return Instance of {@link Builder} + */ + @NonNull + public Builder setPlugState(int plugState) { + mPlugState = plugState; + return this; + } + + /** + * Sets the plug orientation of {@link UsbPortStatus} + * + * @return Instance of {@link Builder} + */ + @NonNull + public Builder setDisplayPortAltModeInfo( + @Nullable DisplayPortAltModeInfo displayPortAltModeInfo) { + mDisplayPortAltModeInfo = displayPortAltModeInfo; + return this; + } /** * Creates the {@link UsbPortStatus} object. @@ -751,7 +873,8 @@ public final class UsbPortStatus implements Parcelable { UsbPortStatus status = new UsbPortStatus(mCurrentMode, mCurrentPowerRole, mCurrentDataRole, mSupportedRoleCombinations, mContaminantProtectionStatus, mContaminantDetectionStatus, mUsbDataStatus, mPowerTransferLimited, - mPowerBrickConnectionStatus, mComplianceWarnings); + mPowerBrickConnectionStatus, mComplianceWarnings, + mPlugState, mDisplayPortAltModeInfo); return status; } }; diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java index f920f0f1f2816..28d726e480884 100644 --- a/services/usb/java/com/android/server/usb/UsbPortManager.java +++ b/services/usb/java/com/android/server/usb/UsbPortManager.java @@ -46,11 +46,13 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.hardware.usb.IDisplayPortAltModeInfoListener; import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.ParcelableUsbPort; import android.hardware.usb.UsbManager; import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; +import android.hardware.usb.DisplayPortAltModeInfo; import android.hardware.usb.V1_0.IUsb; import android.hardware.usb.V1_0.PortRole; import android.hardware.usb.V1_0.PortRoleType; @@ -63,6 +65,8 @@ import android.hidl.manager.V1_0.IServiceNotification; import android.os.Bundle; import android.os.Handler; import android.os.HwBinder; +import android.os.IBinder; +import android.os.IInterface; import android.os.Message; import android.os.Parcel; import android.os.Parcelable; @@ -90,8 +94,10 @@ import com.android.server.usb.hal.port.UsbPortHalInstance; import java.util.Arrays; import java.util.ArrayList; +import java.util.LinkedList; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.concurrent.Executor; /** * Allows trusted components to control the properties of physical USB ports @@ -105,7 +111,7 @@ import java.util.Objects; * (but we don't care today). *

*/ -public class UsbPortManager { +public class UsbPortManager implements IBinder.DeathRecipient { private static final String TAG = "UsbPortManager"; private static final int MSG_UPDATE_PORTS = 1; @@ -158,6 +164,12 @@ public class UsbPortManager { private NotificationManager mNotificationManager; + // Maintains a list of DisplayPortAltModeInfo Event listeners, + // protected by mDisplayPortListenerLock for broadcasts/register/unregister events + private final Object mDisplayPortListenerLock = new Object(); + private final ArrayMap mDisplayPortListeners = + new ArrayMap(); + /** * If there currently is a notification related to contaminated USB port management * shown the id of the notification, or 0 if there is none. @@ -673,6 +685,46 @@ public class UsbPortManager { } } + @Override + public void binderDied() { + // All calls should go to binderDied(IBinder deadBinder) + Slog.wtf(TAG, "binderDied() called unexpectedly"); + } + + public void binderDied(IBinder deadBinder) { + synchronized (mDisplayPortListenerLock) { + mDisplayPortListeners.remove(deadBinder); + Slog.d(TAG, "DisplayPortEventDispatcherListener died at " + deadBinder); + } + } + + public boolean registerForDisplayPortEvents( + @NonNull IDisplayPortAltModeInfoListener listener) { + synchronized (mDisplayPortListenerLock) { + if (!mDisplayPortListeners.containsKey(listener.asBinder())) { + try { + listener.asBinder().linkToDeath(this, 0); + } catch (RemoteException e) { + logAndPrintException(null, "Caught RemoteException in " + + "registerForDisplayPortEvents: ", e); + return false; + } + mDisplayPortListeners.put(listener.asBinder(), listener); + return true; + } + } + return false; + } + + public void unregisterForDisplayPortEvents( + @NonNull IDisplayPortAltModeInfoListener listener) { + synchronized (mDisplayPortListenerLock) { + if (mDisplayPortListeners.remove(listener.asBinder()) != null) { + listener.asBinder().unlinkToDeath(this, 0); + } + } + } + public void updatePorts(ArrayList newPortInfo) { Message message = mHandler.obtainMessage(); Bundle bundle = new Bundle(); @@ -683,8 +735,15 @@ public class UsbPortManager { } public void addSimulatedPort(String portId, int supportedModes, - boolean supportsComplianceWarnings, - IndentingPrintWriter pw) { + boolean supportsComplianceWarnings, boolean supportsDisplayPortAltMode, + IndentingPrintWriter pw) { + int supportedAltModes = supportsDisplayPortAltMode ? + UsbPort.FLAG_ALT_MODE_TYPE_DISPLAYPORT : 0; + DisplayPortAltModeInfo displayPortAltModeInfo = null; + + if (supportsDisplayPortAltMode) { + displayPortAltModeInfo = new DisplayPortAltModeInfo(); + } synchronized (mLock) { if (mSimulatedPorts.containsKey(portId)) { @@ -713,7 +772,10 @@ public class UsbPortManager { false, UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN, supportsComplianceWarnings, - new int[] {})); + new int[] {}, + UsbPortStatus.PLUG_STATE_UNKNOWN, + supportedAltModes, + displayPortAltModeInfo)); updatePortsLocked(pw, null); } } @@ -802,6 +864,25 @@ public class UsbPortManager { } } + + public void simulateDisplayPortAltModeInfo(String portId, int partnerSinkStatus, + int cableStatus, int numLanes, IndentingPrintWriter pw) { + synchronized (mLock) { + final RawPortInfo portInfo = mSimulatedPorts.get(portId); + if (portInfo == null) { + pw.println("Simulated port not found"); + return; + } + + DisplayPortAltModeInfo displayPortAltModeInfo = + new DisplayPortAltModeInfo(partnerSinkStatus, cableStatus, numLanes); + portInfo.displayPortAltModeInfo = displayPortAltModeInfo; + pw.println("Simulating DisplayPort Info: " + displayPortAltModeInfo); + updatePortsLocked(pw, null); + } + + } + public void disconnectSimulatedPort(String portId, IndentingPrintWriter pw) { synchronized (mLock) { final RawPortInfo portInfo = mSimulatedPorts.get(portId); @@ -893,6 +974,9 @@ public class UsbPortManager { portInfo.powerBrickConnectionStatus, portInfo.supportsComplianceWarnings, portInfo.complianceWarnings, + portInfo.plugState, + portInfo.supportedAltModes, + portInfo.displayPortAltModeInfo, pw); } } else { @@ -911,6 +995,9 @@ public class UsbPortManager { currentPortInfo.powerBrickConnectionStatus, currentPortInfo.supportsComplianceWarnings, currentPortInfo.complianceWarnings, + currentPortInfo.plugState, + currentPortInfo.supportedAltModes, + currentPortInfo.displayPortAltModeInfo, pw); } } @@ -937,6 +1024,9 @@ public class UsbPortManager { if (portInfo.mComplianceWarningChange == portInfo.COMPLIANCE_WARNING_CHANGED) { handlePortComplianceWarningLocked(portInfo, pw); } + if (portInfo.mDisplayPortAltModeChange == portInfo.ALTMODE_INFO_CHANGED) { + handleDpAltModeLocked(portInfo, pw); + } } } @@ -955,6 +1045,9 @@ public class UsbPortManager { int powerBrickConnectionStatus, boolean supportsComplianceWarnings, @NonNull int[] complianceWarnings, + int plugState, + int supportedAltModes, + DisplayPortAltModeInfo displayPortAltModeInfo, IndentingPrintWriter pw) { // Only allow mode switch capability for dual role ports. // Validate that the current mode matches the supported modes we expect. @@ -1009,14 +1102,15 @@ public class UsbPortManager { portId, supportedModes, supportedContaminantProtectionModes, supportsEnableContaminantPresenceProtection, supportsEnableContaminantPresenceDetection, - supportsComplianceWarnings); + supportsComplianceWarnings, + supportedAltModes); portInfo.setStatus(currentMode, canChangeMode, currentPowerRole, canChangePowerRole, currentDataRole, canChangeDataRole, supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - complianceWarnings); + complianceWarnings, plugState, displayPortAltModeInfo); mPorts.put(portId, portInfo); } else { // Validate that ports aren't changing definition out from under us. @@ -1054,7 +1148,7 @@ public class UsbPortManager { supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - complianceWarnings)) { + complianceWarnings, plugState, displayPortAltModeInfo)) { portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED; } else { portInfo.mDisposition = PortInfo.DISPOSITION_READY; @@ -1086,6 +1180,11 @@ public class UsbPortManager { sendComplianceWarningBroadcastLocked(portInfo); } + private void handleDpAltModeLocked(PortInfo portInfo, IndentingPrintWriter pw) { + logAndPrint(Log.INFO, pw, "USB port DisplayPort Alt Mode Status Changed: " + portInfo); + sendDpAltModeCallbackLocked(portInfo, pw); + } + private void handlePortRemovedLocked(PortInfo portInfo, IndentingPrintWriter pw) { logAndPrint(Log.INFO, pw, "USB port removed: " + portInfo); handlePortLocked(portInfo, pw); @@ -1135,7 +1234,6 @@ public class UsbPortManager { return complianceWarningsProto.toArray(); } - private void sendPortChangedBroadcastLocked(PortInfo portInfo) { final Intent intent = new Intent(UsbManager.ACTION_USB_PORT_CHANGED); intent.addFlags( @@ -1167,6 +1265,21 @@ public class UsbPortManager { Manifest.permission.MANAGE_USB)); } + private void sendDpAltModeCallbackLocked(PortInfo portInfo, IndentingPrintWriter pw) { + String portId = portInfo.mUsbPort.getId(); + synchronized (mDisplayPortListenerLock) { + for (IDisplayPortAltModeInfoListener mListener : mDisplayPortListeners.values()) { + try { + mListener.onDisplayPortAltModeInfoChanged(portId, + portInfo.mUsbPortStatus.getDisplayPortAltModeInfo()); + } catch (RemoteException e) { + logAndPrintException(pw, "Caught RemoteException at " + + "sendDpAltModeCallbackLocked", e); + } + } + } + } + private void enableContaminantDetectionIfNeeded(PortInfo portInfo, IndentingPrintWriter pw) { if (!mConnected.containsKey(portInfo.mUsbPort.getId())) { return; @@ -1308,6 +1421,9 @@ public class UsbPortManager { public static final int COMPLIANCE_WARNING_UNCHANGED = 0; public static final int COMPLIANCE_WARNING_CHANGED = 1; + public static final int ALTMODE_INFO_UNCHANGED = 0; + public static final int ALTMODE_INFO_CHANGED = 1; + public final UsbPort mUsbPort; public UsbPortStatus mUsbPortStatus; public boolean mCanChangeMode; @@ -1321,18 +1437,23 @@ public class UsbPortManager { public long mLastConnectDurationMillis; // default initialized to 0 which means no changes reported public int mComplianceWarningChange; + // default initialized to 0 which means unchanged + public int mDisplayPortAltModeChange; PortInfo(@NonNull UsbManager usbManager, @NonNull String portId, int supportedModes, int supportedContaminantProtectionModes, boolean supportsEnableContaminantPresenceDetection, boolean supportsEnableContaminantPresenceProtection, - boolean supportsComplianceWarnings) { + boolean supportsComplianceWarnings, + int supportedAltModes) { mUsbPort = new UsbPort(usbManager, portId, supportedModes, supportedContaminantProtectionModes, supportsEnableContaminantPresenceDetection, supportsEnableContaminantPresenceProtection, - supportsComplianceWarnings); + supportsComplianceWarnings, + supportedAltModes); mComplianceWarningChange = COMPLIANCE_WARNING_UNCHANGED; + mDisplayPortAltModeChange = ALTMODE_INFO_UNCHANGED; } public boolean complianceWarningsChanged(@NonNull int[] complianceWarnings) { @@ -1344,6 +1465,34 @@ public class UsbPortManager { return true; } + public boolean displayPortAltModeChanged(DisplayPortAltModeInfo + displayPortAltModeInfo) { + DisplayPortAltModeInfo currentDisplayPortAltModeInfo = + mUsbPortStatus.getDisplayPortAltModeInfo(); + + mDisplayPortAltModeChange = ALTMODE_INFO_UNCHANGED; + + if (displayPortAltModeInfo == null + && currentDisplayPortAltModeInfo != null) { + mDisplayPortAltModeChange = ALTMODE_INFO_CHANGED; + return true; + } + + if (currentDisplayPortAltModeInfo == null) { + if (displayPortAltModeInfo != null) { + mDisplayPortAltModeChange = ALTMODE_INFO_CHANGED; + return true; + } + return false; + } + + if (!(currentDisplayPortAltModeInfo.equals(displayPortAltModeInfo))) { + mDisplayPortAltModeChange = ALTMODE_INFO_CHANGED; + return true; + } + return false; + } + public boolean setStatus(int currentMode, boolean canChangeMode, int currentPowerRole, boolean canChangePowerRole, int currentDataRole, boolean canChangeDataRole, @@ -1364,7 +1513,7 @@ public class UsbPortManager { UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED, UsbPortStatus.DATA_STATUS_UNKNOWN, false, UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN, - new int[] {}); + new int[] {}, 0, null); dispositionChanged = true; } @@ -1410,7 +1559,7 @@ public class UsbPortManager { supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - new int[] {}); + new int[] {}, 0, null); dispositionChanged = true; } @@ -1431,8 +1580,16 @@ public class UsbPortManager { int supportedRoleCombinations, int contaminantProtectionStatus, int contaminantDetectionStatus, int usbDataStatus, boolean powerTransferLimited, int powerBrickConnectionStatus, - @NonNull int[] complianceWarnings) { + @NonNull int[] complianceWarnings, + int plugState, DisplayPortAltModeInfo displayPortAltModeInfo) { boolean dispositionChanged = false; + boolean complianceChanged = false; + boolean displayPortChanged = false; + + if (mUsbPortStatus != null) { + complianceChanged = complianceWarningsChanged(complianceWarnings); + displayPortChanged = displayPortAltModeChanged(displayPortAltModeInfo); + } mCanChangeMode = canChangeMode; mCanChangePowerRole = canChangePowerRole; @@ -1452,7 +1609,9 @@ public class UsbPortManager { || mUsbPortStatus.isPowerTransferLimited() != powerTransferLimited || mUsbPortStatus.getPowerBrickConnectionStatus() - != powerBrickConnectionStatus) { + != powerBrickConnectionStatus + || mUsbPortStatus.getPlugState() + != plugState) { if (mUsbPortStatus == null && complianceWarnings.length > 0) { mComplianceWarningChange = COMPLIANCE_WARNING_CHANGED; } @@ -1460,14 +1619,17 @@ public class UsbPortManager { supportedRoleCombinations, contaminantProtectionStatus, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - complianceWarnings); + complianceWarnings, plugState, displayPortAltModeInfo); dispositionChanged = true; - } else if (complianceWarningsChanged(complianceWarnings)) { - mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole, - supportedRoleCombinations, contaminantProtectionStatus, - contaminantDetectionStatus, usbDataStatus, - powerTransferLimited, powerBrickConnectionStatus, - complianceWarnings); + // Case used in order to send compliance warning broadcast or signal DisplayPort + // listeners. These targeted broadcasts don't use dispositionChanged to broadcast to + // general ACTION_USB_PORT_CHANGED. + } else if (complianceChanged || displayPortChanged) { + mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, + currentDataRole, supportedRoleCombinations, + contaminantProtectionStatus, contaminantDetectionStatus, + usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, + complianceWarnings, plugState, displayPortAltModeInfo); } if (mUsbPortStatus.isConnected() && mConnectedAtMillis == 0) { diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 6eb04d94e7570..7d84222d55a45 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -36,6 +36,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.hardware.usb.IUsbManager; +import android.hardware.usb.IDisplayPortAltModeInfoListener; import android.hardware.usb.IUsbOperationInternal; import android.hardware.usb.ParcelableUsbPort; import android.hardware.usb.UsbAccessory; @@ -43,6 +44,7 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; +import android.hardware.usb.DisplayPortAltModeInfo; import android.os.Binder; import android.os.Bundle; import android.os.ParcelFileDescriptor; @@ -902,6 +904,45 @@ public class UsbService extends IUsbManager.Stub { } } + @Override + public boolean registerForDisplayPortEvents( + @NonNull IDisplayPortAltModeInfoListener listener) { + Objects.requireNonNull(listener, "registerForDisplayPortEvents: listener " + + "must not be null."); + + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + + final long ident = Binder.clearCallingIdentity(); + try { + if (mPortManager != null) { + return mPortManager.registerForDisplayPortEvents(listener); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + + return false; + } + + @Override + public void unregisterForDisplayPortEvents( + @NonNull IDisplayPortAltModeInfoListener listener) { + Objects.requireNonNull(listener, "unregisterForDisplayPortEvents: listener " + + "must not be null."); + + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + + final long ident = Binder.clearCallingIdentity(); + try { + if (mPortManager != null) { + mPortManager.unregisterForDisplayPortEvents(listener); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + @NeverCompile // Avoid size overhead of debugging code. @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { @@ -993,6 +1034,7 @@ public class UsbService extends IUsbManager.Stub { int i; boolean supportsComplianceWarnings = false; + boolean supportsDisplayPortAltMode = false; switch (args[2]) { case "ufp": supportedModes = MODE_UFP; @@ -1015,14 +1057,17 @@ public class UsbService extends IUsbManager.Stub { case "--compliance-warnings": supportsComplianceWarnings = true; continue; + case "--displayport": + supportsDisplayPortAltMode = true; + continue; default: pw.println("Invalid Identifier: " + args[i]); } } if (mPortManager != null) { mPortManager.addSimulatedPort(portId, supportedModes, - supportsComplianceWarnings, - pw); + supportsComplianceWarnings, supportsDisplayPortAltMode, + pw); pw.println(); mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), "", 0); @@ -1124,6 +1169,29 @@ public class UsbService extends IUsbManager.Stub { mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), "", 0); } + } else if ("set-displayport-status".equals(args[0]) && args.length == 5) { + final String portId = args[1]; + final int partnerSinkStatus = Integer.parseInt(args[2]); + final int cableStatus = Integer.parseInt(args[3]); + final int displayPortNumLanes = Integer.parseInt(args[4]); + if (mPortManager != null) { + mPortManager.simulateDisplayPortAltModeInfo(portId, + partnerSinkStatus, cableStatus, displayPortNumLanes, pw); + pw.println(); + mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), + "", 0); + } + } else if ("reset-displayport-status".equals(args[0]) && args.length == 2) { + final String portId = args[1]; + if (mPortManager != null) { + mPortManager.simulateDisplayPortAltModeInfo(portId, + DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN, + DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN, + 0, pw); + pw.println(); + mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), + "", 0); + } } else if ("ports".equals(args[0]) && args.length == 1) { if (mPortManager != null) { mPortManager.dump(new DualDumpOutputStream(new IndentingPrintWriter(pw, " ")), @@ -1138,6 +1206,7 @@ public class UsbService extends IUsbManager.Stub { pw.println(" add-port "); pw.println(" include:"); pw.println(" --compliance-warnings: enables compliance warnings on port"); + pw.println(" --displayport: enables DisplayPort Alt Mode on port"); pw.println(" connect-port "); pw.println(" (add ? suffix if mode, power role, or data role can be changed)"); pw.println(" disconnect-port "); @@ -1148,7 +1217,8 @@ public class UsbService extends IUsbManager.Stub { pw.println(" dumpsys usb set-port-roles \"default\" source device"); pw.println(); pw.println("Example USB type C port simulation with full capabilities:"); - pw.println(" dumpsys usb add-port \"matrix\" dual --compliance-warnings"); + pw.println(" dumpsys usb add-port \"matrix\" dual --compliance-warnings " + + "--displayport"); pw.println(" dumpsys usb connect-port \"matrix\" ufp? sink? device?"); pw.println(" dumpsys usb ports"); pw.println(" dumpsys usb disconnect-port \"matrix\""); @@ -1186,6 +1256,14 @@ public class UsbService extends IUsbManager.Stub { pw.println(" 3: bc12"); pw.println(" 4: missing rp"); pw.println(); + pw.println("Example simulate DisplayPort Alt Mode Changes:"); + pw.println(" dumpsys usb add-port \"matrix\" dual --displayport"); + pw.println(" dumpsys usb set-displayport-status \"matrix\" " + + " "); + pw.println(" dumpsys usb reset-displayport-status \"matrix\""); + pw.println("reset-displayport-status can also be used in order to set"); + pw.println("the DisplayPortInfo to default values."); + pw.println(); pw.println("Example USB device descriptors:"); pw.println(" dumpsys usb dump-descriptors -dump-short"); pw.println(" dumpsys usb dump-descriptors -dump-tree"); diff --git a/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java b/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java index e6a3e53435076..ef32e938217e8 100644 --- a/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java +++ b/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java @@ -15,7 +15,9 @@ */ package com.android.server.usb.hal.port; +import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; +import android.hardware.usb.DisplayPortAltModeInfo; import android.os.Parcel; import android.os.Parcelable; @@ -42,6 +44,9 @@ public final class RawPortInfo implements Parcelable { public int powerBrickConnectionStatus; public final boolean supportsComplianceWarnings; public int[] complianceWarnings; + public int plugState; + public int supportedAltModes; + public DisplayPortAltModeInfo displayPortAltModeInfo; public RawPortInfo(String portId, int supportedModes) { this.portId = portId; @@ -56,6 +61,9 @@ public final class RawPortInfo implements Parcelable { this.powerBrickConnectionStatus = UsbPortStatus.POWER_BRICK_STATUS_UNKNOWN; this.supportsComplianceWarnings = false; this.complianceWarnings = new int[] {}; + this.plugState = UsbPortStatus.PLUG_STATE_UNKNOWN; + this.supportedAltModes = 0; + this.displayPortAltModeInfo = null; } public RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes, @@ -76,7 +84,8 @@ public final class RawPortInfo implements Parcelable { supportsEnableContaminantPresenceProtection, contaminantProtectionStatus, supportsEnableContaminantPresenceDetection, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - false, new int[] {}); + false, new int[] {}, UsbPortStatus.PLUG_STATE_UNKNOWN, + 0, null); } public RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes, @@ -91,7 +100,10 @@ public final class RawPortInfo implements Parcelable { boolean powerTransferLimited, int powerBrickConnectionStatus, boolean supportsComplianceWarnings, - int[] complianceWarnings) { + int[] complianceWarnings, + int plugState, + int supportedAltModes, + DisplayPortAltModeInfo displayPortAltModeInfo) { this.portId = portId; this.supportedModes = supportedModes; this.supportedContaminantProtectionModes = supportedContaminantProtectionModes; @@ -112,6 +124,9 @@ public final class RawPortInfo implements Parcelable { this.powerBrickConnectionStatus = powerBrickConnectionStatus; this.supportsComplianceWarnings = supportsComplianceWarnings; this.complianceWarnings = complianceWarnings; + this.plugState = plugState; + this.supportedAltModes = supportedAltModes; + this.displayPortAltModeInfo = displayPortAltModeInfo; } @Override @@ -139,12 +154,19 @@ public final class RawPortInfo implements Parcelable { dest.writeInt(powerBrickConnectionStatus); dest.writeBoolean(supportsComplianceWarnings); dest.writeIntArray(complianceWarnings); + dest.writeInt(plugState); + dest.writeInt(supportedAltModes); + if ((supportedAltModes & UsbPort.FLAG_ALT_MODE_TYPE_DISPLAYPORT) != 0) { + displayPortAltModeInfo.writeToParcel(dest, 0); + } } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @Override public RawPortInfo createFromParcel(Parcel in) { + DisplayPortAltModeInfo displayPortAltModeInfo; + String id = in.readString(); int supportedModes = in.readInt(); int supportedContaminantProtectionModes = in.readInt(); @@ -163,6 +185,13 @@ public final class RawPortInfo implements Parcelable { int powerBrickConnectionStatus = in.readInt(); boolean supportsComplianceWarnings = in.readBoolean(); int[] complianceWarnings = in.createIntArray(); + int plugState = in.readInt(); + int supportedAltModes = in.readInt(); + if ((supportedAltModes & UsbPort.FLAG_ALT_MODE_TYPE_DISPLAYPORT) != 0) { + displayPortAltModeInfo = DisplayPortAltModeInfo.CREATOR.createFromParcel(in); + } else { + displayPortAltModeInfo = null; + } return new RawPortInfo(id, supportedModes, supportedContaminantProtectionModes, currentMode, canChangeMode, currentPowerRole, canChangePowerRole, @@ -172,7 +201,8 @@ public final class RawPortInfo implements Parcelable { supportsEnableContaminantPresenceDetection, contaminantDetectionStatus, usbDataStatus, powerTransferLimited, powerBrickConnectionStatus, - supportsComplianceWarnings, complianceWarnings); + supportsComplianceWarnings, complianceWarnings, + plugState, supportedAltModes, displayPortAltModeInfo); } @Override diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java index ff4268fda93e6..b9ccacea7aa48 100644 --- a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java +++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java @@ -35,6 +35,10 @@ import android.hardware.usb.IUsbCallback; import android.hardware.usb.PortRole; import android.hardware.usb.PortStatus; import android.hardware.usb.ComplianceWarning; +import android.hardware.usb.DisplayPortAltModeInfo; +import android.hardware.usb.AltModeData; +import android.hardware.usb.AltModeData.DisplayPortAltModeData; +import android.hardware.usb.DisplayPortAltModePinAssignment; import android.os.Build; import android.os.ServiceManager; import android.os.IBinder; @@ -600,6 +604,47 @@ public final class UsbPortAidl implements UsbPortHal { return newComplianceWarnings.toArray(); } + private int toSupportedAltModesInt(android.hardware.usb.AltModeData[] supportedAltModes) { + int supportedAltModesInt = 0; + for (android.hardware.usb.AltModeData altModeData : supportedAltModes) { + switch (altModeData.getTag()) { + case AltModeData.displayPortAltModeData: + supportedAltModesInt |= UsbPort.FLAG_ALT_MODE_TYPE_DISPLAYPORT; + break; + } + } + return supportedAltModesInt; + } + + private int toDisplayPortAltModeNumLanesInt(int pinAssignment) { + switch (pinAssignment) { + case DisplayPortAltModePinAssignment.A: + case DisplayPortAltModePinAssignment.C: + case DisplayPortAltModePinAssignment.E: + return 4; + case DisplayPortAltModePinAssignment.B: + case DisplayPortAltModePinAssignment.D: + case DisplayPortAltModePinAssignment.F: + return 2; + default: + return 0; + } + } + + private DisplayPortAltModeInfo formatDisplayPortAltModeInfo( + android.hardware.usb.AltModeData[] supportedAltModes) { + for (android.hardware.usb.AltModeData altModeData : supportedAltModes) { + if (altModeData.getTag() == AltModeData.displayPortAltModeData) { + DisplayPortAltModeData displayPortData = + altModeData.getDisplayPortAltModeData(); + return new DisplayPortAltModeInfo(displayPortData.partnerSinkStatus, + displayPortData.cableStatus, + toDisplayPortAltModeNumLanesInt(displayPortData.pinAssignment)); + } + } + return null; + } + @Override public void notifyPortStatusChange( android.hardware.usb.PortStatus[] currentPortStatus, int retval) { @@ -635,7 +680,10 @@ public final class UsbPortAidl implements UsbPortHal { current.powerTransferLimited, current.powerBrickStatus, current.supportsComplianceWarnings, - formatComplianceWarnings(current.complianceWarnings)); + formatComplianceWarnings(current.complianceWarnings), + current.plugOrientation, + toSupportedAltModesInt(current.supportedAltModes), + formatDisplayPortAltModeInfo(current.supportedAltModes)); newPortInfo.add(temp); UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback AIDL V1: " + current.portName); diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java index 10403c1a5f73a..a7ecabb7c80e6 100644 --- a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java +++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java @@ -35,7 +35,8 @@ import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK; import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_UNKNOWN; - +import static android.hardware.usb.UsbPortStatus.PLUG_STATE_UNKNOWN; +import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN; import static com.android.server.usb.UsbPortManager.logAndPrint; import static com.android.server.usb.UsbPortManager.logAndPrintException; @@ -422,7 +423,10 @@ public final class UsbPortHidl implements UsbPortHal { false, CONTAMINANT_PROTECTION_NONE, false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataStatus, false, POWER_BRICK_STATUS_UNKNOWN, - false, new int[] {}); + false, new int[] {}, + PLUG_STATE_UNKNOWN, + 0, + null); newPortInfo.add(temp); UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_0: " + current.portName); @@ -457,7 +461,10 @@ public final class UsbPortHidl implements UsbPortHal { false, CONTAMINANT_PROTECTION_NONE, false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataStatus, false, POWER_BRICK_STATUS_UNKNOWN, - false, new int[] {}); + false, new int[] {}, + PLUG_STATE_UNKNOWN, + 0, + null); newPortInfo.add(temp); UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_1: " + current.status.portName); @@ -496,7 +503,10 @@ public final class UsbPortHidl implements UsbPortHal { current.contaminantDetectionStatus, sUsbDataStatus, false, POWER_BRICK_STATUS_UNKNOWN, - false, new int[] {}); + false, new int[] {}, + PLUG_STATE_UNKNOWN, + 0, + null); newPortInfo.add(temp); UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_2: " + current.status_1_1.status.portName);