Merge "Usb DisplayPort alt mode frameworks api"

This commit is contained in:
RD Babiera
2023-01-10 19:11:19 +00:00
committed by Android (Google) Code Review
14 changed files with 1017 additions and 46 deletions

View File

@@ -5771,6 +5771,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<android.hardware.usb.DisplayPortAltModeInfo> 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();
}
@@ -5779,8 +5792,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<android.hardware.usb.UsbPort> 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";
@@ -5804,11 +5819,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<java.lang.Integer>);
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean supportsComplianceWarnings();
@@ -5828,6 +5848,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
@@ -5841,6 +5862,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();
@@ -5870,6 +5893,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

View File

@@ -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;

View File

@@ -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:
* <ul>
* <li> No port partner is connected to the device
* <li> The USB Power Delivery Discover Identity command has not been issued to the port
* partner via SOP messaging.
* </ul>
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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<DisplayPortAltModeInfo> CREATOR =
new Parcelable.Creator<DisplayPortAltModeInfo>() {
@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];
}
};
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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<ParcelableUsbPort> 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

View File

@@ -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<DisplayPortAltModeInfoListener, Executor> 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<DisplayPortAltModeInfoListener, Executor> 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.
* <p>
* 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<DisplayPortAltModeInfoListener,
Executor>();
}
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.
* <p>

View File

@@ -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.
* <p>
@@ -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,

View File

@@ -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<UsbPortStatus> 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;
}
};

View File

@@ -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).
* </p>
*/
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<IBinder, IDisplayPortAltModeInfoListener> mDisplayPortListeners =
new ArrayMap<IBinder, IDisplayPortAltModeInfoListener>();
/**
* 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<RawPortInfo> 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) {

View File

@@ -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 <id> <ufp|dfp|dual|none> <optional args>");
pw.println(" <optional args> include:");
pw.println(" --compliance-warnings: enables compliance warnings on port");
pw.println(" --displayport: enables DisplayPort Alt Mode on port");
pw.println(" connect-port <id> <ufp|dfp><?> <source|sink><?> <host|device><?>");
pw.println(" (add ? suffix if mode, power role, or data role can be changed)");
pw.println(" disconnect-port <id>");
@@ -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\" <partner-sink>"
+ " <cable> <num-lanes>");
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");

View File

@@ -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<RawPortInfo> CREATOR =
new Parcelable.Creator<RawPortInfo>() {
@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

View File

@@ -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);

View File

@@ -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);