Merge changes from topic "227137943"
* changes: Implement getInterfaceHash/Version (USB) Support IUsb AIDL interface
This commit is contained in:
@@ -100,10 +100,12 @@ package android.hardware.usb {
|
|||||||
field public static final int USB_DATA_TRANSFER_RATE_LOW_SPEED = 2; // 0x2
|
field public static final int USB_DATA_TRANSFER_RATE_LOW_SPEED = 2; // 0x2
|
||||||
field public static final int USB_DATA_TRANSFER_RATE_UNKNOWN = -1; // 0xffffffff
|
field public static final int USB_DATA_TRANSFER_RATE_UNKNOWN = -1; // 0xffffffff
|
||||||
field public static final int USB_HAL_NOT_SUPPORTED = -1; // 0xffffffff
|
field public static final int USB_HAL_NOT_SUPPORTED = -1; // 0xffffffff
|
||||||
|
field public static final int USB_HAL_RETRY = -2; // 0xfffffffe
|
||||||
field public static final int USB_HAL_V1_0 = 10; // 0xa
|
field public static final int USB_HAL_V1_0 = 10; // 0xa
|
||||||
field public static final int USB_HAL_V1_1 = 11; // 0xb
|
field public static final int USB_HAL_V1_1 = 11; // 0xb
|
||||||
field public static final int USB_HAL_V1_2 = 12; // 0xc
|
field public static final int USB_HAL_V1_2 = 12; // 0xc
|
||||||
field public static final int USB_HAL_V1_3 = 13; // 0xd
|
field public static final int USB_HAL_V1_3 = 13; // 0xd
|
||||||
|
field public static final int USB_HAL_V2_0 = 20; // 0x14
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4169,8 +4169,14 @@ package android.hardware.usb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class UsbPort {
|
public final class UsbPort {
|
||||||
|
method @CheckResult @RequiresPermission(android.Manifest.permission.MANAGE_USB) public int enableUsbData(boolean);
|
||||||
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
|
method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USB) public android.hardware.usb.UsbPortStatus getStatus();
|
||||||
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
|
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setRoles(int, int);
|
||||||
|
field public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1; // 0x1
|
||||||
|
field public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2; // 0x2
|
||||||
|
field public static final int ENABLE_USB_DATA_ERROR_OTHER = 4; // 0x4
|
||||||
|
field public static final int ENABLE_USB_DATA_ERROR_PORT_MISMATCH = 3; // 0x3
|
||||||
|
field public static final int ENABLE_USB_DATA_SUCCESS = 0; // 0x0
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class UsbPortStatus implements android.os.Parcelable {
|
public final class UsbPortStatus implements android.os.Parcelable {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.hardware.usb;
|
|||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
import android.hardware.usb.UsbAccessory;
|
import android.hardware.usb.UsbAccessory;
|
||||||
import android.hardware.usb.UsbDevice;
|
import android.hardware.usb.UsbDevice;
|
||||||
import android.hardware.usb.ParcelableUsbPort;
|
import android.hardware.usb.ParcelableUsbPort;
|
||||||
@@ -136,7 +137,7 @@ interface IUsbManager
|
|||||||
void resetUsbGadget();
|
void resetUsbGadget();
|
||||||
|
|
||||||
/* Set USB data on or off */
|
/* Set USB data on or off */
|
||||||
boolean enableUsbDataSignal(boolean enable);
|
boolean enableUsbData(in String portId, boolean enable, int operationId, in IUsbOperationInternal callback);
|
||||||
|
|
||||||
/* Gets the USB Hal Version. */
|
/* Gets the USB Hal Version. */
|
||||||
int getUsbHalVersion();
|
int getUsbHalVersion();
|
||||||
@@ -159,6 +160,6 @@ interface IUsbManager
|
|||||||
/* Enable/disable contaminant detection */
|
/* Enable/disable contaminant detection */
|
||||||
void enableContaminantDetection(in String portId, boolean enable);
|
void enableContaminantDetection(in String portId, boolean enable);
|
||||||
|
|
||||||
/* Sets USB device connection handler. */
|
/* Sets USB device connection handler. */
|
||||||
void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
|
void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
|
||||||
}
|
}
|
||||||
|
|||||||
24
core/java/android/hardware/usb/IUsbOperationInternal.aidl
Normal file
24
core/java/android/hardware/usb/IUsbOperationInternal.aidl
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
oneway interface IUsbOperationInternal {
|
||||||
|
void onOperationComplete(in int status);
|
||||||
|
}
|
||||||
@@ -36,6 +36,8 @@ import android.content.pm.PackageManager;
|
|||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.hardware.usb.gadget.V1_0.GadgetFunction;
|
import android.hardware.usb.gadget.V1_0.GadgetFunction;
|
||||||
import android.hardware.usb.gadget.V1_2.UsbSpeed;
|
import android.hardware.usb.gadget.V1_2.UsbSpeed;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
|
import android.hardware.usb.UsbPort;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
@@ -48,6 +50,7 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.StringJoiner;
|
import java.util.StringJoiner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -515,6 +518,14 @@ public class UsbManager {
|
|||||||
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
public static final int USB_DATA_TRANSFER_RATE_40G = 40 * 1024;
|
public static final int USB_DATA_TRANSFER_RATE_40G = 40 * 1024;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returned when the client has to retry querying the version.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
|
public static final int USB_HAL_RETRY = -2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Value for USB hal is not presented.
|
* The Value for USB hal is not presented.
|
||||||
*
|
*
|
||||||
@@ -555,6 +566,14 @@ public class UsbManager {
|
|||||||
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
public static final int USB_HAL_V1_3 = 13;
|
public static final int USB_HAL_V1_3 = 13;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value for USB Hal Version v2.0.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||||||
|
public static final int USB_HAL_V2_0 = 20;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
|
* Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
|
||||||
* {@hide}
|
* {@hide}
|
||||||
@@ -664,6 +683,7 @@ public class UsbManager {
|
|||||||
USB_HAL_V1_1,
|
USB_HAL_V1_1,
|
||||||
USB_HAL_V1_2,
|
USB_HAL_V1_2,
|
||||||
USB_HAL_V1_3,
|
USB_HAL_V1_3,
|
||||||
|
USB_HAL_V2_0,
|
||||||
})
|
})
|
||||||
public @interface UsbHalVersion {}
|
public @interface UsbHalVersion {}
|
||||||
|
|
||||||
@@ -1168,8 +1188,9 @@ public class UsbManager {
|
|||||||
/**
|
/**
|
||||||
* Enable/Disable the USB data signaling.
|
* Enable/Disable the USB data signaling.
|
||||||
* <p>
|
* <p>
|
||||||
* Enables/Disables USB data path in all the USB ports.
|
* Enables/Disables USB data path of the first port..
|
||||||
* It will force to stop or restore USB data signaling.
|
* It will force to stop or restore USB data signaling.
|
||||||
|
* Call UsbPort API if the device has more than one UsbPort.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param enable enable or disable USB data signaling
|
* @param enable enable or disable USB data signaling
|
||||||
@@ -1180,11 +1201,11 @@ public class UsbManager {
|
|||||||
*/
|
*/
|
||||||
@RequiresPermission(Manifest.permission.MANAGE_USB)
|
@RequiresPermission(Manifest.permission.MANAGE_USB)
|
||||||
public boolean enableUsbDataSignal(boolean enable) {
|
public boolean enableUsbDataSignal(boolean enable) {
|
||||||
try {
|
List<UsbPort> usbPorts = getPorts();
|
||||||
return mService.enableUsbDataSignal(enable);
|
if (usbPorts.size() == 1) {
|
||||||
} catch (RemoteException e) {
|
return usbPorts.get(0).enableUsbData(enable) == UsbPort.ENABLE_USB_DATA_SUCCESS;
|
||||||
throw e.rethrowFromSystemServer();
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1269,6 +1290,41 @@ public class UsbManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should only be called by {@link UsbPort#enableUsbData}.
|
||||||
|
* <p>
|
||||||
|
* Enables or disables USB data on the specific port.
|
||||||
|
*
|
||||||
|
* @param port USB port for which USB data needs to be enabled or disabled.
|
||||||
|
* @param enable Enable USB data when true.
|
||||||
|
* Disable USB data when false.
|
||||||
|
* @param operationId operationId for the request.
|
||||||
|
* @param callback callback object to be invoked when the operation is complete.
|
||||||
|
* @return True when the operation is asynchronous. The caller must therefore call
|
||||||
|
* {@link UsbOperationInternal#waitForOperationComplete} for processing
|
||||||
|
* the result.
|
||||||
|
* False when the operation is synchronous. Caller can proceed reading the result
|
||||||
|
* through {@link UsbOperationInternal#getStatus}
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@RequiresPermission(Manifest.permission.MANAGE_USB)
|
||||||
|
boolean enableUsbData(@NonNull UsbPort port, boolean enable, int operationId,
|
||||||
|
IUsbOperationInternal callback) {
|
||||||
|
Objects.requireNonNull(port, "enableUsbData: port must not be null. opId:" + operationId);
|
||||||
|
try {
|
||||||
|
return mService.enableUsbData(port.getId(), enable, operationId, callback);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "enableUsbData: failed. opId:" + operationId, e);
|
||||||
|
try {
|
||||||
|
callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
} catch (RemoteException r) {
|
||||||
|
Log.e(TAG, "enableUsbData: failed to call onOperationComplete. opId:"
|
||||||
|
+ operationId, r);
|
||||||
|
}
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the component that will handle USB device connection.
|
* Sets the component that will handle USB device connection.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
131
core/java/android/hardware/usb/UsbOperationInternal.java
Normal file
131
core/java/android/hardware/usb/UsbOperationInternal.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* 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.annotation.IntDef;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
|
import android.hardware.usb.UsbPort;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.util.concurrent.locks.Condition;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
/**
|
||||||
|
* UsbOperationInternal allows UsbPort to support both synchronous and
|
||||||
|
* asynchronous function irrespective of whether the underlying hal
|
||||||
|
* method is synchronous or asynchronous.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public final class UsbOperationInternal extends IUsbOperationInternal.Stub {
|
||||||
|
private static final String TAG = "UsbPortStatus";
|
||||||
|
private final int mOperationID;
|
||||||
|
// Cached portId.
|
||||||
|
private final String mId;
|
||||||
|
// True implies operation did not timeout.
|
||||||
|
private boolean mOperationComplete;
|
||||||
|
private @UsbOperationStatus int mStatus;
|
||||||
|
final ReentrantLock mLock = new ReentrantLock();
|
||||||
|
final Condition mOperationWait = mLock.newCondition();
|
||||||
|
// Maximum time the caller has to wait for onOperationComplete to be called.
|
||||||
|
private static final int USB_OPERATION_TIMEOUT_MSECS = 5000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested operation was successfully completed.
|
||||||
|
* Returned in {@link onOperationComplete} and {@link getStatus}.
|
||||||
|
*/
|
||||||
|
public static final int USB_OPERATION_SUCCESS = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested operation failed due to internal error.
|
||||||
|
* Returned in {@link onOperationComplete} and {@link getStatus}.
|
||||||
|
*/
|
||||||
|
public static final int USB_OPERATION_ERROR_INTERNAL = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested operation failed as it's not supported.
|
||||||
|
* Returned in {@link onOperationComplete} and {@link getStatus}.
|
||||||
|
*/
|
||||||
|
public static final int USB_OPERATION_ERROR_NOT_SUPPORTED = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The requested operation failed as it's not supported.
|
||||||
|
* Returned in {@link onOperationComplete} and {@link getStatus}.
|
||||||
|
*/
|
||||||
|
public static final int USB_OPERATION_ERROR_PORT_MISMATCH = 3;
|
||||||
|
|
||||||
|
@IntDef(prefix = { "USB_OPERATION_" }, value = {
|
||||||
|
USB_OPERATION_SUCCESS,
|
||||||
|
USB_OPERATION_ERROR_INTERNAL,
|
||||||
|
USB_OPERATION_ERROR_NOT_SUPPORTED,
|
||||||
|
USB_OPERATION_ERROR_PORT_MISMATCH
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@interface UsbOperationStatus{}
|
||||||
|
|
||||||
|
UsbOperationInternal(int operationID, String id) {
|
||||||
|
this.mOperationID = operationID;
|
||||||
|
this.mId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hal glue layer would directly call this function when the requested
|
||||||
|
* operation is complete.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onOperationComplete(@UsbOperationStatus int status) {
|
||||||
|
mLock.lock();
|
||||||
|
try {
|
||||||
|
mOperationComplete = true;
|
||||||
|
mStatus = status;
|
||||||
|
Log.i(TAG, "Port:" + mId + " opID:" + mOperationID + " status:" + mStatus);
|
||||||
|
mOperationWait.signal();
|
||||||
|
} finally {
|
||||||
|
mLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caller invokes this function to wait for the operation to be complete.
|
||||||
|
*/
|
||||||
|
public void waitForOperationComplete() {
|
||||||
|
mLock.lock();
|
||||||
|
try {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long deadline = now + USB_OPERATION_TIMEOUT_MSECS;
|
||||||
|
// Wait in loop to overcome spurious wakeups.
|
||||||
|
do {
|
||||||
|
mOperationWait.await(deadline - System.currentTimeMillis(),
|
||||||
|
TimeUnit.MILLISECONDS);
|
||||||
|
} while (!mOperationComplete && System.currentTimeMillis() < deadline);
|
||||||
|
if (!mOperationComplete) {
|
||||||
|
Log.e(TAG, "Port:" + mId + " opID:" + mOperationID
|
||||||
|
+ " operationComplete not received in " + USB_OPERATION_TIMEOUT_MSECS
|
||||||
|
+ "msecs");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(TAG, "Port:" + mId + " opID:" + mOperationID + " operationComplete interrupted");
|
||||||
|
} finally {
|
||||||
|
mLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public @UsbOperationStatus int getStatus() {
|
||||||
|
return mOperationComplete ? mStatus : USB_OPERATION_ERROR_INTERNAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package android.hardware.usb;
|
package android.hardware.usb;
|
||||||
|
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_NOT_SUPPORTED;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_PORT_MISMATCH;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS;
|
||||||
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED;
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DETECTED;
|
||||||
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED;
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_DISABLED;
|
||||||
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;
|
||||||
@@ -34,15 +38,23 @@ import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
|
|||||||
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
|
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
|
||||||
|
|
||||||
import android.Manifest;
|
import android.Manifest;
|
||||||
|
import android.annotation.CheckResult;
|
||||||
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.annotation.RequiresPermission;
|
import android.annotation.RequiresPermission;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
|
import android.hardware.usb.UsbOperationInternal;
|
||||||
import android.hardware.usb.V1_0.Constants;
|
import android.hardware.usb.V1_0.Constants;
|
||||||
|
import android.os.Binder;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
import com.android.internal.util.Preconditions;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a physical USB port and describes its characteristics.
|
* Represents a physical USB port and describes its characteristics.
|
||||||
@@ -51,6 +63,7 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
public final class UsbPort {
|
public final class UsbPort {
|
||||||
|
private static final String TAG = "UsbPort";
|
||||||
private final String mId;
|
private final String mId;
|
||||||
private final int mSupportedModes;
|
private final int mSupportedModes;
|
||||||
private final UsbManager mUsbManager;
|
private final UsbManager mUsbManager;
|
||||||
@@ -64,6 +77,47 @@ public final class UsbPort {
|
|||||||
*/
|
*/
|
||||||
private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE;
|
private static final int POWER_ROLE_OFFSET = Constants.PortPowerRole.NONE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Counter for tracking UsbOperation operations.
|
||||||
|
*/
|
||||||
|
private static final AtomicInteger sUsbOperationCount = new AtomicInteger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #enableUsbData} request was successfully completed.
|
||||||
|
*/
|
||||||
|
public static final int ENABLE_USB_DATA_SUCCESS = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #enableUsbData} request failed due to internal error.
|
||||||
|
*/
|
||||||
|
public static final int ENABLE_USB_DATA_ERROR_INTERNAL = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #enableUsbData} request failed as it's not supported.
|
||||||
|
*/
|
||||||
|
public static final int ENABLE_USB_DATA_ERROR_NOT_SUPPORTED = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #enableUsbData} request failed as port id mismatched.
|
||||||
|
*/
|
||||||
|
public static final int ENABLE_USB_DATA_ERROR_PORT_MISMATCH = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #enableUsbData} request failed due to other reasons.
|
||||||
|
*/
|
||||||
|
public static final int ENABLE_USB_DATA_ERROR_OTHER = 4;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@IntDef(prefix = { "ENABLE_USB_DATA_" }, value = {
|
||||||
|
ENABLE_USB_DATA_SUCCESS,
|
||||||
|
ENABLE_USB_DATA_ERROR_INTERNAL,
|
||||||
|
ENABLE_USB_DATA_ERROR_NOT_SUPPORTED,
|
||||||
|
ENABLE_USB_DATA_ERROR_PORT_MISMATCH,
|
||||||
|
ENABLE_USB_DATA_ERROR_OTHER
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@interface EnableUsbDataStatus{}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
|
public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
|
||||||
int supportedContaminantProtectionModes,
|
int supportedContaminantProtectionModes,
|
||||||
@@ -157,7 +211,7 @@ public final class UsbPort {
|
|||||||
* {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}.
|
* {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}.
|
||||||
* </p><p>
|
* </p><p>
|
||||||
* Note: This function is asynchronous and may fail silently without applying
|
* Note: This function is asynchronous and may fail silently without applying
|
||||||
* the requested changes. If this function does cause a status change to occur then
|
* the operationed changes. If this function does cause a status change to occur then
|
||||||
* a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent.
|
* a {@link UsbManager#ACTION_USB_PORT_CHANGED} broadcast will be sent.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
@@ -176,6 +230,47 @@ public final class UsbPort {
|
|||||||
mUsbManager.setPortRoles(this, powerRole, dataRole);
|
mUsbManager.setPortRoles(this, powerRole, dataRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables/Disables Usb data on the port.
|
||||||
|
*
|
||||||
|
* @param enable When true enables USB data if disabled.
|
||||||
|
* When false disables USB data if enabled.
|
||||||
|
* @return {@link #ENABLE_USB_DATA_SUCCESS} when request completes successfully or
|
||||||
|
* {@link #ENABLE_USB_DATA_ERROR_INTERNAL} when request fails due to internal
|
||||||
|
* error or
|
||||||
|
* {@link ENABLE_USB_DATA_ERROR_NOT_SUPPORTED} when not supported or
|
||||||
|
* {@link ENABLE_USB_DATA_ERROR_PORT_MISMATCH} when request fails due to port id
|
||||||
|
* mismatch or
|
||||||
|
* {@link ENABLE_USB_DATA_ERROR_OTHER} when fails due to other reasons.
|
||||||
|
*/
|
||||||
|
@CheckResult
|
||||||
|
@RequiresPermission(Manifest.permission.MANAGE_USB)
|
||||||
|
public @EnableUsbDataStatus int enableUsbData(boolean enable) {
|
||||||
|
// UID is added To minimize operationID overlap between two different packages.
|
||||||
|
int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid();
|
||||||
|
Log.i(TAG, "enableUsbData opId:" + operationId
|
||||||
|
+ " callingUid:" + Binder.getCallingUid());
|
||||||
|
UsbOperationInternal opCallback =
|
||||||
|
new UsbOperationInternal(operationId, mId);
|
||||||
|
if (mUsbManager.enableUsbData(this, enable, operationId, opCallback) == true) {
|
||||||
|
opCallback.waitForOperationComplete();
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = opCallback.getStatus();
|
||||||
|
switch (result) {
|
||||||
|
case USB_OPERATION_SUCCESS:
|
||||||
|
return ENABLE_USB_DATA_SUCCESS;
|
||||||
|
case USB_OPERATION_ERROR_INTERNAL:
|
||||||
|
return ENABLE_USB_DATA_ERROR_INTERNAL;
|
||||||
|
case USB_OPERATION_ERROR_NOT_SUPPORTED:
|
||||||
|
return ENABLE_USB_DATA_ERROR_NOT_SUPPORTED;
|
||||||
|
case USB_OPERATION_ERROR_PORT_MISMATCH:
|
||||||
|
return ENABLE_USB_DATA_ERROR_PORT_MISMATCH;
|
||||||
|
default:
|
||||||
|
return ENABLE_USB_DATA_ERROR_OTHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
**/
|
**/
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ package android.hardware.usb;
|
|||||||
import android.annotation.IntDef;
|
import android.annotation.IntDef;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.SystemApi;
|
import android.annotation.SystemApi;
|
||||||
import android.hardware.usb.V1_0.Constants;
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
@@ -36,27 +35,29 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
@Immutable
|
@Immutable
|
||||||
@SystemApi
|
@SystemApi
|
||||||
public final class UsbPortStatus implements Parcelable {
|
public final class UsbPortStatus implements Parcelable {
|
||||||
|
private static final String TAG = "UsbPortStatus";
|
||||||
private final int mCurrentMode;
|
private final int mCurrentMode;
|
||||||
private final @UsbPowerRole int mCurrentPowerRole;
|
private final @UsbPowerRole int mCurrentPowerRole;
|
||||||
private final @UsbDataRole int mCurrentDataRole;
|
private final @UsbDataRole int mCurrentDataRole;
|
||||||
private final int mSupportedRoleCombinations;
|
private final int mSupportedRoleCombinations;
|
||||||
private final @ContaminantProtectionStatus int mContaminantProtectionStatus;
|
private final @ContaminantProtectionStatus int mContaminantProtectionStatus;
|
||||||
private final @ContaminantDetectionStatus int mContaminantDetectionStatus;
|
private final @ContaminantDetectionStatus int mContaminantDetectionStatus;
|
||||||
|
private final boolean mUsbDataEnabled;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Power role: This USB port does not have a power role.
|
* Power role: This USB port does not have a power role.
|
||||||
*/
|
*/
|
||||||
public static final int POWER_ROLE_NONE = Constants.PortPowerRole.NONE;
|
public static final int POWER_ROLE_NONE = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Power role: This USB port can act as a source (provide power).
|
* Power role: This USB port can act as a source (provide power).
|
||||||
*/
|
*/
|
||||||
public static final int POWER_ROLE_SOURCE = Constants.PortPowerRole.SOURCE;
|
public static final int POWER_ROLE_SOURCE = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Power role: This USB port can act as a sink (receive power).
|
* Power role: This USB port can act as a sink (receive power).
|
||||||
*/
|
*/
|
||||||
public static final int POWER_ROLE_SINK = Constants.PortPowerRole.SINK;
|
public static final int POWER_ROLE_SINK = 2;
|
||||||
|
|
||||||
@IntDef(prefix = { "POWER_ROLE_" }, value = {
|
@IntDef(prefix = { "POWER_ROLE_" }, value = {
|
||||||
POWER_ROLE_NONE,
|
POWER_ROLE_NONE,
|
||||||
@@ -69,17 +70,17 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
/**
|
/**
|
||||||
* Power role: This USB port does not have a data role.
|
* Power role: This USB port does not have a data role.
|
||||||
*/
|
*/
|
||||||
public static final int DATA_ROLE_NONE = Constants.PortDataRole.NONE;
|
public static final int DATA_ROLE_NONE = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data role: This USB port can act as a host (access data services).
|
* Data role: This USB port can act as a host (access data services).
|
||||||
*/
|
*/
|
||||||
public static final int DATA_ROLE_HOST = Constants.PortDataRole.HOST;
|
public static final int DATA_ROLE_HOST = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data role: This USB port can act as a device (offer data services).
|
* Data role: This USB port can act as a device (offer data services).
|
||||||
*/
|
*/
|
||||||
public static final int DATA_ROLE_DEVICE = Constants.PortDataRole.DEVICE;
|
public static final int DATA_ROLE_DEVICE = 2;
|
||||||
|
|
||||||
@IntDef(prefix = { "DATA_ROLE_" }, value = {
|
@IntDef(prefix = { "DATA_ROLE_" }, value = {
|
||||||
DATA_ROLE_NONE,
|
DATA_ROLE_NONE,
|
||||||
@@ -92,15 +93,7 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
/**
|
/**
|
||||||
* There is currently nothing connected to this USB port.
|
* There is currently nothing connected to this USB port.
|
||||||
*/
|
*/
|
||||||
public static final int MODE_NONE = Constants.PortMode.NONE;
|
public static final int MODE_NONE = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* This USB port can act as a downstream facing port (host).
|
|
||||||
*
|
|
||||||
* <p> Implies that the port supports the {@link #POWER_ROLE_SOURCE} and
|
|
||||||
* {@link #DATA_ROLE_HOST} combination of roles (and possibly others as well).
|
|
||||||
*/
|
|
||||||
public static final int MODE_DFP = Constants.PortMode.DFP;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This USB port can act as an upstream facing port (device).
|
* This USB port can act as an upstream facing port (device).
|
||||||
@@ -108,7 +101,15 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
* <p> Implies that the port supports the {@link #POWER_ROLE_SINK} and
|
* <p> Implies that the port supports the {@link #POWER_ROLE_SINK} and
|
||||||
* {@link #DATA_ROLE_DEVICE} combination of roles (and possibly others as well).
|
* {@link #DATA_ROLE_DEVICE} combination of roles (and possibly others as well).
|
||||||
*/
|
*/
|
||||||
public static final int MODE_UFP = Constants.PortMode.UFP;
|
public static final int MODE_UFP = 1 << 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This USB port can act as a downstream facing port (host).
|
||||||
|
*
|
||||||
|
* <p> Implies that the port supports the {@link #POWER_ROLE_SOURCE} and
|
||||||
|
* {@link #DATA_ROLE_HOST} combination of roles (and possibly others as well).
|
||||||
|
*/
|
||||||
|
public static final int MODE_DFP = 1 << 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This USB port can act either as an downstream facing port (host) or as
|
* This USB port can act either as an downstream facing port (host) or as
|
||||||
@@ -120,87 +121,76 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int MODE_DUAL = Constants.PortMode.DRP;
|
public static final int MODE_DUAL = MODE_UFP | MODE_DFP;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This USB port can support USB Type-C Audio accessory.
|
* This USB port can support USB Type-C Audio accessory.
|
||||||
*/
|
*/
|
||||||
public static final int MODE_AUDIO_ACCESSORY =
|
public static final int MODE_AUDIO_ACCESSORY = 1 << 2;
|
||||||
android.hardware.usb.V1_1.Constants.PortMode_1_1.AUDIO_ACCESSORY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This USB port can support USB Type-C debug accessory.
|
* This USB port can support USB Type-C debug accessory.
|
||||||
*/
|
*/
|
||||||
public static final int MODE_DEBUG_ACCESSORY =
|
public static final int MODE_DEBUG_ACCESSORY = 1 << 3;
|
||||||
android.hardware.usb.V1_1.Constants.PortMode_1_1.DEBUG_ACCESSORY;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant presence detection not supported by the device.
|
* Contaminant presence detection not supported by the device.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_DETECTION_NOT_SUPPORTED =
|
public static final int CONTAMINANT_DETECTION_NOT_SUPPORTED = 0;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.NOT_SUPPORTED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant presence detection supported but disabled.
|
* Contaminant presence detection supported but disabled.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_DETECTION_DISABLED =
|
public static final int CONTAMINANT_DETECTION_DISABLED = 1;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.DISABLED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant presence enabled but not detected.
|
* Contaminant presence enabled but not detected.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_DETECTION_NOT_DETECTED =
|
public static final int CONTAMINANT_DETECTION_NOT_DETECTED = 2;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.NOT_DETECTED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant presence enabled and detected.
|
* Contaminant presence enabled and detected.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_DETECTION_DETECTED =
|
public static final int CONTAMINANT_DETECTION_DETECTED = 3;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.DETECTED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant protection - No action performed upon detection of
|
* Contaminant protection - No action performed upon detection of
|
||||||
* contaminant presence.
|
* contaminant presence.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_PROTECTION_NONE =
|
public static final int CONTAMINANT_PROTECTION_NONE = 0;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.NONE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant protection - Port is forced to sink upon detection of
|
* Contaminant protection - Port is forced to sink upon detection of
|
||||||
* contaminant presence.
|
* contaminant presence.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_PROTECTION_SINK =
|
public static final int CONTAMINANT_PROTECTION_SINK = 1 << 0;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_SINK;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant protection - Port is forced to source upon detection of
|
* Contaminant protection - Port is forced to source upon detection of
|
||||||
* contaminant presence.
|
* contaminant presence.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_PROTECTION_SOURCE =
|
public static final int CONTAMINANT_PROTECTION_SOURCE = 1 << 1;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_SOURCE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant protection - Port is disabled upon detection of
|
* Contaminant protection - Port is disabled upon detection of
|
||||||
* contaminant presence.
|
* contaminant presence.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_PROTECTION_FORCE_DISABLE =
|
public static final int CONTAMINANT_PROTECTION_FORCE_DISABLE = 1 << 2;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_DISABLE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contaminant protection - Port is disabled upon detection of
|
* Contaminant protection - Port is disabled upon detection of
|
||||||
* contaminant presence.
|
* contaminant presence.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static final int CONTAMINANT_PROTECTION_DISABLED =
|
public static final int CONTAMINANT_PROTECTION_DISABLED = 1 << 3;
|
||||||
android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.DISABLED;
|
|
||||||
|
|
||||||
@IntDef(prefix = { "CONTAMINANT_DETECTION_" }, value = {
|
@IntDef(prefix = { "CONTAMINANT_DETECTION_" }, value = {
|
||||||
CONTAMINANT_DETECTION_NOT_SUPPORTED,
|
CONTAMINANT_DETECTION_NOT_SUPPORTED,
|
||||||
@@ -231,6 +221,19 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
@Retention(RetentionPolicy.SOURCE)
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
@interface UsbPortMode{}
|
@interface UsbPortMode{}
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
|
||||||
|
int supportedRoleCombinations, int contaminantProtectionStatus,
|
||||||
|
int contaminantDetectionStatus, boolean usbDataEnabled) {
|
||||||
|
mCurrentMode = currentMode;
|
||||||
|
mCurrentPowerRole = currentPowerRole;
|
||||||
|
mCurrentDataRole = currentDataRole;
|
||||||
|
mSupportedRoleCombinations = supportedRoleCombinations;
|
||||||
|
mContaminantProtectionStatus = contaminantProtectionStatus;
|
||||||
|
mContaminantDetectionStatus = contaminantDetectionStatus;
|
||||||
|
mUsbDataEnabled = usbDataEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
|
public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
|
||||||
int supportedRoleCombinations, int contaminantProtectionStatus,
|
int supportedRoleCombinations, int contaminantProtectionStatus,
|
||||||
@@ -241,6 +244,7 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
mSupportedRoleCombinations = supportedRoleCombinations;
|
mSupportedRoleCombinations = supportedRoleCombinations;
|
||||||
mContaminantProtectionStatus = contaminantProtectionStatus;
|
mContaminantProtectionStatus = contaminantProtectionStatus;
|
||||||
mContaminantDetectionStatus = contaminantDetectionStatus;
|
mContaminantDetectionStatus = contaminantDetectionStatus;
|
||||||
|
mUsbDataEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,6 +327,15 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
return mContaminantProtectionStatus;
|
return mContaminantProtectionStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns UsbData status.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean getUsbDataStatus() {
|
||||||
|
return mUsbDataEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@@ -336,6 +349,8 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
+ getContaminantDetectionStatus()
|
+ getContaminantDetectionStatus()
|
||||||
+ ", contaminantProtectionStatus="
|
+ ", contaminantProtectionStatus="
|
||||||
+ getContaminantProtectionStatus()
|
+ getContaminantProtectionStatus()
|
||||||
|
+ ", usbDataEnabled="
|
||||||
|
+ getUsbDataStatus()
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,6 +367,7 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
dest.writeInt(mSupportedRoleCombinations);
|
dest.writeInt(mSupportedRoleCombinations);
|
||||||
dest.writeInt(mContaminantProtectionStatus);
|
dest.writeInt(mContaminantProtectionStatus);
|
||||||
dest.writeInt(mContaminantDetectionStatus);
|
dest.writeInt(mContaminantDetectionStatus);
|
||||||
|
dest.writeBoolean(mUsbDataEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR =
|
public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR =
|
||||||
@@ -364,9 +380,10 @@ public final class UsbPortStatus implements Parcelable {
|
|||||||
int supportedRoleCombinations = in.readInt();
|
int supportedRoleCombinations = in.readInt();
|
||||||
int contaminantProtectionStatus = in.readInt();
|
int contaminantProtectionStatus = in.readInt();
|
||||||
int contaminantDetectionStatus = in.readInt();
|
int contaminantDetectionStatus = in.readInt();
|
||||||
|
boolean usbDataEnabled = in.readBoolean();
|
||||||
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
|
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
|
||||||
supportedRoleCombinations, contaminantProtectionStatus,
|
supportedRoleCombinations, contaminantProtectionStatus,
|
||||||
contaminantDetectionStatus);
|
contaminantDetectionStatus, usbDataEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -244,7 +244,8 @@ public class DumpUtils {
|
|||||||
writeContaminantPresenceStatus(dump, "contaminant_presence_status",
|
writeContaminantPresenceStatus(dump, "contaminant_presence_status",
|
||||||
UsbPortStatusProto.CONTAMINANT_PRESENCE_STATUS,
|
UsbPortStatusProto.CONTAMINANT_PRESENCE_STATUS,
|
||||||
status.getContaminantDetectionStatus());
|
status.getContaminantDetectionStatus());
|
||||||
|
dump.write("usb_data_enabled", UsbPortStatusProto.USB_DATA_ENABLED,
|
||||||
|
status.getUsbDataStatus());
|
||||||
dump.end(token);
|
dump.end(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,9 +195,19 @@ message UsbIsHeadsetProto {
|
|||||||
message UsbPortManagerProto {
|
message UsbPortManagerProto {
|
||||||
option (android.msg_privacy).dest = DEST_AUTOMATIC;
|
option (android.msg_privacy).dest = DEST_AUTOMATIC;
|
||||||
|
|
||||||
|
enum HalVersion {
|
||||||
|
V_UNKNOWN = 0;
|
||||||
|
V1_0 = 10;
|
||||||
|
V1_1 = 11;
|
||||||
|
V1_2 = 12;
|
||||||
|
V1_3 = 13;
|
||||||
|
V2 = 20;
|
||||||
|
}
|
||||||
|
|
||||||
optional bool is_simulation_active = 1;
|
optional bool is_simulation_active = 1;
|
||||||
repeated UsbPortInfoProto usb_ports = 2;
|
repeated UsbPortInfoProto usb_ports = 2;
|
||||||
optional bool enable_usb_data_signaling = 3;
|
optional bool enable_usb_data_signaling = 3;
|
||||||
|
optional HalVersion hal_version = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UsbPortInfoProto {
|
message UsbPortInfoProto {
|
||||||
@@ -253,6 +263,7 @@ message UsbPortStatusProto {
|
|||||||
optional DataRole data_role = 4;
|
optional DataRole data_role = 4;
|
||||||
repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
|
repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
|
||||||
optional android.service.ContaminantPresenceStatus contaminant_presence_status = 6;
|
optional android.service.ContaminantPresenceStatus contaminant_presence_status = 6;
|
||||||
|
optional bool usb_data_enabled = 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UsbPortStatusRoleCombinationProto {
|
message UsbPortStatusRoleCombinationProto {
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ java_library_static {
|
|||||||
"android.hardware.usb-V1.1-java",
|
"android.hardware.usb-V1.1-java",
|
||||||
"android.hardware.usb-V1.2-java",
|
"android.hardware.usb-V1.2-java",
|
||||||
"android.hardware.usb-V1.3-java",
|
"android.hardware.usb-V1.3-java",
|
||||||
|
"android.hardware.usb-V1-java",
|
||||||
"android.hardware.usb.gadget-V1.0-java",
|
"android.hardware.usb.gadget-V1.0-java",
|
||||||
"android.hardware.usb.gadget-V1.1-java",
|
"android.hardware.usb.gadget-V1.1-java",
|
||||||
"android.hardware.usb.gadget-V1.2-java",
|
"android.hardware.usb.gadget-V1.2-java",
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.server.usb;
|
package com.android.server.usb;
|
||||||
|
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_PORT_MISMATCH;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
|
||||||
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
|
||||||
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
|
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
|
||||||
@@ -25,6 +27,12 @@ import static android.hardware.usb.UsbPortStatus.MODE_DUAL;
|
|||||||
import static android.hardware.usb.UsbPortStatus.MODE_UFP;
|
import static android.hardware.usb.UsbPortStatus.MODE_UFP;
|
||||||
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
|
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
|
||||||
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
|
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
|
||||||
|
import static com.android.server.usb.hal.port.UsbPortHal.HAL_POWER_ROLE_SOURCE;
|
||||||
|
import static com.android.server.usb.hal.port.UsbPortHal.HAL_POWER_ROLE_SINK;
|
||||||
|
import static com.android.server.usb.hal.port.UsbPortHal.HAL_DATA_ROLE_HOST;
|
||||||
|
import static com.android.server.usb.hal.port.UsbPortHal.HAL_DATA_ROLE_DEVICE;
|
||||||
|
import static com.android.server.usb.hal.port.UsbPortHal.HAL_MODE_DFP;
|
||||||
|
import static com.android.server.usb.hal.port.UsbPortHal.HAL_MODE_UFP;
|
||||||
|
|
||||||
import static com.android.internal.usb.DumpUtils.writePort;
|
import static com.android.internal.usb.DumpUtils.writePort;
|
||||||
import static com.android.internal.usb.DumpUtils.writePortStatus;
|
import static com.android.internal.usb.DumpUtils.writePortStatus;
|
||||||
@@ -38,6 +46,7 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
import android.hardware.usb.ParcelableUsbPort;
|
import android.hardware.usb.ParcelableUsbPort;
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
import android.hardware.usb.UsbPort;
|
import android.hardware.usb.UsbPort;
|
||||||
@@ -74,9 +83,13 @@ import com.android.internal.util.FrameworkStatsLog;
|
|||||||
import com.android.internal.util.IndentingPrintWriter;
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
import com.android.internal.util.dump.DualDumpOutputStream;
|
import com.android.internal.util.dump.DualDumpOutputStream;
|
||||||
import com.android.server.FgThread;
|
import com.android.server.FgThread;
|
||||||
|
import com.android.server.usb.hal.port.RawPortInfo;
|
||||||
|
import com.android.server.usb.hal.port.UsbPortHal;
|
||||||
|
import com.android.server.usb.hal.port.UsbPortHalInstance;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows trusted components to control the properties of physical USB ports
|
* Allows trusted components to control the properties of physical USB ports
|
||||||
@@ -109,16 +122,9 @@ public class UsbPortManager {
|
|||||||
// The system context.
|
// The system context.
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
|
||||||
// Proxy object for the usb hal daemon.
|
|
||||||
@GuardedBy("mLock")
|
|
||||||
private IUsb mProxy = null;
|
|
||||||
|
|
||||||
// Callback when the UsbPort status is changed by the kernel.
|
// Callback when the UsbPort status is changed by the kernel.
|
||||||
// Mostly due a command sent by the remote Usb device.
|
// Mostly due a command sent by the remote Usb device.
|
||||||
private HALCallback mHALCallback = new HALCallback(null, this);
|
//private HALCallback mHALCallback = new HALCallback(null, this);
|
||||||
|
|
||||||
// Cookie sent for usb hal death notification.
|
|
||||||
private static final int USB_HAL_DEATH_COOKIE = 1000;
|
|
||||||
|
|
||||||
// Used as the key while sending the bundle to Main thread.
|
// Used as the key while sending the bundle to Main thread.
|
||||||
private static final String PORT_INFO = "port_info";
|
private static final String PORT_INFO = "port_info";
|
||||||
@@ -156,36 +162,23 @@ public class UsbPortManager {
|
|||||||
*/
|
*/
|
||||||
private int mIsPortContaminatedNotificationId;
|
private int mIsPortContaminatedNotificationId;
|
||||||
|
|
||||||
private boolean mEnableUsbDataSignaling;
|
private UsbPortHal mUsbPortHal;
|
||||||
protected int mCurrentUsbHalVersion;
|
|
||||||
|
private long mTransactionId;
|
||||||
|
|
||||||
public UsbPortManager(Context context) {
|
public UsbPortManager(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
try {
|
mUsbPortHal = UsbPortHalInstance.getInstance(this, null);
|
||||||
ServiceNotification serviceNotification = new ServiceNotification();
|
logAndPrint(Log.DEBUG, null, "getInstance done");
|
||||||
|
|
||||||
boolean ret = IServiceManager.getService()
|
|
||||||
.registerForNotifications("android.hardware.usb@1.0::IUsb",
|
|
||||||
"", serviceNotification);
|
|
||||||
if (!ret) {
|
|
||||||
logAndPrint(Log.ERROR, null,
|
|
||||||
"Failed to register service start notification");
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
logAndPrintException(null,
|
|
||||||
"Failed to register service start notification", e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
connectToProxy(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void systemReady() {
|
public void systemReady() {
|
||||||
mSystemReady = true;
|
mSystemReady = true;
|
||||||
if (mProxy != null) {
|
if (mUsbPortHal != null) {
|
||||||
|
mUsbPortHal.systemReady();
|
||||||
try {
|
try {
|
||||||
mProxy.queryPortStatus();
|
mUsbPortHal.queryPortStatus(++mTransactionId);
|
||||||
mEnableUsbDataSignaling = true;
|
} catch (Exception e) {
|
||||||
} catch (RemoteException e) {
|
|
||||||
logAndPrintException(null,
|
logAndPrintException(null,
|
||||||
"ServiceStart: Failed to query port status", e);
|
"ServiceStart: Failed to query port status", e);
|
||||||
}
|
}
|
||||||
@@ -340,13 +333,9 @@ public class UsbPortManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Oneway call into the hal. Use the castFrom method from HIDL.
|
mUsbPortHal.enableContaminantPresenceDetection(portId, enable, ++mTransactionId);
|
||||||
android.hardware.usb.V1_2.IUsb proxy = android.hardware.usb.V1_2.IUsb.castFrom(mProxy);
|
} catch (Exception e) {
|
||||||
proxy.enableContaminantPresenceDetection(portId, enable);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
logAndPrintException(pw, "Failed to set contaminant detection", e);
|
logAndPrintException(pw, "Failed to set contaminant detection", e);
|
||||||
} catch (ClassCastException e) {
|
|
||||||
logAndPrintException(pw, "Method only applicable to V1.2 or above implementation", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,46 +344,79 @@ public class UsbPortManager {
|
|||||||
*
|
*
|
||||||
* @param enable enable or disable USB data signaling
|
* @param enable enable or disable USB data signaling
|
||||||
*/
|
*/
|
||||||
public boolean enableUsbDataSignal(boolean enable) {
|
public boolean enableUsbData(@NonNull String portId, boolean enable, int transactionId,
|
||||||
try {
|
@NonNull IUsbOperationInternal callback, IndentingPrintWriter pw) {
|
||||||
mEnableUsbDataSignaling = enable;
|
Objects.requireNonNull(callback);
|
||||||
// Call into the hal. Use the castFrom method from HIDL.
|
Objects.requireNonNull(portId);
|
||||||
android.hardware.usb.V1_3.IUsb proxy = android.hardware.usb.V1_3.IUsb.castFrom(mProxy);
|
final PortInfo portInfo = mPorts.get(portId);
|
||||||
return proxy.enableUsbDataSignal(enable);
|
if (portInfo == null) {
|
||||||
} catch (RemoteException e) {
|
logAndPrint(Log.ERROR, pw, "enableUsbData: No such port: " + portId
|
||||||
logAndPrintException(null, "Failed to set USB data signaling", e);
|
+ " opId:" + transactionId);
|
||||||
return false;
|
try {
|
||||||
} catch (ClassCastException e) {
|
callback.onOperationComplete(USB_OPERATION_ERROR_PORT_MISMATCH);
|
||||||
logAndPrintException(null, "Method only applicable to V1.3 or above implementation", e);
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(pw,
|
||||||
|
"enableUsbData: Failed to call OperationComplete. opId:"
|
||||||
|
+ transactionId, e);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
return mUsbPortHal.enableUsbData(portId, enable, transactionId, callback);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logAndPrintException(pw,
|
||||||
|
"enableUsbData: Failed to invoke enableUsbData. opId:"
|
||||||
|
+ transactionId , e);
|
||||||
|
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(pw,
|
||||||
|
"enableUsbData: Failed to call onOperationComplete. opId:"
|
||||||
|
+ transactionId, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get USB HAL version
|
* Get USB HAL version
|
||||||
*
|
*
|
||||||
* @param none
|
* @param none
|
||||||
|
* @return {@link UsbManager#USB_HAL_RETRY} returned when hal version
|
||||||
|
* is yet to be determined.
|
||||||
*/
|
*/
|
||||||
public int getUsbHalVersion() {
|
public int getUsbHalVersion() {
|
||||||
return mCurrentUsbHalVersion;
|
if (mUsbPortHal != null) {
|
||||||
|
try {
|
||||||
|
return mUsbPortHal.getUsbHalVersion();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
return UsbManager.USB_HAL_RETRY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UsbManager.USB_HAL_RETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private int toHalUsbDataRole(int usbDataRole) {
|
||||||
* update USB HAL version
|
if (usbDataRole == DATA_ROLE_DEVICE)
|
||||||
*
|
return HAL_DATA_ROLE_DEVICE;
|
||||||
* @param none
|
else
|
||||||
*/
|
return HAL_DATA_ROLE_HOST;
|
||||||
private void updateUsbHalVersion() {
|
}
|
||||||
if (android.hardware.usb.V1_3.IUsb.castFrom(mProxy) != null) {
|
|
||||||
mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_3;
|
private int toHalUsbPowerRole(int usbPowerRole) {
|
||||||
} else if (android.hardware.usb.V1_2.IUsb.castFrom(mProxy) != null) {
|
if (usbPowerRole == POWER_ROLE_SINK)
|
||||||
mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_2;
|
return HAL_POWER_ROLE_SINK;
|
||||||
} else if (android.hardware.usb.V1_1.IUsb.castFrom(mProxy) != null) {
|
else
|
||||||
mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_1;
|
return HAL_POWER_ROLE_SOURCE;
|
||||||
} else {
|
}
|
||||||
mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_0;
|
|
||||||
}
|
private int toHalUsbMode(int usbMode) {
|
||||||
logAndPrint(Log.INFO, null, "USB HAL version: " + mCurrentUsbHalVersion);
|
if (usbMode == MODE_UFP)
|
||||||
|
return HAL_MODE_UFP;
|
||||||
|
else
|
||||||
|
return HAL_MODE_DFP;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPortRoles(String portId, int newPowerRole, int newDataRole,
|
public void setPortRoles(String portId, int newPowerRole, int newDataRole,
|
||||||
@@ -473,7 +495,7 @@ public class UsbPortManager {
|
|||||||
sim.currentPowerRole = newPowerRole;
|
sim.currentPowerRole = newPowerRole;
|
||||||
sim.currentDataRole = newDataRole;
|
sim.currentDataRole = newDataRole;
|
||||||
updatePortsLocked(pw, null);
|
updatePortsLocked(pw, null);
|
||||||
} else if (mProxy != null) {
|
} else if (mUsbPortHal != null) {
|
||||||
if (currentMode != newMode) {
|
if (currentMode != newMode) {
|
||||||
// Changing the mode will have the side-effect of also changing
|
// Changing the mode will have the side-effect of also changing
|
||||||
// the power and data roles but it might take some time to apply
|
// the power and data roles but it might take some time to apply
|
||||||
@@ -485,44 +507,37 @@ public class UsbPortManager {
|
|||||||
logAndPrint(Log.ERROR, pw, "Trying to set the USB port mode: "
|
logAndPrint(Log.ERROR, pw, "Trying to set the USB port mode: "
|
||||||
+ "portId=" + portId
|
+ "portId=" + portId
|
||||||
+ ", newMode=" + UsbPort.modeToString(newMode));
|
+ ", newMode=" + UsbPort.modeToString(newMode));
|
||||||
PortRole newRole = new PortRole();
|
|
||||||
newRole.type = PortRoleType.MODE;
|
|
||||||
newRole.role = newMode;
|
|
||||||
try {
|
try {
|
||||||
mProxy.switchRole(portId, newRole);
|
mUsbPortHal.switchMode(portId, toHalUsbMode(newMode), ++mTransactionId);
|
||||||
} catch (RemoteException e) {
|
} catch (Exception e) {
|
||||||
logAndPrintException(pw, "Failed to set the USB port mode: "
|
logAndPrintException(pw, "Failed to set the USB port mode: "
|
||||||
+ "portId=" + portId
|
+ "portId=" + portId
|
||||||
+ ", newMode=" + UsbPort.modeToString(newRole.role), e);
|
+ ", newMode=" + UsbPort.modeToString(newMode), e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Change power and data role independently as needed.
|
// Change power and data role independently as needed.
|
||||||
if (currentPowerRole != newPowerRole) {
|
if (currentPowerRole != newPowerRole) {
|
||||||
PortRole newRole = new PortRole();
|
|
||||||
newRole.type = PortRoleType.POWER_ROLE;
|
|
||||||
newRole.role = newPowerRole;
|
|
||||||
try {
|
try {
|
||||||
mProxy.switchRole(portId, newRole);
|
mUsbPortHal.switchPowerRole(portId, toHalUsbPowerRole(newPowerRole),
|
||||||
} catch (RemoteException e) {
|
++mTransactionId);
|
||||||
|
} catch (Exception e) {
|
||||||
logAndPrintException(pw, "Failed to set the USB port power role: "
|
logAndPrintException(pw, "Failed to set the USB port power role: "
|
||||||
+ "portId=" + portId
|
+ "portId=" + portId
|
||||||
+ ", newPowerRole=" + UsbPort.powerRoleToString
|
+ ", newPowerRole=" + UsbPort.powerRoleToString
|
||||||
(newRole.role),
|
(newPowerRole),
|
||||||
e);
|
e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (currentDataRole != newDataRole) {
|
if (currentDataRole != newDataRole) {
|
||||||
PortRole newRole = new PortRole();
|
|
||||||
newRole.type = PortRoleType.DATA_ROLE;
|
|
||||||
newRole.role = newDataRole;
|
|
||||||
try {
|
try {
|
||||||
mProxy.switchRole(portId, newRole);
|
mUsbPortHal.switchDataRole(portId, toHalUsbDataRole(newDataRole),
|
||||||
} catch (RemoteException e) {
|
++mTransactionId);
|
||||||
|
} catch (Exception e) {
|
||||||
logAndPrintException(pw, "Failed to set the USB port data role: "
|
logAndPrintException(pw, "Failed to set the USB port data role: "
|
||||||
+ "portId=" + portId
|
+ "portId=" + portId
|
||||||
+ ", newDataRole=" + UsbPort.dataRoleToString(newRole
|
+ ", newDataRole=" + UsbPort.dataRoleToString
|
||||||
.role),
|
(newDataRole),
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -531,6 +546,15 @@ public class UsbPortManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updatePorts(ArrayList<RawPortInfo> newPortInfo) {
|
||||||
|
Message message = mHandler.obtainMessage();
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
|
||||||
|
message.what = MSG_UPDATE_PORTS;
|
||||||
|
message.setData(bundle);
|
||||||
|
mHandler.sendMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
public void addSimulatedPort(String portId, int supportedModes, IndentingPrintWriter pw) {
|
public void addSimulatedPort(String portId, int supportedModes, IndentingPrintWriter pw) {
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mSimulatedPorts.containsKey(portId)) {
|
if (mSimulatedPorts.containsKey(portId)) {
|
||||||
@@ -662,191 +686,12 @@ public class UsbPortManager {
|
|||||||
portInfo.dump(dump, "usb_ports", UsbPortManagerProto.USB_PORTS);
|
portInfo.dump(dump, "usb_ports", UsbPortManagerProto.USB_PORTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
dump.write("enable_usb_data_signaling", UsbPortManagerProto.ENABLE_USB_DATA_SIGNALING,
|
dump.write("usb_hal_version", UsbPortManagerProto.HAL_VERSION, getUsbHalVersion());
|
||||||
mEnableUsbDataSignaling);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dump.end(token);
|
dump.end(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class HALCallback extends IUsbCallback.Stub {
|
|
||||||
public IndentingPrintWriter pw;
|
|
||||||
public UsbPortManager portManager;
|
|
||||||
|
|
||||||
HALCallback(IndentingPrintWriter pw, UsbPortManager portManager) {
|
|
||||||
this.pw = pw;
|
|
||||||
this.portManager = portManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyPortStatusChange(
|
|
||||||
ArrayList<android.hardware.usb.V1_0.PortStatus> currentPortStatus, int retval) {
|
|
||||||
if (!portManager.mSystemReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval != Status.SUCCESS) {
|
|
||||||
logAndPrint(Log.ERROR, pw, "port status enquiry failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
|
||||||
|
|
||||||
for (android.hardware.usb.V1_0.PortStatus current : currentPortStatus) {
|
|
||||||
RawPortInfo temp = new RawPortInfo(current.portName,
|
|
||||||
current.supportedModes, CONTAMINANT_PROTECTION_NONE,
|
|
||||||
current.currentMode,
|
|
||||||
current.canChangeMode, current.currentPowerRole,
|
|
||||||
current.canChangePowerRole,
|
|
||||||
current.currentDataRole, current.canChangeDataRole,
|
|
||||||
false, CONTAMINANT_PROTECTION_NONE,
|
|
||||||
false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
|
|
||||||
newPortInfo.add(temp);
|
|
||||||
logAndPrint(Log.INFO, pw, "ClientCallback V1_0: " + current.portName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message message = portManager.mHandler.obtainMessage();
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
|
|
||||||
message.what = MSG_UPDATE_PORTS;
|
|
||||||
message.setData(bundle);
|
|
||||||
portManager.mHandler.sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void notifyPortStatusChange_1_1(ArrayList<PortStatus_1_1> currentPortStatus,
|
|
||||||
int retval) {
|
|
||||||
if (!portManager.mSystemReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval != Status.SUCCESS) {
|
|
||||||
logAndPrint(Log.ERROR, pw, "port status enquiry failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
|
||||||
|
|
||||||
int numStatus = currentPortStatus.size();
|
|
||||||
for (int i = 0; i < numStatus; i++) {
|
|
||||||
PortStatus_1_1 current = currentPortStatus.get(i);
|
|
||||||
RawPortInfo temp = new RawPortInfo(current.status.portName,
|
|
||||||
current.supportedModes, CONTAMINANT_PROTECTION_NONE,
|
|
||||||
current.currentMode,
|
|
||||||
current.status.canChangeMode, current.status.currentPowerRole,
|
|
||||||
current.status.canChangePowerRole,
|
|
||||||
current.status.currentDataRole, current.status.canChangeDataRole,
|
|
||||||
false, CONTAMINANT_PROTECTION_NONE,
|
|
||||||
false, CONTAMINANT_DETECTION_NOT_SUPPORTED);
|
|
||||||
newPortInfo.add(temp);
|
|
||||||
logAndPrint(Log.INFO, pw, "ClientCallback V1_1: " + current.status.portName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message message = portManager.mHandler.obtainMessage();
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
|
|
||||||
message.what = MSG_UPDATE_PORTS;
|
|
||||||
message.setData(bundle);
|
|
||||||
portManager.mHandler.sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyPortStatusChange_1_2(
|
|
||||||
ArrayList<PortStatus> currentPortStatus, int retval) {
|
|
||||||
if (!portManager.mSystemReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval != Status.SUCCESS) {
|
|
||||||
logAndPrint(Log.ERROR, pw, "port status enquiry failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
|
||||||
|
|
||||||
int numStatus = currentPortStatus.size();
|
|
||||||
for (int i = 0; i < numStatus; i++) {
|
|
||||||
PortStatus current = currentPortStatus.get(i);
|
|
||||||
RawPortInfo temp = new RawPortInfo(current.status_1_1.status.portName,
|
|
||||||
current.status_1_1.supportedModes,
|
|
||||||
current.supportedContaminantProtectionModes,
|
|
||||||
current.status_1_1.currentMode,
|
|
||||||
current.status_1_1.status.canChangeMode,
|
|
||||||
current.status_1_1.status.currentPowerRole,
|
|
||||||
current.status_1_1.status.canChangePowerRole,
|
|
||||||
current.status_1_1.status.currentDataRole,
|
|
||||||
current.status_1_1.status.canChangeDataRole,
|
|
||||||
current.supportsEnableContaminantPresenceProtection,
|
|
||||||
current.contaminantProtectionStatus,
|
|
||||||
current.supportsEnableContaminantPresenceDetection,
|
|
||||||
current.contaminantDetectionStatus);
|
|
||||||
newPortInfo.add(temp);
|
|
||||||
logAndPrint(Log.INFO, pw, "ClientCallback V1_2: "
|
|
||||||
+ current.status_1_1.status.portName);
|
|
||||||
}
|
|
||||||
|
|
||||||
Message message = portManager.mHandler.obtainMessage();
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putParcelableArrayList(PORT_INFO, newPortInfo);
|
|
||||||
message.what = MSG_UPDATE_PORTS;
|
|
||||||
message.setData(bundle);
|
|
||||||
portManager.mHandler.sendMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyRoleSwitchStatus(String portName, PortRole role, int retval) {
|
|
||||||
if (retval == Status.SUCCESS) {
|
|
||||||
logAndPrint(Log.INFO, pw, portName + " role switch successful");
|
|
||||||
} else {
|
|
||||||
logAndPrint(Log.ERROR, pw, portName + " role switch failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class DeathRecipient implements HwBinder.DeathRecipient {
|
|
||||||
public IndentingPrintWriter pw;
|
|
||||||
|
|
||||||
DeathRecipient(IndentingPrintWriter pw) {
|
|
||||||
this.pw = pw;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void serviceDied(long cookie) {
|
|
||||||
if (cookie == USB_HAL_DEATH_COOKIE) {
|
|
||||||
logAndPrint(Log.ERROR, pw, "Usb hal service died cookie: " + cookie);
|
|
||||||
synchronized (mLock) {
|
|
||||||
mProxy = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class ServiceNotification extends IServiceNotification.Stub {
|
|
||||||
@Override
|
|
||||||
public void onRegistration(String fqName, String name, boolean preexisting) {
|
|
||||||
logAndPrint(Log.INFO, null, "Usb hal service started " + fqName + " " + name);
|
|
||||||
connectToProxy(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connectToProxy(IndentingPrintWriter pw) {
|
|
||||||
synchronized (mLock) {
|
|
||||||
if (mProxy != null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
mProxy = IUsb.getService();
|
|
||||||
mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
|
|
||||||
mProxy.setCallback(mHALCallback);
|
|
||||||
mProxy.queryPortStatus();
|
|
||||||
updateUsbHalVersion();
|
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
logAndPrintException(pw, "connectToProxy: usb hal service not found."
|
|
||||||
+ " Did the service fail to start?", e);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
logAndPrintException(pw, "connectToProxy: usb hal service not responding", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simulated ports directly add the new roles to mSimulatedPorts before calling.
|
* Simulated ports directly add the new roles to mSimulatedPorts before calling.
|
||||||
* USB hal callback populates and sends the newPortInfo.
|
* USB hal callback populates and sends the newPortInfo.
|
||||||
@@ -869,7 +714,8 @@ public class UsbPortManager {
|
|||||||
portInfo.supportsEnableContaminantPresenceProtection,
|
portInfo.supportsEnableContaminantPresenceProtection,
|
||||||
portInfo.contaminantProtectionStatus,
|
portInfo.contaminantProtectionStatus,
|
||||||
portInfo.supportsEnableContaminantPresenceDetection,
|
portInfo.supportsEnableContaminantPresenceDetection,
|
||||||
portInfo.contaminantDetectionStatus, pw);
|
portInfo.contaminantDetectionStatus,
|
||||||
|
portInfo.usbDataEnabled, pw);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (RawPortInfo currentPortInfo : newPortInfo) {
|
for (RawPortInfo currentPortInfo : newPortInfo) {
|
||||||
@@ -881,7 +727,8 @@ public class UsbPortManager {
|
|||||||
currentPortInfo.supportsEnableContaminantPresenceProtection,
|
currentPortInfo.supportsEnableContaminantPresenceProtection,
|
||||||
currentPortInfo.contaminantProtectionStatus,
|
currentPortInfo.contaminantProtectionStatus,
|
||||||
currentPortInfo.supportsEnableContaminantPresenceDetection,
|
currentPortInfo.supportsEnableContaminantPresenceDetection,
|
||||||
currentPortInfo.contaminantDetectionStatus, pw);
|
currentPortInfo.contaminantDetectionStatus,
|
||||||
|
currentPortInfo.usbDataEnabled, pw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -917,6 +764,7 @@ public class UsbPortManager {
|
|||||||
int contaminantProtectionStatus,
|
int contaminantProtectionStatus,
|
||||||
boolean supportsEnableContaminantPresenceDetection,
|
boolean supportsEnableContaminantPresenceDetection,
|
||||||
int contaminantDetectionStatus,
|
int contaminantDetectionStatus,
|
||||||
|
boolean usbDataEnabled,
|
||||||
IndentingPrintWriter pw) {
|
IndentingPrintWriter pw) {
|
||||||
// Only allow mode switch capability for dual role ports.
|
// Only allow mode switch capability for dual role ports.
|
||||||
// Validate that the current mode matches the supported modes we expect.
|
// Validate that the current mode matches the supported modes we expect.
|
||||||
@@ -975,7 +823,7 @@ public class UsbPortManager {
|
|||||||
currentPowerRole, canChangePowerRole,
|
currentPowerRole, canChangePowerRole,
|
||||||
currentDataRole, canChangeDataRole,
|
currentDataRole, canChangeDataRole,
|
||||||
supportedRoleCombinations, contaminantProtectionStatus,
|
supportedRoleCombinations, contaminantProtectionStatus,
|
||||||
contaminantDetectionStatus);
|
contaminantDetectionStatus, usbDataEnabled);
|
||||||
mPorts.put(portId, portInfo);
|
mPorts.put(portId, portInfo);
|
||||||
} else {
|
} else {
|
||||||
// Validate that ports aren't changing definition out from under us.
|
// Validate that ports aren't changing definition out from under us.
|
||||||
@@ -1012,7 +860,7 @@ public class UsbPortManager {
|
|||||||
currentPowerRole, canChangePowerRole,
|
currentPowerRole, canChangePowerRole,
|
||||||
currentDataRole, canChangeDataRole,
|
currentDataRole, canChangeDataRole,
|
||||||
supportedRoleCombinations, contaminantProtectionStatus,
|
supportedRoleCombinations, contaminantProtectionStatus,
|
||||||
contaminantDetectionStatus)) {
|
contaminantDetectionStatus, usbDataEnabled)) {
|
||||||
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
|
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
|
||||||
} else {
|
} else {
|
||||||
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
|
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
|
||||||
@@ -1141,14 +989,14 @@ public class UsbPortManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logAndPrint(int priority, IndentingPrintWriter pw, String msg) {
|
public static void logAndPrint(int priority, IndentingPrintWriter pw, String msg) {
|
||||||
Slog.println(priority, TAG, msg);
|
Slog.println(priority, TAG, msg);
|
||||||
if (pw != null) {
|
if (pw != null) {
|
||||||
pw.println(msg);
|
pw.println(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void logAndPrintException(IndentingPrintWriter pw, String msg, Exception e) {
|
public static void logAndPrintException(IndentingPrintWriter pw, String msg, Exception e) {
|
||||||
Slog.e(TAG, msg, e);
|
Slog.e(TAG, msg, e);
|
||||||
if (pw != null) {
|
if (pw != null) {
|
||||||
pw.println(msg + e);
|
pw.println(msg + e);
|
||||||
@@ -1179,7 +1027,7 @@ public class UsbPortManager {
|
|||||||
/**
|
/**
|
||||||
* Describes a USB port.
|
* Describes a USB port.
|
||||||
*/
|
*/
|
||||||
private static final class PortInfo {
|
public static final class PortInfo {
|
||||||
public static final int DISPOSITION_ADDED = 0;
|
public static final int DISPOSITION_ADDED = 0;
|
||||||
public static final int DISPOSITION_CHANGED = 1;
|
public static final int DISPOSITION_CHANGED = 1;
|
||||||
public static final int DISPOSITION_READY = 2;
|
public static final int DISPOSITION_READY = 2;
|
||||||
@@ -1224,7 +1072,7 @@ public class UsbPortManager {
|
|||||||
!= supportedRoleCombinations) {
|
!= supportedRoleCombinations) {
|
||||||
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
|
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
|
||||||
supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
|
supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
|
||||||
UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED);
|
UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED, true);
|
||||||
dispositionChanged = true;
|
dispositionChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1243,7 +1091,7 @@ public class UsbPortManager {
|
|||||||
int currentPowerRole, boolean canChangePowerRole,
|
int currentPowerRole, boolean canChangePowerRole,
|
||||||
int currentDataRole, boolean canChangeDataRole,
|
int currentDataRole, boolean canChangeDataRole,
|
||||||
int supportedRoleCombinations, int contaminantProtectionStatus,
|
int supportedRoleCombinations, int contaminantProtectionStatus,
|
||||||
int contaminantDetectionStatus) {
|
int contaminantDetectionStatus, boolean usbDataEnabled) {
|
||||||
boolean dispositionChanged = false;
|
boolean dispositionChanged = false;
|
||||||
|
|
||||||
mCanChangeMode = canChangeMode;
|
mCanChangeMode = canChangeMode;
|
||||||
@@ -1258,10 +1106,12 @@ public class UsbPortManager {
|
|||||||
|| mUsbPortStatus.getContaminantProtectionStatus()
|
|| mUsbPortStatus.getContaminantProtectionStatus()
|
||||||
!= contaminantProtectionStatus
|
!= contaminantProtectionStatus
|
||||||
|| mUsbPortStatus.getContaminantDetectionStatus()
|
|| mUsbPortStatus.getContaminantDetectionStatus()
|
||||||
!= contaminantDetectionStatus) {
|
!= contaminantDetectionStatus
|
||||||
|
|| mUsbPortStatus.getUsbDataStatus()
|
||||||
|
!= usbDataEnabled){
|
||||||
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
|
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
|
||||||
supportedRoleCombinations, contaminantProtectionStatus,
|
supportedRoleCombinations, contaminantProtectionStatus,
|
||||||
contaminantDetectionStatus);
|
contaminantDetectionStatus, usbDataEnabled);
|
||||||
dispositionChanged = true;
|
dispositionChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1290,7 +1140,6 @@ public class UsbPortManager {
|
|||||||
UsbPortInfoProto.CONNECTED_AT_MILLIS, mConnectedAtMillis);
|
UsbPortInfoProto.CONNECTED_AT_MILLIS, mConnectedAtMillis);
|
||||||
dump.write("last_connect_duration_millis",
|
dump.write("last_connect_duration_millis",
|
||||||
UsbPortInfoProto.LAST_CONNECT_DURATION_MILLIS, mLastConnectDurationMillis);
|
UsbPortInfoProto.LAST_CONNECT_DURATION_MILLIS, mLastConnectDurationMillis);
|
||||||
|
|
||||||
dump.end(token);
|
dump.end(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,115 +1153,4 @@ public class UsbPortManager {
|
|||||||
+ ", lastConnectDurationMillis=" + mLastConnectDurationMillis;
|
+ ", lastConnectDurationMillis=" + mLastConnectDurationMillis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Used for storing the raw data from the kernel
|
|
||||||
* Values of the member variables mocked directly incase of emulation.
|
|
||||||
*/
|
|
||||||
private static final class RawPortInfo implements Parcelable {
|
|
||||||
public final String portId;
|
|
||||||
public final int supportedModes;
|
|
||||||
public final int supportedContaminantProtectionModes;
|
|
||||||
public int currentMode;
|
|
||||||
public boolean canChangeMode;
|
|
||||||
public int currentPowerRole;
|
|
||||||
public boolean canChangePowerRole;
|
|
||||||
public int currentDataRole;
|
|
||||||
public boolean canChangeDataRole;
|
|
||||||
public boolean supportsEnableContaminantPresenceProtection;
|
|
||||||
public int contaminantProtectionStatus;
|
|
||||||
public boolean supportsEnableContaminantPresenceDetection;
|
|
||||||
public int contaminantDetectionStatus;
|
|
||||||
|
|
||||||
RawPortInfo(String portId, int supportedModes) {
|
|
||||||
this.portId = portId;
|
|
||||||
this.supportedModes = supportedModes;
|
|
||||||
this.supportedContaminantProtectionModes = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
|
||||||
this.supportsEnableContaminantPresenceProtection = false;
|
|
||||||
this.contaminantProtectionStatus = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
|
||||||
this.supportsEnableContaminantPresenceDetection = false;
|
|
||||||
this.contaminantDetectionStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
|
|
||||||
int currentMode, boolean canChangeMode,
|
|
||||||
int currentPowerRole, boolean canChangePowerRole,
|
|
||||||
int currentDataRole, boolean canChangeDataRole,
|
|
||||||
boolean supportsEnableContaminantPresenceProtection,
|
|
||||||
int contaminantProtectionStatus,
|
|
||||||
boolean supportsEnableContaminantPresenceDetection,
|
|
||||||
int contaminantDetectionStatus) {
|
|
||||||
this.portId = portId;
|
|
||||||
this.supportedModes = supportedModes;
|
|
||||||
this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
|
|
||||||
this.currentMode = currentMode;
|
|
||||||
this.canChangeMode = canChangeMode;
|
|
||||||
this.currentPowerRole = currentPowerRole;
|
|
||||||
this.canChangePowerRole = canChangePowerRole;
|
|
||||||
this.currentDataRole = currentDataRole;
|
|
||||||
this.canChangeDataRole = canChangeDataRole;
|
|
||||||
this.supportsEnableContaminantPresenceProtection =
|
|
||||||
supportsEnableContaminantPresenceProtection;
|
|
||||||
this.contaminantProtectionStatus = contaminantProtectionStatus;
|
|
||||||
this.supportsEnableContaminantPresenceDetection =
|
|
||||||
supportsEnableContaminantPresenceDetection;
|
|
||||||
this.contaminantDetectionStatus = contaminantDetectionStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int describeContents() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
|
||||||
dest.writeString(portId);
|
|
||||||
dest.writeInt(supportedModes);
|
|
||||||
dest.writeInt(supportedContaminantProtectionModes);
|
|
||||||
dest.writeInt(currentMode);
|
|
||||||
dest.writeByte((byte) (canChangeMode ? 1 : 0));
|
|
||||||
dest.writeInt(currentPowerRole);
|
|
||||||
dest.writeByte((byte) (canChangePowerRole ? 1 : 0));
|
|
||||||
dest.writeInt(currentDataRole);
|
|
||||||
dest.writeByte((byte) (canChangeDataRole ? 1 : 0));
|
|
||||||
dest.writeBoolean(supportsEnableContaminantPresenceProtection);
|
|
||||||
dest.writeInt(contaminantProtectionStatus);
|
|
||||||
dest.writeBoolean(supportsEnableContaminantPresenceDetection);
|
|
||||||
dest.writeInt(contaminantDetectionStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Parcelable.Creator<RawPortInfo> CREATOR =
|
|
||||||
new Parcelable.Creator<RawPortInfo>() {
|
|
||||||
@Override
|
|
||||||
public RawPortInfo createFromParcel(Parcel in) {
|
|
||||||
String id = in.readString();
|
|
||||||
int supportedModes = in.readInt();
|
|
||||||
int supportedContaminantProtectionModes = in.readInt();
|
|
||||||
int currentMode = in.readInt();
|
|
||||||
boolean canChangeMode = in.readByte() != 0;
|
|
||||||
int currentPowerRole = in.readInt();
|
|
||||||
boolean canChangePowerRole = in.readByte() != 0;
|
|
||||||
int currentDataRole = in.readInt();
|
|
||||||
boolean canChangeDataRole = in.readByte() != 0;
|
|
||||||
boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
|
|
||||||
int contaminantProtectionStatus = in.readInt();
|
|
||||||
boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
|
|
||||||
int contaminantDetectionStatus = in.readInt();
|
|
||||||
return new RawPortInfo(id, supportedModes,
|
|
||||||
supportedContaminantProtectionModes, currentMode, canChangeMode,
|
|
||||||
currentPowerRole, canChangePowerRole,
|
|
||||||
currentDataRole, canChangeDataRole,
|
|
||||||
supportsEnableContaminantPresenceProtection,
|
|
||||||
contaminantProtectionStatus,
|
|
||||||
supportsEnableContaminantPresenceDetection,
|
|
||||||
contaminantDetectionStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public RawPortInfo[] newArray(int size) {
|
|
||||||
return new RawPortInfo[size];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.usb;
|
package com.android.server.usb;
|
||||||
|
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
|
||||||
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
|
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
|
||||||
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
|
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
|
||||||
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
|
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
|
||||||
@@ -35,6 +36,7 @@ import android.content.Intent;
|
|||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.hardware.usb.IUsbManager;
|
import android.hardware.usb.IUsbManager;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
import android.hardware.usb.ParcelableUsbPort;
|
import android.hardware.usb.ParcelableUsbPort;
|
||||||
import android.hardware.usb.UsbAccessory;
|
import android.hardware.usb.UsbAccessory;
|
||||||
import android.hardware.usb.UsbDevice;
|
import android.hardware.usb.UsbDevice;
|
||||||
@@ -44,6 +46,7 @@ import android.hardware.usb.UsbPortStatus;
|
|||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
import android.os.UserManager;
|
||||||
import android.service.usb.UsbServiceDumpProto;
|
import android.service.usb.UsbServiceDumpProto;
|
||||||
@@ -762,19 +765,30 @@ public class UsbService extends IUsbManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean enableUsbDataSignal(boolean enable) {
|
public boolean enableUsbData(String portId, boolean enable, int operationId,
|
||||||
|
IUsbOperationInternal callback) {
|
||||||
|
Objects.requireNonNull(portId, "enableUsbData: portId must not be null. opId:"
|
||||||
|
+ operationId);
|
||||||
|
Objects.requireNonNull(callback, "enableUsbData: callback must not be null. opId:"
|
||||||
|
+ operationId);
|
||||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
|
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);
|
||||||
|
|
||||||
final long ident = Binder.clearCallingIdentity();
|
final long ident = Binder.clearCallingIdentity();
|
||||||
|
boolean wait;
|
||||||
try {
|
try {
|
||||||
if (mPortManager != null) {
|
if (mPortManager != null) {
|
||||||
return mPortManager.enableUsbDataSignal(enable);
|
wait = mPortManager.enableUsbData(portId, enable, operationId, callback, null);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
wait = false;
|
||||||
|
try {
|
||||||
|
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "enableUsbData: Failed to call onOperationComplete", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
|
return wait;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.server.usb.hal.port;
|
||||||
|
|
||||||
|
import android.hardware.usb.UsbPortStatus;
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for storing the raw data from the HAL.
|
||||||
|
* Values of the member variables mocked directly in case of emulation.
|
||||||
|
*/
|
||||||
|
public final class RawPortInfo implements Parcelable {
|
||||||
|
public final String portId;
|
||||||
|
public final int supportedModes;
|
||||||
|
public final int supportedContaminantProtectionModes;
|
||||||
|
public int currentMode;
|
||||||
|
public boolean canChangeMode;
|
||||||
|
public int currentPowerRole;
|
||||||
|
public boolean canChangePowerRole;
|
||||||
|
public int currentDataRole;
|
||||||
|
public boolean canChangeDataRole;
|
||||||
|
public boolean supportsEnableContaminantPresenceProtection;
|
||||||
|
public int contaminantProtectionStatus;
|
||||||
|
public boolean supportsEnableContaminantPresenceDetection;
|
||||||
|
public int contaminantDetectionStatus;
|
||||||
|
public boolean usbDataEnabled;
|
||||||
|
|
||||||
|
public RawPortInfo(String portId, int supportedModes) {
|
||||||
|
this.portId = portId;
|
||||||
|
this.supportedModes = supportedModes;
|
||||||
|
this.supportedContaminantProtectionModes = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
|
this.supportsEnableContaminantPresenceProtection = false;
|
||||||
|
this.contaminantProtectionStatus = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
|
this.supportsEnableContaminantPresenceDetection = false;
|
||||||
|
this.contaminantDetectionStatus = UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
|
||||||
|
this.usbDataEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RawPortInfo(String portId, int supportedModes, int supportedContaminantProtectionModes,
|
||||||
|
int currentMode, boolean canChangeMode,
|
||||||
|
int currentPowerRole, boolean canChangePowerRole,
|
||||||
|
int currentDataRole, boolean canChangeDataRole,
|
||||||
|
boolean supportsEnableContaminantPresenceProtection,
|
||||||
|
int contaminantProtectionStatus,
|
||||||
|
boolean supportsEnableContaminantPresenceDetection,
|
||||||
|
int contaminantDetectionStatus,
|
||||||
|
boolean usbDataEnabled) {
|
||||||
|
this.portId = portId;
|
||||||
|
this.supportedModes = supportedModes;
|
||||||
|
this.supportedContaminantProtectionModes = supportedContaminantProtectionModes;
|
||||||
|
this.currentMode = currentMode;
|
||||||
|
this.canChangeMode = canChangeMode;
|
||||||
|
this.currentPowerRole = currentPowerRole;
|
||||||
|
this.canChangePowerRole = canChangePowerRole;
|
||||||
|
this.currentDataRole = currentDataRole;
|
||||||
|
this.canChangeDataRole = canChangeDataRole;
|
||||||
|
this.supportsEnableContaminantPresenceProtection =
|
||||||
|
supportsEnableContaminantPresenceProtection;
|
||||||
|
this.contaminantProtectionStatus = contaminantProtectionStatus;
|
||||||
|
this.supportsEnableContaminantPresenceDetection =
|
||||||
|
supportsEnableContaminantPresenceDetection;
|
||||||
|
this.contaminantDetectionStatus = contaminantDetectionStatus;
|
||||||
|
this.usbDataEnabled = usbDataEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(portId);
|
||||||
|
dest.writeInt(supportedModes);
|
||||||
|
dest.writeInt(supportedContaminantProtectionModes);
|
||||||
|
dest.writeInt(currentMode);
|
||||||
|
dest.writeByte((byte) (canChangeMode ? 1 : 0));
|
||||||
|
dest.writeInt(currentPowerRole);
|
||||||
|
dest.writeByte((byte) (canChangePowerRole ? 1 : 0));
|
||||||
|
dest.writeInt(currentDataRole);
|
||||||
|
dest.writeByte((byte) (canChangeDataRole ? 1 : 0));
|
||||||
|
dest.writeBoolean(supportsEnableContaminantPresenceProtection);
|
||||||
|
dest.writeInt(contaminantProtectionStatus);
|
||||||
|
dest.writeBoolean(supportsEnableContaminantPresenceDetection);
|
||||||
|
dest.writeInt(contaminantDetectionStatus);
|
||||||
|
dest.writeBoolean(usbDataEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Parcelable.Creator<RawPortInfo> CREATOR =
|
||||||
|
new Parcelable.Creator<RawPortInfo>() {
|
||||||
|
@Override
|
||||||
|
public RawPortInfo createFromParcel(Parcel in) {
|
||||||
|
String id = in.readString();
|
||||||
|
int supportedModes = in.readInt();
|
||||||
|
int supportedContaminantProtectionModes = in.readInt();
|
||||||
|
int currentMode = in.readInt();
|
||||||
|
boolean canChangeMode = in.readByte() != 0;
|
||||||
|
int currentPowerRole = in.readInt();
|
||||||
|
boolean canChangePowerRole = in.readByte() != 0;
|
||||||
|
int currentDataRole = in.readInt();
|
||||||
|
boolean canChangeDataRole = in.readByte() != 0;
|
||||||
|
boolean supportsEnableContaminantPresenceProtection = in.readBoolean();
|
||||||
|
int contaminantProtectionStatus = in.readInt();
|
||||||
|
boolean supportsEnableContaminantPresenceDetection = in.readBoolean();
|
||||||
|
int contaminantDetectionStatus = in.readInt();
|
||||||
|
boolean usbDataEnabled = in.readBoolean();
|
||||||
|
return new RawPortInfo(id, supportedModes,
|
||||||
|
supportedContaminantProtectionModes, currentMode, canChangeMode,
|
||||||
|
currentPowerRole, canChangePowerRole,
|
||||||
|
currentDataRole, canChangeDataRole,
|
||||||
|
supportsEnableContaminantPresenceProtection,
|
||||||
|
contaminantProtectionStatus,
|
||||||
|
supportsEnableContaminantPresenceDetection,
|
||||||
|
contaminantDetectionStatus, usbDataEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RawPortInfo[] newArray(int size) {
|
||||||
|
return new RawPortInfo[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,476 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.server.usb.hal.port;
|
||||||
|
|
||||||
|
import static android.hardware.usb.UsbManager.USB_HAL_V2_0;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS;
|
||||||
|
|
||||||
|
import static com.android.server.usb.UsbPortManager.logAndPrint;
|
||||||
|
import static com.android.server.usb.UsbPortManager.logAndPrintException;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.hardware.usb.ContaminantProtectionStatus;
|
||||||
|
import android.hardware.usb.IUsb;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
|
import android.hardware.usb.UsbManager.UsbHalVersion;
|
||||||
|
import android.hardware.usb.UsbPort;
|
||||||
|
import android.hardware.usb.UsbPortStatus;
|
||||||
|
import android.hardware.usb.PortMode;
|
||||||
|
import android.hardware.usb.Status;
|
||||||
|
import android.hardware.usb.IUsbCallback;
|
||||||
|
import android.hardware.usb.PortRole;
|
||||||
|
import android.hardware.usb.PortStatus;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.LongSparseArray;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
import com.android.server.usb.UsbPortManager;
|
||||||
|
import com.android.server.usb.hal.port.RawPortInfo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the methods to interact with AIDL USB HAL.
|
||||||
|
*/
|
||||||
|
public final class UsbPortAidl implements UsbPortHal {
|
||||||
|
private static final String TAG = UsbPortAidl.class.getSimpleName();
|
||||||
|
private static final String USB_AIDL_SERVICE =
|
||||||
|
"android.hardware.usb.IUsb/default";
|
||||||
|
private static final LongSparseArray<IUsbOperationInternal>
|
||||||
|
sCallbacks = new LongSparseArray<>();
|
||||||
|
// Proxy object for the usb hal daemon.
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private IUsb mProxy;
|
||||||
|
private UsbPortManager mPortManager;
|
||||||
|
public IndentingPrintWriter mPw;
|
||||||
|
// Mutex for all mutable shared state.
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
// Callback when the UsbPort status is changed by the kernel.
|
||||||
|
private HALCallback mHALCallback;
|
||||||
|
private IBinder mBinder;
|
||||||
|
private boolean mSystemReady;
|
||||||
|
private long mTransactionId;
|
||||||
|
|
||||||
|
public @UsbHalVersion int getUsbHalVersion() throws RemoteException {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
throw new RemoteException("IUsb not initialized yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logAndPrint(Log.INFO, null, "USB HAL AIDL version: USB_HAL_V2_0");
|
||||||
|
return USB_HAL_V2_0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void systemReady() {
|
||||||
|
mSystemReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void serviceDied() {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Usb AIDL hal service died");
|
||||||
|
synchronized (mLock) {
|
||||||
|
mProxy = null;
|
||||||
|
}
|
||||||
|
connectToProxy(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connectToProxy(IndentingPrintWriter pw) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mBinder = ServiceManager.waitForService(USB_AIDL_SERVICE);
|
||||||
|
mProxy = IUsb.Stub.asInterface(mBinder);
|
||||||
|
mBinder.linkToDeath(this::serviceDied, 0);
|
||||||
|
mProxy.setCallback(mHALCallback);
|
||||||
|
mProxy.queryPortStatus(++mTransactionId);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
logAndPrintException(pw, "connectToProxy: usb hal service not found."
|
||||||
|
+ " Did the service fail to start?", e);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(pw, "connectToProxy: usb hal service not responding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isServicePresent(IndentingPrintWriter pw) {
|
||||||
|
try {
|
||||||
|
return ServiceManager.isDeclared(USB_AIDL_SERVICE);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
logAndPrintException(pw, "connectToProxy: usb Aidl hal service not found.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsbPortAidl(UsbPortManager portManager, IndentingPrintWriter pw) {
|
||||||
|
mPortManager = Objects.requireNonNull(portManager);
|
||||||
|
mPw = pw;
|
||||||
|
mHALCallback = new HALCallback(null, mPortManager, this);
|
||||||
|
connectToProxy(mPw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableContaminantPresenceDetection(String portName, boolean enable,
|
||||||
|
long operationID) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID: "
|
||||||
|
+ operationID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Oneway call into the hal. Use the castFrom method from HIDL.
|
||||||
|
mProxy.enableContaminantPresenceDetection(portName, enable, operationID);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set contaminant detection. opID:"
|
||||||
|
+ operationID, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void queryPortStatus(long operationID) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
|
||||||
|
+ operationID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mProxy.queryPortStatus(operationID);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(null, "ServiceStart: Failed to query port status. opID:"
|
||||||
|
+ operationID, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchMode(String portId, @HalUsbPortMode int newMode, long operationID) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
|
||||||
|
+ operationID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortRole newRole = new PortRole();
|
||||||
|
newRole.setMode((byte)newMode);
|
||||||
|
try {
|
||||||
|
mProxy.switchRole(portId, newRole, operationID);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set the USB port mode: "
|
||||||
|
+ "portId=" + portId
|
||||||
|
+ ", newMode=" + UsbPort.modeToString(newMode)
|
||||||
|
+ "opID:" + operationID, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchPowerRole(String portId, @HalUsbPowerRole int newPowerRole,
|
||||||
|
long operationID) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
|
||||||
|
+ operationID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortRole newRole = new PortRole();
|
||||||
|
newRole.setPowerRole((byte)newPowerRole);
|
||||||
|
try {
|
||||||
|
mProxy.switchRole(portId, newRole, operationID);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set the USB power role: portId=" + portId
|
||||||
|
+ ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
|
||||||
|
+ "opID:" + operationID, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchDataRole(String portId, @HalUsbDataRole int newDataRole, long operationID) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
|
||||||
|
+ operationID);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortRole newRole = new PortRole();
|
||||||
|
newRole.setDataRole((byte)newDataRole);
|
||||||
|
try {
|
||||||
|
mProxy.switchRole(portId, newRole, operationID);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set the USB data role: portId=" + portId
|
||||||
|
+ ", newDataRole=" + UsbPort.dataRoleToString(newDataRole)
|
||||||
|
+ "opID:" + operationID, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enableUsbData(String portName, boolean enable, long operationID,
|
||||||
|
IUsbOperationInternal callback) {
|
||||||
|
Objects.requireNonNull(portName);
|
||||||
|
Objects.requireNonNull(callback);
|
||||||
|
long key = operationID;
|
||||||
|
synchronized (mLock) {
|
||||||
|
try {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw,
|
||||||
|
"enableUsbData: Proxy is null. Retry !opID:"
|
||||||
|
+ operationID);
|
||||||
|
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (sCallbacks.get(key) != null) {
|
||||||
|
key = ThreadLocalRandom.current().nextInt();
|
||||||
|
}
|
||||||
|
if (key != operationID) {
|
||||||
|
logAndPrint(Log.INFO, mPw, "enableUsbData: operationID exists ! opID:"
|
||||||
|
+ operationID + " key:" + key);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
sCallbacks.put(key, callback);
|
||||||
|
mProxy.enableUsbData(portName, enable, key);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw,
|
||||||
|
"enableUsbData: Failed to invoke enableUsbData: portID="
|
||||||
|
+ portName + "opID:" + operationID, e);
|
||||||
|
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
sCallbacks.remove(key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw,
|
||||||
|
"enableUsbData: Failed to call onOperationComplete portID="
|
||||||
|
+ portName + "opID:" + operationID, e);
|
||||||
|
sCallbacks.remove(key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HALCallback extends IUsbCallback.Stub {
|
||||||
|
public IndentingPrintWriter mPw;
|
||||||
|
public UsbPortManager mPortManager;
|
||||||
|
public UsbPortAidl mUsbPortAidl;
|
||||||
|
|
||||||
|
HALCallback(IndentingPrintWriter pw, UsbPortManager portManager, UsbPortAidl usbPortAidl) {
|
||||||
|
this.mPw = pw;
|
||||||
|
this.mPortManager = portManager;
|
||||||
|
this.mUsbPortAidl = usbPortAidl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts from AIDL defined mode constants to UsbPortStatus constants.
|
||||||
|
* AIDL does not gracefully support bitfield when combined with enums.
|
||||||
|
*/
|
||||||
|
private int toPortMode(byte aidlPortMode) {
|
||||||
|
switch (aidlPortMode) {
|
||||||
|
case PortMode.NONE:
|
||||||
|
return UsbPortStatus.MODE_NONE;
|
||||||
|
case PortMode.UFP:
|
||||||
|
return UsbPortStatus.MODE_UFP;
|
||||||
|
case PortMode.DFP:
|
||||||
|
return UsbPortStatus.MODE_DFP;
|
||||||
|
case PortMode.DRP:
|
||||||
|
return UsbPortStatus.MODE_DUAL;
|
||||||
|
case PortMode.AUDIO_ACCESSORY:
|
||||||
|
return UsbPortStatus.MODE_AUDIO_ACCESSORY;
|
||||||
|
case PortMode.DEBUG_ACCESSORY:
|
||||||
|
return UsbPortStatus.MODE_DEBUG_ACCESSORY;
|
||||||
|
default:
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, "Unrecognized aidlPortMode:"
|
||||||
|
+ aidlPortMode);
|
||||||
|
return UsbPortStatus.MODE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toSupportedModes(byte[] aidlPortModes) {
|
||||||
|
int supportedModes = UsbPortStatus.MODE_NONE;
|
||||||
|
|
||||||
|
for (byte aidlPortMode : aidlPortModes) {
|
||||||
|
supportedModes |= toPortMode(aidlPortMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return supportedModes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts from AIDL defined contaminant protection constants to UsbPortStatus constants.
|
||||||
|
* AIDL does not gracefully support bitfield when combined with enums.
|
||||||
|
* Common to both ContaminantProtectionMode and ContaminantProtectionStatus.
|
||||||
|
*/
|
||||||
|
private int toContaminantProtectionStatus(byte aidlContaminantProtection) {
|
||||||
|
switch (aidlContaminantProtection) {
|
||||||
|
case ContaminantProtectionStatus.NONE:
|
||||||
|
return UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
|
case ContaminantProtectionStatus.FORCE_SINK:
|
||||||
|
return UsbPortStatus.CONTAMINANT_PROTECTION_SINK;
|
||||||
|
case ContaminantProtectionStatus.FORCE_SOURCE:
|
||||||
|
return UsbPortStatus.CONTAMINANT_PROTECTION_SOURCE;
|
||||||
|
case ContaminantProtectionStatus.FORCE_DISABLE:
|
||||||
|
return UsbPortStatus.CONTAMINANT_PROTECTION_FORCE_DISABLE;
|
||||||
|
case ContaminantProtectionStatus.DISABLED:
|
||||||
|
return UsbPortStatus.CONTAMINANT_PROTECTION_DISABLED;
|
||||||
|
default:
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw,
|
||||||
|
"Unrecognized aidlContaminantProtection:"
|
||||||
|
+ aidlContaminantProtection);
|
||||||
|
return UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toSupportedContaminantProtectionModes(byte[] aidlModes) {
|
||||||
|
int supportedContaminantProtectionModes = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
|
|
||||||
|
for (byte aidlMode : aidlModes) {
|
||||||
|
supportedContaminantProtectionModes |= toContaminantProtectionStatus(aidlMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return supportedContaminantProtectionModes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyPortStatusChange(
|
||||||
|
android.hardware.usb.PortStatus[] currentPortStatus, int retval) {
|
||||||
|
if (!mUsbPortAidl.mSystemReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, "port status enquiry failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
||||||
|
|
||||||
|
int numStatus = currentPortStatus.length;
|
||||||
|
for (int i = 0; i < numStatus; i++) {
|
||||||
|
PortStatus current = currentPortStatus[i];
|
||||||
|
RawPortInfo temp = new RawPortInfo(current.portName,
|
||||||
|
toSupportedModes(current.supportedModes),
|
||||||
|
toSupportedContaminantProtectionModes(current
|
||||||
|
.supportedContaminantProtectionModes),
|
||||||
|
toPortMode(current.currentMode),
|
||||||
|
current.canChangeMode,
|
||||||
|
current.currentPowerRole,
|
||||||
|
current.canChangePowerRole,
|
||||||
|
current.currentDataRole,
|
||||||
|
current.canChangeDataRole,
|
||||||
|
current.supportsEnableContaminantPresenceProtection,
|
||||||
|
toContaminantProtectionStatus(current.contaminantProtectionStatus),
|
||||||
|
current.supportsEnableContaminantPresenceDetection,
|
||||||
|
current.contaminantDetectionStatus,
|
||||||
|
current.usbDataEnabled);
|
||||||
|
newPortInfo.add(temp);
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback AIDL V1: "
|
||||||
|
+ current.portName);
|
||||||
|
}
|
||||||
|
mPortManager.updatePorts(newPortInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyRoleSwitchStatus(String portName, PortRole role, int retval,
|
||||||
|
long operationID) {
|
||||||
|
if (retval == Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, portName
|
||||||
|
+ " role switch successful. opID:"
|
||||||
|
+ operationID);
|
||||||
|
} else {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, portName + " role switch failed. err:"
|
||||||
|
+ retval
|
||||||
|
+ "opID:" + operationID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyQueryPortStatus(String portName, int retval, long operationID) {
|
||||||
|
if (retval == Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, portName + ": opID:"
|
||||||
|
+ operationID + " successful");
|
||||||
|
} else {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, portName + ": opID:"
|
||||||
|
+ operationID + " failed. err:" + retval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyEnableUsbDataStatus(String portName, boolean enable, int retval,
|
||||||
|
long operationID) {
|
||||||
|
if (retval == Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, "notifyEnableUsbDataStatus:"
|
||||||
|
+ portName + ": opID:"
|
||||||
|
+ operationID + " enable:" + enable);
|
||||||
|
} else {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
|
||||||
|
+ "notifyEnableUsbDataStatus: opID:"
|
||||||
|
+ operationID + " failed. err:" + retval);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
sCallbacks.get(operationID).onOperationComplete(retval == Status.SUCCESS
|
||||||
|
? USB_OPERATION_SUCCESS
|
||||||
|
: USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw,
|
||||||
|
"notifyEnableUsbDataStatus: Failed to call onOperationComplete",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyContaminantEnabledStatus(String portName, boolean enable, int retval,
|
||||||
|
long operationID) {
|
||||||
|
if (retval == Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, "notifyContaminantEnabledStatus:"
|
||||||
|
+ portName + ": opID:"
|
||||||
|
+ operationID + " enable:" + enable);
|
||||||
|
} else {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
|
||||||
|
+ "notifyContaminantEnabledStatus: opID:"
|
||||||
|
+ operationID + " failed. err:" + retval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInterfaceHash() {
|
||||||
|
return IUsbCallback.HASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInterfaceVersion() {
|
||||||
|
return IUsbCallback.VERSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,169 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.server.usb.hal.port;
|
||||||
|
|
||||||
|
import android.annotation.IntDef;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
|
import android.hardware.usb.UsbManager.UsbHalVersion;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public interface UsbPortHal {
|
||||||
|
/**
|
||||||
|
* Power role: This USB port can act as a source (provide power).
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int HAL_POWER_ROLE_SOURCE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Power role: This USB port can act as a sink (receive power).
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int HAL_POWER_ROLE_SINK = 2;
|
||||||
|
|
||||||
|
@IntDef(prefix = { "HAL_POWER_ROLE_" }, value = {
|
||||||
|
HAL_POWER_ROLE_SOURCE,
|
||||||
|
HAL_POWER_ROLE_SINK
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@interface HalUsbPowerRole{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data role: This USB port can act as a host (access data services).
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int HAL_DATA_ROLE_HOST = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data role: This USB port can act as a device (offer data services).
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int HAL_DATA_ROLE_DEVICE = 2;
|
||||||
|
|
||||||
|
@IntDef(prefix = { "HAL_DATA_ROLE_" }, value = {
|
||||||
|
HAL_DATA_ROLE_HOST,
|
||||||
|
HAL_DATA_ROLE_DEVICE
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@interface HalUsbDataRole{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This USB port can act as a downstream facing port (host).
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int HAL_MODE_DFP = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This USB port can act as an upstream facing port (device).
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int HAL_MODE_UFP = 2;
|
||||||
|
@IntDef(prefix = { "HAL_MODE_" }, value = {
|
||||||
|
HAL_MODE_DFP,
|
||||||
|
HAL_MODE_UFP,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@interface HalUsbPortMode{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UsbPortManager would call this when the system is done booting.
|
||||||
|
*/
|
||||||
|
public void systemReady();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to enable/disable contaminant presence detection on the USB port.
|
||||||
|
*
|
||||||
|
* @param portName Port Identifier.
|
||||||
|
* @param enable Enable contaminant presence detection when true.
|
||||||
|
* Disable when false.
|
||||||
|
* @param transactionId Used for tracking the current request and is passed down to the HAL
|
||||||
|
* implementation as needed.
|
||||||
|
*/
|
||||||
|
public void enableContaminantPresenceDetection(String portName, boolean enable,
|
||||||
|
long transactionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to query port status of all the ports.
|
||||||
|
*
|
||||||
|
* @param transactionId Used for tracking the current request and is passed down to the HAL
|
||||||
|
* implementation as needed.
|
||||||
|
*/
|
||||||
|
public void queryPortStatus(long transactionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to switch USB port mode.
|
||||||
|
*
|
||||||
|
* @param portName Port Identifier.
|
||||||
|
* @param mode New mode that the port is switching into.
|
||||||
|
* @param transactionId Used for tracking the current request and is passed down to the HAL
|
||||||
|
* implementation as needed.
|
||||||
|
*/
|
||||||
|
public void switchMode(String portName, @HalUsbPortMode int mode, long transactionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to switch USB port power role.
|
||||||
|
*
|
||||||
|
* @param portName Port Identifier.
|
||||||
|
* @param powerRole New power role that the port is switching into.
|
||||||
|
* @param transactionId Used for tracking the current request and is passed down to the HAL
|
||||||
|
* implementation as needed.
|
||||||
|
*/
|
||||||
|
public void switchPowerRole(String portName, @HalUsbPowerRole int powerRole,
|
||||||
|
long transactionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to switch USB port data role.
|
||||||
|
*
|
||||||
|
* @param portName Port Identifier.
|
||||||
|
* @param dataRole New data role that the port is switching into.
|
||||||
|
* @param transactionId Used for tracking the current request and is passed down to the HAL
|
||||||
|
* implementation as needed.
|
||||||
|
*/
|
||||||
|
public void switchDataRole(String portName, @HalUsbDataRole int dataRole, long transactionId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to query the version of current hal implementation.
|
||||||
|
*/
|
||||||
|
public @UsbHalVersion int getUsbHalVersion() throws RemoteException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoked to enable/disable UsbData on the specified port.
|
||||||
|
*
|
||||||
|
* @param portName Port Identifier.
|
||||||
|
* @param enable Enable USB data when true.
|
||||||
|
* Disable when false.
|
||||||
|
* @param transactionId Used for tracking the current request and is passed down to the HAL
|
||||||
|
* implementation as needed.
|
||||||
|
* @param callback callback object to be invoked to invoke the status of the operation upon
|
||||||
|
* completion.
|
||||||
|
* @param callback callback object to be invoked when the operation is complete.
|
||||||
|
* @return True when the operation is asynchronous. The caller of
|
||||||
|
* {@link UsbOperationCallbackInternal} must therefore call
|
||||||
|
* {@link UsbOperationCallbackInternal#waitForOperationComplete} for processing
|
||||||
|
* the result.
|
||||||
|
* False when the operation is synchronous. Caller can proceed reading the result
|
||||||
|
* through {@link UsbOperationCallbackInternal#getStatus}
|
||||||
|
*/
|
||||||
|
public boolean enableUsbData(String portName, boolean enable, long transactionId,
|
||||||
|
IUsbOperationInternal callback);
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.server.usb.hal.port;
|
||||||
|
|
||||||
|
import static com.android.server.usb.UsbPortManager.logAndPrint;
|
||||||
|
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
import com.android.server.usb.hal.port.UsbPortHidl;
|
||||||
|
import com.android.server.usb.hal.port.UsbPortAidl;
|
||||||
|
import com.android.server.usb.UsbPortManager;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
/**
|
||||||
|
* Helper class that queries the underlying hal layer to populate UsbPortHal instance.
|
||||||
|
*/
|
||||||
|
public final class UsbPortHalInstance {
|
||||||
|
|
||||||
|
public static UsbPortHal getInstance(UsbPortManager portManager, IndentingPrintWriter pw) {
|
||||||
|
|
||||||
|
logAndPrint(Log.DEBUG, null, "Querying USB HAL version");
|
||||||
|
if (UsbPortHidl.isServicePresent(null)) {
|
||||||
|
logAndPrint(Log.INFO, null, "USB HAL HIDL present");
|
||||||
|
return new UsbPortHidl(portManager, pw);
|
||||||
|
}
|
||||||
|
if (UsbPortAidl.isServicePresent(null)) {
|
||||||
|
logAndPrint(Log.INFO, null, "USB HAL AIDL present");
|
||||||
|
return new UsbPortAidl(portManager, pw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.android.server.usb.hal.port;
|
||||||
|
|
||||||
|
import static android.hardware.usb.UsbManager.USB_HAL_NOT_SUPPORTED;
|
||||||
|
import static android.hardware.usb.UsbManager.USB_HAL_V1_0;
|
||||||
|
import static android.hardware.usb.UsbManager.USB_HAL_V1_1;
|
||||||
|
import static android.hardware.usb.UsbManager.USB_HAL_V1_2;
|
||||||
|
import static android.hardware.usb.UsbManager.USB_HAL_V1_3;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_NOT_SUPPORTED;
|
||||||
|
import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.MODE_DUAL;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.MODE_UFP;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
|
||||||
|
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
|
||||||
|
|
||||||
|
import static com.android.server.usb.UsbPortManager.logAndPrint;
|
||||||
|
import static com.android.server.usb.UsbPortManager.logAndPrintException;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.hardware.usb.IUsbOperationInternal;
|
||||||
|
import android.hardware.usb.UsbManager.UsbHalVersion;
|
||||||
|
import android.hardware.usb.UsbPort;
|
||||||
|
import android.hardware.usb.V1_0.IUsb;
|
||||||
|
import android.hardware.usb.V1_0.PortRoleType;
|
||||||
|
import android.hardware.usb.V1_0.Status;
|
||||||
|
import android.hardware.usb.V1_1.PortStatus_1_1;
|
||||||
|
import android.hardware.usb.V1_2.IUsbCallback;
|
||||||
|
import android.hardware.usb.V1_0.PortRole;
|
||||||
|
import android.hardware.usb.V1_2.PortStatus;
|
||||||
|
import android.hidl.manager.V1_0.IServiceManager;
|
||||||
|
import android.hidl.manager.V1_0.IServiceNotification;
|
||||||
|
import android.os.IHwBinder;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
import com.android.internal.util.IndentingPrintWriter;
|
||||||
|
import com.android.server.usb.UsbPortManager;
|
||||||
|
import com.android.server.usb.hal.port.RawPortInfo;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Objects;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public final class UsbPortHidl implements UsbPortHal {
|
||||||
|
private static final String TAG = UsbPortHidl.class.getSimpleName();
|
||||||
|
// Cookie sent for usb hal death notification.
|
||||||
|
private static final int USB_HAL_DEATH_COOKIE = 1000;
|
||||||
|
// Proxy object for the usb hal daemon.
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private IUsb mProxy;
|
||||||
|
private UsbPortManager mPortManager;
|
||||||
|
public IndentingPrintWriter mPw;
|
||||||
|
// Mutex for all mutable shared state.
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
// Callback when the UsbPort status is changed by the kernel.
|
||||||
|
private HALCallback mHALCallback;
|
||||||
|
private boolean mSystemReady;
|
||||||
|
// Workaround since HIDL HAL versions report UsbDataEnabled status in UsbPortStatus;
|
||||||
|
private static boolean sUsbDataEnabled = true;
|
||||||
|
|
||||||
|
public @UsbHalVersion int getUsbHalVersion() throws RemoteException {
|
||||||
|
int version;
|
||||||
|
synchronized(mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
throw new RemoteException("IUsb not initialized yet");
|
||||||
|
}
|
||||||
|
if (android.hardware.usb.V1_3.IUsb.castFrom(mProxy) != null) {
|
||||||
|
version = USB_HAL_V1_3;
|
||||||
|
} else if (android.hardware.usb.V1_2.IUsb.castFrom(mProxy) != null) {
|
||||||
|
version = USB_HAL_V1_2;
|
||||||
|
} else if (android.hardware.usb.V1_1.IUsb.castFrom(mProxy) != null) {
|
||||||
|
version = USB_HAL_V1_1;
|
||||||
|
} else {
|
||||||
|
version = USB_HAL_V1_0;
|
||||||
|
}
|
||||||
|
logAndPrint(Log.INFO, null, "USB HAL HIDL version: " + version);
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class DeathRecipient implements IHwBinder.DeathRecipient {
|
||||||
|
public IndentingPrintWriter pw;
|
||||||
|
|
||||||
|
DeathRecipient(IndentingPrintWriter pw) {
|
||||||
|
this.pw = pw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serviceDied(long cookie) {
|
||||||
|
if (cookie == USB_HAL_DEATH_COOKIE) {
|
||||||
|
logAndPrint(Log.ERROR, pw, "Usb hal service died cookie: " + cookie);
|
||||||
|
synchronized (mLock) {
|
||||||
|
mProxy = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ServiceNotification extends IServiceNotification.Stub {
|
||||||
|
@Override
|
||||||
|
public void onRegistration(String fqName, String name, boolean preexisting) {
|
||||||
|
logAndPrint(Log.INFO, null, "Usb hal service started " + fqName + " " + name);
|
||||||
|
connectToProxy(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connectToProxy(IndentingPrintWriter pw) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mProxy = IUsb.getService();
|
||||||
|
mProxy.linkToDeath(new DeathRecipient(pw), USB_HAL_DEATH_COOKIE);
|
||||||
|
mProxy.setCallback(mHALCallback);
|
||||||
|
mProxy.queryPortStatus();
|
||||||
|
//updateUsbHalVersion();
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
logAndPrintException(pw, "connectToProxy: usb hal service not found."
|
||||||
|
+ " Did the service fail to start?", e);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(pw, "connectToProxy: usb hal service not responding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void systemReady() {
|
||||||
|
mSystemReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isServicePresent(IndentingPrintWriter pw) {
|
||||||
|
try {
|
||||||
|
IUsb.getService(true);
|
||||||
|
} catch (NoSuchElementException e) {
|
||||||
|
logAndPrintException(pw, "connectToProxy: usb hidl hal service not found.", e);
|
||||||
|
return false;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(pw, "IUSB hal service present but failed to get service", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UsbPortHidl(UsbPortManager portManager, IndentingPrintWriter pw) {
|
||||||
|
mPortManager = Objects.requireNonNull(portManager);
|
||||||
|
mPw = pw;
|
||||||
|
mHALCallback = new HALCallback(null, mPortManager, this);
|
||||||
|
try {
|
||||||
|
ServiceNotification serviceNotification = new ServiceNotification();
|
||||||
|
|
||||||
|
boolean ret = IServiceManager.getService()
|
||||||
|
.registerForNotifications("android.hardware.usb@1.0::IUsb",
|
||||||
|
"", serviceNotification);
|
||||||
|
if (!ret) {
|
||||||
|
logAndPrint(Log.ERROR, null,
|
||||||
|
"Failed to register service start notification");
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(null,
|
||||||
|
"Failed to register service start notification", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
connectToProxy(mPw);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableContaminantPresenceDetection(String portName, boolean enable,
|
||||||
|
long transactionId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Oneway call into the hal. Use the castFrom method from HIDL.
|
||||||
|
android.hardware.usb.V1_2.IUsb proxy =
|
||||||
|
android.hardware.usb.V1_2.IUsb.castFrom(mProxy);
|
||||||
|
proxy.enableContaminantPresenceDetection(portName, enable);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set contaminant detection", e);
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
logAndPrintException(mPw, "Method only applicable to V1.2 or above implementation",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void queryPortStatus(long transactionId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
mProxy.queryPortStatus();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(null, "ServiceStart: Failed to query port status", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchMode(String portId, @HalUsbPortMode int newMode, long transactionId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortRole newRole = new PortRole();
|
||||||
|
newRole.type = PortRoleType.MODE;
|
||||||
|
newRole.role = newMode;
|
||||||
|
try {
|
||||||
|
mProxy.switchRole(portId, newRole);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set the USB port mode: "
|
||||||
|
+ "portId=" + portId
|
||||||
|
+ ", newMode=" + UsbPort.modeToString(newRole.role), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchPowerRole(String portId, @HalUsbPowerRole int newPowerRole,
|
||||||
|
long transactionId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortRole newRole = new PortRole();
|
||||||
|
newRole.type = PortRoleType.POWER_ROLE;
|
||||||
|
newRole.role = newPowerRole;
|
||||||
|
try {
|
||||||
|
mProxy.switchRole(portId, newRole);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set the USB power role: portId=" + portId
|
||||||
|
+ ", newPowerRole=" + UsbPort.powerRoleToString(newRole.role), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void switchDataRole(String portId, @HalUsbDataRole int newDataRole, long transactionId) {
|
||||||
|
synchronized (mLock) {
|
||||||
|
if (mProxy == null) {
|
||||||
|
logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PortRole newRole = new PortRole();
|
||||||
|
newRole.type = PortRoleType.DATA_ROLE;
|
||||||
|
newRole.role = newDataRole;
|
||||||
|
try {
|
||||||
|
mProxy.switchRole(portId, newRole);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to set the USB data role: portId=" + portId
|
||||||
|
+ ", newDataRole=" + UsbPort.dataRoleToString(newRole.role), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enableUsbData(String portName, boolean enable, long transactionId,
|
||||||
|
IUsbOperationInternal callback) {
|
||||||
|
int halVersion;
|
||||||
|
|
||||||
|
try {
|
||||||
|
halVersion = getUsbHalVersion();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to query USB HAL version. opID:"
|
||||||
|
+ transactionId
|
||||||
|
+ " portId:" + portName, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (halVersion != USB_HAL_V1_3) {
|
||||||
|
try {
|
||||||
|
callback.onOperationComplete(USB_OPERATION_ERROR_NOT_SUPPORTED);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed to call onOperationComplete. opID:"
|
||||||
|
+ transactionId
|
||||||
|
+ " portId:" + portName, e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean success;
|
||||||
|
synchronized(mLock) {
|
||||||
|
try {
|
||||||
|
android.hardware.usb.V1_3.IUsb proxy
|
||||||
|
= android.hardware.usb.V1_3.IUsb.castFrom(mProxy);
|
||||||
|
success = proxy.enableUsbDataSignal(enable);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
logAndPrintException(mPw, "Failed enableUsbData: opId:" + transactionId
|
||||||
|
+ " portId=" + portName , e);
|
||||||
|
try {
|
||||||
|
callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
} catch (RemoteException r) {
|
||||||
|
logAndPrintException(mPw, "Failed to call onOperationComplete. opID:"
|
||||||
|
+ transactionId
|
||||||
|
+ " portId:" + portName, r);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
sUsbDataEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
callback.onOperationComplete(success
|
||||||
|
? USB_OPERATION_SUCCESS
|
||||||
|
: USB_OPERATION_ERROR_INTERNAL);
|
||||||
|
} catch (RemoteException r) {
|
||||||
|
logAndPrintException(mPw, "Failed to call onOperationComplete. opID:"
|
||||||
|
+ transactionId
|
||||||
|
+ " portId:" + portName, r);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class HALCallback extends IUsbCallback.Stub {
|
||||||
|
public IndentingPrintWriter mPw;
|
||||||
|
public UsbPortManager mPortManager;
|
||||||
|
public UsbPortHidl mUsbPortHidl;
|
||||||
|
|
||||||
|
HALCallback(IndentingPrintWriter pw, UsbPortManager portManager, UsbPortHidl usbPortHidl) {
|
||||||
|
this.mPw = pw;
|
||||||
|
this.mPortManager = portManager;
|
||||||
|
this.mUsbPortHidl = usbPortHidl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyPortStatusChange(
|
||||||
|
ArrayList<android.hardware.usb.V1_0.PortStatus> currentPortStatus, int retval) {
|
||||||
|
if (!mUsbPortHidl.mSystemReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, "port status enquiry failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
||||||
|
|
||||||
|
for (android.hardware.usb.V1_0.PortStatus current : currentPortStatus) {
|
||||||
|
RawPortInfo temp = new RawPortInfo(current.portName,
|
||||||
|
current.supportedModes, CONTAMINANT_PROTECTION_NONE,
|
||||||
|
current.currentMode,
|
||||||
|
current.canChangeMode, current.currentPowerRole,
|
||||||
|
current.canChangePowerRole,
|
||||||
|
current.currentDataRole, current.canChangeDataRole,
|
||||||
|
false, CONTAMINANT_PROTECTION_NONE,
|
||||||
|
false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataEnabled);
|
||||||
|
newPortInfo.add(temp);
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_0: "
|
||||||
|
+ current.portName);
|
||||||
|
}
|
||||||
|
|
||||||
|
mPortManager.updatePorts(newPortInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void notifyPortStatusChange_1_1(ArrayList<PortStatus_1_1> currentPortStatus,
|
||||||
|
int retval) {
|
||||||
|
if (!mUsbPortHidl.mSystemReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, "port status enquiry failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
||||||
|
|
||||||
|
int numStatus = currentPortStatus.size();
|
||||||
|
for (int i = 0; i < numStatus; i++) {
|
||||||
|
PortStatus_1_1 current = currentPortStatus.get(i);
|
||||||
|
RawPortInfo temp = new RawPortInfo(current.status.portName,
|
||||||
|
current.supportedModes, CONTAMINANT_PROTECTION_NONE,
|
||||||
|
current.currentMode,
|
||||||
|
current.status.canChangeMode, current.status.currentPowerRole,
|
||||||
|
current.status.canChangePowerRole,
|
||||||
|
current.status.currentDataRole, current.status.canChangeDataRole,
|
||||||
|
false, CONTAMINANT_PROTECTION_NONE,
|
||||||
|
false, CONTAMINANT_DETECTION_NOT_SUPPORTED, sUsbDataEnabled);
|
||||||
|
newPortInfo.add(temp);
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_1: "
|
||||||
|
+ current.status.portName);
|
||||||
|
}
|
||||||
|
mPortManager.updatePorts(newPortInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyPortStatusChange_1_2(
|
||||||
|
ArrayList<PortStatus> currentPortStatus, int retval) {
|
||||||
|
if (!mUsbPortHidl.mSystemReady) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, "port status enquiry failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
|
||||||
|
|
||||||
|
int numStatus = currentPortStatus.size();
|
||||||
|
for (int i = 0; i < numStatus; i++) {
|
||||||
|
PortStatus current = currentPortStatus.get(i);
|
||||||
|
RawPortInfo temp = new RawPortInfo(current.status_1_1.status.portName,
|
||||||
|
current.status_1_1.supportedModes,
|
||||||
|
current.supportedContaminantProtectionModes,
|
||||||
|
current.status_1_1.currentMode,
|
||||||
|
current.status_1_1.status.canChangeMode,
|
||||||
|
current.status_1_1.status.currentPowerRole,
|
||||||
|
current.status_1_1.status.canChangePowerRole,
|
||||||
|
current.status_1_1.status.currentDataRole,
|
||||||
|
current.status_1_1.status.canChangeDataRole,
|
||||||
|
current.supportsEnableContaminantPresenceProtection,
|
||||||
|
current.contaminantProtectionStatus,
|
||||||
|
current.supportsEnableContaminantPresenceDetection,
|
||||||
|
current.contaminantDetectionStatus,
|
||||||
|
sUsbDataEnabled);
|
||||||
|
newPortInfo.add(temp);
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback V1_2: "
|
||||||
|
+ current.status_1_1.status.portName);
|
||||||
|
}
|
||||||
|
mPortManager.updatePorts(newPortInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyRoleSwitchStatus(String portName, PortRole role, int retval) {
|
||||||
|
if (retval == Status.SUCCESS) {
|
||||||
|
UsbPortManager.logAndPrint(Log.INFO, mPw, portName + " role switch successful");
|
||||||
|
} else {
|
||||||
|
UsbPortManager.logAndPrint(Log.ERROR, mPw, portName + " role switch failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user