Support IUsb AIDL interface
UsbPortManager is made to support both AIDL & HIDL interface until
HIDL is deprecated eventually. UsbPortHal abstract class is defined
which the UsbPortManager grabs an instance of from UsbPortHalInstance
method to talk to the Hal implementation process. UsbPortHalInstance
queries the underlying hal implementation and instantiates UsbPortHal
with either UsbPortHidl or UsbPortAidl based on the IUsb interface
implemented by HAL implementation.
go/iusb-aidl-migrate.
Bug: 200993386
Bug: 199357330
Bug: 211677613
Bug: 213312081
Bug: 199358576
Test: Manually tested through UI.
CTS-Coverage-Bug: 215019881
Change-Id: I246fd6e5bee8138d3ad3b6994665a1d4788c8789
Merged-In: I246fd6e5bee8138d3ad3b6994665a1d4788c8789
(cherry picked from commit bbfa92e694)
This commit is contained in:
committed by
Ray Chi
parent
8f721b9229
commit
b09d68a2ea
@@ -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,466 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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