Merge changes from topics "CATEGORY_ERROR_IKE", "CATEGORY_ERROR_NETWORK", "CATEGORY_ERROR_USER_DEACTIVATED", "CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED"
* changes:
Send VPN manager event when there is a network error
Send VPN manager event when there is an IkeProtocolException
Send VPN manager event when VPN is deactivated
Send VPN manager event when VPN always-on status is changed
diff --git a/core/api/current.txt b/core/api/current.txt
index 641b1a3..e4fc9f3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -29612,6 +29612,7 @@
field public static final int S = 31; // 0x1f
field public static final int S_V2 = 32; // 0x20
field public static final int TIRAMISU = 10000; // 0x2710
+ field public static final int UPSIDE_DOWN_CAKE = 10000; // 0x2710
}
public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 9db3cdc..fd87a61 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -100,10 +100,12 @@
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_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_1 = 11; // 0xb
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_V2_0 = 20; // 0x14
}
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 95fc7ec..abc2b74 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4169,8 +4169,14 @@
}
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 @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 {
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index 7f07af7..3e79f18 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -18,6 +18,7 @@
import android.app.PendingIntent;
import android.content.ComponentName;
+import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.ParcelableUsbPort;
@@ -136,7 +137,7 @@
void resetUsbGadget();
/* 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. */
int getUsbHalVersion();
@@ -159,6 +160,6 @@
/* Enable/disable contaminant detection */
void enableContaminantDetection(in String portId, boolean enable);
- /* Sets USB device connection handler. */
- void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
+ /* Sets USB device connection handler. */
+ void setUsbDeviceConnectionHandler(in ComponentName usbDeviceConnectionHandler);
}
diff --git a/core/java/android/hardware/usb/IUsbOperationInternal.aidl b/core/java/android/hardware/usb/IUsbOperationInternal.aidl
new file mode 100644
index 0000000..3f3bbf6
--- /dev/null
+++ b/core/java/android/hardware/usb/IUsbOperationInternal.aidl
@@ -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);
+}
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 964d7c1..df70bfd 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -36,6 +36,8 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.hardware.usb.gadget.V1_0.GadgetFunction;
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.Bundle;
import android.os.ParcelFileDescriptor;
@@ -48,6 +50,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.StringJoiner;
/**
@@ -516,6 +519,14 @@
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.
*
* {@hide}
@@ -556,6 +567,14 @@
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)}
* {@hide}
*/
@@ -664,6 +683,7 @@
USB_HAL_V1_1,
USB_HAL_V1_2,
USB_HAL_V1_3,
+ USB_HAL_V2_0,
})
public @interface UsbHalVersion {}
@@ -1168,8 +1188,9 @@
/**
* Enable/Disable the USB data signaling.
* <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.
+ * Call UsbPort API if the device has more than one UsbPort.
* </p>
*
* @param enable enable or disable USB data signaling
@@ -1180,11 +1201,11 @@
*/
@RequiresPermission(Manifest.permission.MANAGE_USB)
public boolean enableUsbDataSignal(boolean enable) {
- try {
- return mService.enableUsbDataSignal(enable);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ List<UsbPort> usbPorts = getPorts();
+ if (usbPorts.size() == 1) {
+ return usbPorts.get(0).enableUsbData(enable) == UsbPort.ENABLE_USB_DATA_SUCCESS;
}
+ return false;
}
/**
@@ -1270,6 +1291,41 @@
}
/**
+ * 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.
* <p>
* Setting component allows to specify external USB host manager to handle use cases, where
diff --git a/core/java/android/hardware/usb/UsbOperationInternal.java b/core/java/android/hardware/usb/UsbOperationInternal.java
new file mode 100644
index 0000000..9bc2b38
--- /dev/null
+++ b/core/java/android/hardware/usb/UsbOperationInternal.java
@@ -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;
+ }
+}
diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java
index 274e23f..f469a3e 100644
--- a/core/java/android/hardware/usb/UsbPort.java
+++ b/core/java/android/hardware/usb/UsbPort.java
@@ -16,6 +16,10 @@
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_DISABLED;
import static android.hardware.usb.UsbPortStatus.CONTAMINANT_DETECTION_NOT_DETECTED;
@@ -34,15 +38,23 @@
import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
import android.Manifest;
+import android.annotation.CheckResult;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.hardware.usb.UsbOperationInternal;
import android.hardware.usb.V1_0.Constants;
+import android.os.Binder;
+import android.util.Log;
import com.android.internal.util.Preconditions;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* Represents a physical USB port and describes its characteristics.
@@ -51,6 +63,7 @@
*/
@SystemApi
public final class UsbPort {
+ private static final String TAG = "UsbPort";
private final String mId;
private final int mSupportedModes;
private final UsbManager mUsbManager;
@@ -64,6 +77,47 @@
*/
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 */
public UsbPort(@NonNull UsbManager usbManager, @NonNull String id, int supportedModes,
int supportedContaminantProtectionModes,
@@ -157,7 +211,7 @@
* {@link UsbPortStatus#isRoleCombinationSupported UsbPortStatus.isRoleCombinationSupported}.
* </p><p>
* 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.
* </p>
*
@@ -177,6 +231,47 @@
}
/**
+ * 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
**/
public void enableContaminantDetection(boolean enable) {
diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java
index bb7aff6..bd2f9aa 100644
--- a/core/java/android/hardware/usb/UsbPortStatus.java
+++ b/core/java/android/hardware/usb/UsbPortStatus.java
@@ -19,7 +19,6 @@
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
-import android.hardware.usb.V1_0.Constants;
import android.os.Parcel;
import android.os.Parcelable;
@@ -36,27 +35,29 @@
@Immutable
@SystemApi
public final class UsbPortStatus implements Parcelable {
+ private static final String TAG = "UsbPortStatus";
private final int mCurrentMode;
private final @UsbPowerRole int mCurrentPowerRole;
private final @UsbDataRole int mCurrentDataRole;
private final int mSupportedRoleCombinations;
private final @ContaminantProtectionStatus int mContaminantProtectionStatus;
private final @ContaminantDetectionStatus int mContaminantDetectionStatus;
+ private final boolean mUsbDataEnabled;
/**
* 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).
*/
- 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).
*/
- public static final int POWER_ROLE_SINK = Constants.PortPowerRole.SINK;
+ public static final int POWER_ROLE_SINK = 2;
@IntDef(prefix = { "POWER_ROLE_" }, value = {
POWER_ROLE_NONE,
@@ -69,17 +70,17 @@
/**
* 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).
*/
- 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).
*/
- public static final int DATA_ROLE_DEVICE = Constants.PortDataRole.DEVICE;
+ public static final int DATA_ROLE_DEVICE = 2;
@IntDef(prefix = { "DATA_ROLE_" }, value = {
DATA_ROLE_NONE,
@@ -92,15 +93,7 @@
/**
* There is currently nothing connected to this USB port.
*/
- public static final int MODE_NONE = Constants.PortMode.NONE;
-
- /**
- * 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;
+ public static final int MODE_NONE = 0;
/**
* This USB port can act as an upstream facing port (device).
@@ -108,7 +101,15 @@
* <p> Implies that the port supports the {@link #POWER_ROLE_SINK} and
* {@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
@@ -120,87 +121,76 @@
*
* @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.
*/
- public static final int MODE_AUDIO_ACCESSORY =
- android.hardware.usb.V1_1.Constants.PortMode_1_1.AUDIO_ACCESSORY;
+ public static final int MODE_AUDIO_ACCESSORY = 1 << 2;
/**
* This USB port can support USB Type-C debug accessory.
*/
- public static final int MODE_DEBUG_ACCESSORY =
- android.hardware.usb.V1_1.Constants.PortMode_1_1.DEBUG_ACCESSORY;
+ public static final int MODE_DEBUG_ACCESSORY = 1 << 3;
/**
* Contaminant presence detection not supported by the device.
* @hide
*/
- public static final int CONTAMINANT_DETECTION_NOT_SUPPORTED =
- android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.NOT_SUPPORTED;
+ public static final int CONTAMINANT_DETECTION_NOT_SUPPORTED = 0;
/**
* Contaminant presence detection supported but disabled.
* @hide
*/
- public static final int CONTAMINANT_DETECTION_DISABLED =
- android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.DISABLED;
+ public static final int CONTAMINANT_DETECTION_DISABLED = 1;
/**
* Contaminant presence enabled but not detected.
* @hide
*/
- public static final int CONTAMINANT_DETECTION_NOT_DETECTED =
- android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.NOT_DETECTED;
+ public static final int CONTAMINANT_DETECTION_NOT_DETECTED = 2;
/**
* Contaminant presence enabled and detected.
* @hide
*/
- public static final int CONTAMINANT_DETECTION_DETECTED =
- android.hardware.usb.V1_2.Constants.ContaminantDetectionStatus.DETECTED;
+ public static final int CONTAMINANT_DETECTION_DETECTED = 3;
/**
* Contaminant protection - No action performed upon detection of
* contaminant presence.
* @hide
*/
- public static final int CONTAMINANT_PROTECTION_NONE =
- android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.NONE;
+ public static final int CONTAMINANT_PROTECTION_NONE = 0;
/**
* Contaminant protection - Port is forced to sink upon detection of
* contaminant presence.
* @hide
*/
- public static final int CONTAMINANT_PROTECTION_SINK =
- android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_SINK;
+ public static final int CONTAMINANT_PROTECTION_SINK = 1 << 0;
/**
* Contaminant protection - Port is forced to source upon detection of
* contaminant presence.
* @hide
*/
- public static final int CONTAMINANT_PROTECTION_SOURCE =
- android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_SOURCE;
+ public static final int CONTAMINANT_PROTECTION_SOURCE = 1 << 1;
/**
* Contaminant protection - Port is disabled upon detection of
* contaminant presence.
* @hide
*/
- public static final int CONTAMINANT_PROTECTION_FORCE_DISABLE =
- android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.FORCE_DISABLE;
+ public static final int CONTAMINANT_PROTECTION_FORCE_DISABLE = 1 << 2;
/**
* Contaminant protection - Port is disabled upon detection of
* contaminant presence.
* @hide
*/
- public static final int CONTAMINANT_PROTECTION_DISABLED =
- android.hardware.usb.V1_2.Constants.ContaminantProtectionStatus.DISABLED;
+ public static final int CONTAMINANT_PROTECTION_DISABLED = 1 << 3;
@IntDef(prefix = { "CONTAMINANT_DETECTION_" }, value = {
CONTAMINANT_DETECTION_NOT_SUPPORTED,
@@ -234,6 +224,19 @@
/** @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 */
+ public UsbPortStatus(int currentMode, int currentPowerRole, int currentDataRole,
+ int supportedRoleCombinations, int contaminantProtectionStatus,
int contaminantDetectionStatus) {
mCurrentMode = currentMode;
mCurrentPowerRole = currentPowerRole;
@@ -241,6 +244,7 @@
mSupportedRoleCombinations = supportedRoleCombinations;
mContaminantProtectionStatus = contaminantProtectionStatus;
mContaminantDetectionStatus = contaminantDetectionStatus;
+ mUsbDataEnabled = true;
}
/**
@@ -323,6 +327,15 @@
return mContaminantProtectionStatus;
}
+ /**
+ * Returns UsbData status.
+ *
+ * @hide
+ */
+ public boolean getUsbDataStatus() {
+ return mUsbDataEnabled;
+ }
+
@NonNull
@Override
public String toString() {
@@ -336,6 +349,8 @@
+ getContaminantDetectionStatus()
+ ", contaminantProtectionStatus="
+ getContaminantProtectionStatus()
+ + ", usbDataEnabled="
+ + getUsbDataStatus()
+ "}";
}
@@ -352,6 +367,7 @@
dest.writeInt(mSupportedRoleCombinations);
dest.writeInt(mContaminantProtectionStatus);
dest.writeInt(mContaminantDetectionStatus);
+ dest.writeBoolean(mUsbDataEnabled);
}
public static final @NonNull Parcelable.Creator<UsbPortStatus> CREATOR =
@@ -364,9 +380,10 @@
int supportedRoleCombinations = in.readInt();
int contaminantProtectionStatus = in.readInt();
int contaminantDetectionStatus = in.readInt();
+ boolean usbDataEnabled = in.readBoolean();
return new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus);
+ contaminantDetectionStatus, usbDataEnabled);
}
@Override
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 45cc324d..141b141 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -406,7 +406,7 @@
public static final String CODENAME = getString("ro.build.version.codename");
/**
- * All known codenames starting from {@link VERSION_CODES.Q}.
+ * All known codenames that are present in {@link VERSION_CODES}.
*
* <p>This includes in development codenames as well, i.e. if {@link #CODENAME} is not "REL"
* then the value of that is present in this set.
@@ -1167,6 +1167,11 @@
* Tiramisu.
*/
public static final int TIRAMISU = CUR_DEVELOPMENT;
+
+ /**
+ * Upside Down Cake.
+ */
+ public static final int UPSIDE_DOWN_CAKE = CUR_DEVELOPMENT;
}
/** The type of build, like "user" or "eng". */
diff --git a/core/java/android/permission/OWNERS b/core/java/android/permission/OWNERS
index b5466b6..49f4bf7 100644
--- a/core/java/android/permission/OWNERS
+++ b/core/java/android/permission/OWNERS
@@ -5,10 +5,14 @@
ewol@google.com
guojing@google.com
jaysullivan@google.com
+kvakil@google.com
+mrulhania@google.com
+narayan@google.com
+ntmyren@google.com
olekarg@google.com
pyuli@google.com
-ntmyren@google.com
-svetoslavganov@android.com
-svetoslavganov@google.com
+raphk@google.com
+rmacgregor@google.com
+sergeynv@google.com
theianchen@google.com
zhanghai@google.com
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 4c1cc97..71b5354 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -306,6 +306,13 @@
public static final String NAMESPACE_MEDIA_NATIVE = "media_native";
/**
+ * Namespace for all Kernel Multi-Gen LRU feature.
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_MGLRU_NATIVE = "mglru_native";
+
+ /**
* Namespace for all netd related features.
*
* @hide
diff --git a/core/java/android/speech/OWNERS b/core/java/android/speech/OWNERS
index 32f4822..462d8be 100644
--- a/core/java/android/speech/OWNERS
+++ b/core/java/android/speech/OWNERS
@@ -1,3 +1,4 @@
volnov@google.com
eugeniom@google.com
schfan@google.com
+andreaambu@google.com
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f2ddf52..ffa577a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28283,7 +28283,7 @@
* {@link InputDevice#SOURCE_MOUSE_RELATIVE}, and relative position changes will be
* available through {@link MotionEvent#getX} and {@link MotionEvent#getY}.</li>
*
- * <li>Events from a touchpad will be delivered with the source
+ * <li>Events from a touchpad or trackpad will be delivered with the source
* {@link InputDevice#SOURCE_TOUCHPAD}, where the absolute position of each of the pointers
* on the touchpad will be available through {@link MotionEvent#getX(int)} and
* {@link MotionEvent#getY(int)}, and their relative movements are stored in
@@ -28292,6 +28292,12 @@
* <li>Events from other types of devices, such as touchscreens, will not be affected.</li>
* </ul>
* <p>
+ * When pointer capture changes, connected mouse and trackpad devices may be reconfigured,
+ * and their properties (such as their sources or motion ranges) may change. Use an
+ * {@link android.hardware.input.InputManager.InputDeviceListener} to be notified when a device
+ * changes (which may happen after enabling or disabling pointer capture), and use
+ * {@link InputDevice#getDevice(int)} to get the updated {@link InputDevice}.
+ * <p>
* Events captured through pointer capture will be dispatched to
* {@link OnCapturedPointerListener#onCapturedPointer(View, MotionEvent)} if an
* {@link OnCapturedPointerListener} is set, and otherwise to
diff --git a/core/java/com/android/internal/usb/DumpUtils.java b/core/java/com/android/internal/usb/DumpUtils.java
index 3260136..744fe59 100644
--- a/core/java/com/android/internal/usb/DumpUtils.java
+++ b/core/java/com/android/internal/usb/DumpUtils.java
@@ -244,7 +244,8 @@
writeContaminantPresenceStatus(dump, "contaminant_presence_status",
UsbPortStatusProto.CONTAMINANT_PRESENCE_STATUS,
status.getContaminantDetectionStatus());
-
+ dump.write("usb_data_enabled", UsbPortStatusProto.USB_DATA_ENABLED,
+ status.getUsbDataStatus());
dump.end(token);
}
}
diff --git a/core/java/com/android/internal/usb/OWNERS b/core/java/com/android/internal/usb/OWNERS
new file mode 100644
index 0000000..f7b2a37
--- /dev/null
+++ b/core/java/com/android/internal/usb/OWNERS
@@ -0,0 +1 @@
+include /services/usb/OWNERS
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 51185d4..f4f9f94 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1177,38 +1177,40 @@
}
/**
- * Make other apps data directory not visible in CE, DE storage.
+ * Hide the CE and DE data directories of non-related apps.
*
- * Apps without app data isolation can detect if another app is installed on system,
- * by "touching" other apps data directory like /data/data/com.whatsapp, if it returns
- * "Permission denied" it means apps installed, otherwise it returns "File not found".
- * Traditional file permissions or SELinux can only block accessing those directories but
- * can't fix fingerprinting like this.
- * We fix it by "overlaying" data directory, and only relevant app data packages exists
- * in data directories.
+ * Without this, apps can detect if any app is installed by trying to "touch" the app's CE
+ * or DE data directory, e.g. /data/data/com.whatsapp. This fails with EACCES if the app
+ * is installed, or ENOENT if it's not. Traditional file permissions or SELinux can only
+ * block accessing those directories but can't fix fingerprinting like this.
+ *
+ * Instead, we hide non-related apps' data directories from the filesystem entirely by
+ * mounting tmpfs instances over their parent directories and bind-mounting in just the
+ * needed app data directories. This is done in a private mount namespace.
*
* Steps:
- * 1). Collect a list of all related apps (apps with same uid and allowlisted apps) data info
- * (package name, data stored volume uuid, and inode number of its CE data directory)
- * 2). Mount tmpfs on /data/data, /data/user(_de) and /mnt/expand, so apps no longer
- * able to access apps data directly.
- * 3). For each related app, create its app data directory and bind mount the actual content
- * from apps data mirror directory. This works on both CE and DE storage, as DE storage
- * is always available even storage is FBE locked, while we use inode number to find
- * the encrypted DE directory in mirror so we can still bind mount it successfully.
+ * (1) Collect a list of all related apps (apps with same uid and allowlisted apps) data info
+ * (package name, data stored volume uuid, and inode number of its CE data directory)
+ * (2) Mount tmpfs on /data/data and /data/user{,_de}, and on /mnt/expand/$volume/user{,_de}
+ * for all adoptable storage volumes. This hides all app data directories.
+ * (3) For each related app, create stubs for its data directories in the relevant tmpfs
+ * instances, then bind mount in the actual directories from /data_mirror. This works
+ * for both the CE and DE directories. DE storage is always unlocked, whereas the
+ * app's CE directory can be found via inode number if CE storage is locked.
*
- * Example:
- * 0). Assuming com.android.foo CE data is stored in /data/data and no shared uid
- * 1). Mount a tmpfs on /data/data, /data/user, /data/user_de, /mnt/expand
- * List = ["com.android.foo", "null" (volume uuid "null"=default),
- * 123456 (inode number)]
- * 2). On DE storage, we create a directory /data/user_de/0/com.com.android.foo, and bind
- * mount (in the app's mount namespace) it from /data_mirror/data_de/0/com.android.foo.
- * 3). We do similar for CE storage. But in direct boot mode, as /data_mirror/data_ce/0/ is
- * encrypted, we can't find a directory with name com.android.foo on it, so we will
- * use the inode number to find the right directory instead, which that directory content will
- * be decrypted after storage is decrypted.
- *
+ * Example assuming user 0, app "com.android.foo", no shared uid, and no adoptable storage:
+ * (1) Info = ["com.android.foo", "null" (volume uuid "null"=default), "123456" (inode number)]
+ * (2) Mount tmpfs on /data/data, /data/user, and /data/user_de.
+ * (3) For DE storage, create a directory /data/user_de/0/com.android.foo and bind mount
+ * /data_mirror/data_de/0/com.android.foo onto it.
+ * (4) Do similar for CE storage. But if the device is in direct boot mode, then CE
+ * storage will be locked, so the app's CE data directory won't exist at the usual
+ * path /data_mirror/data_ce/0/com.android.foo. It will still exist in
+ * /data_mirror/data_ce/0, but its filename will be an unpredictable no-key name. In
+ * this case, we use the inode number to find the right directory instead. Note that
+ * the bind-mounted app CE data directory will remain locked. It will be unlocked
+ * automatically if/when the user's CE storage is unlocked, since adding an encryption
+ * key takes effect on a whole filesystem instance including all its mounts.
*/
static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list,
uid_t uid, const char* process_name,
@@ -1599,10 +1601,11 @@
// since the directory is owned by root.
if (!is_system_server && getuid() == 0) {
const int rc = createProcessGroup(uid, getpid());
- if (rc == -EROFS) {
- ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
- } else if (rc != 0) {
- ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
+ if (rc != 0) {
+ fail_fn(rc == -EROFS ? CREATE_ERROR("createProcessGroup failed, kernel missing "
+ "CONFIG_CGROUP_CPUACCT?")
+ : CREATE_ERROR("createProcessGroup(%d, %d) failed: %s", uid,
+ /* pid= */ 0, strerror(-rc)));
}
}
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index 45f8c132..cd002da 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -195,9 +195,19 @@
message UsbPortManagerProto {
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;
repeated UsbPortInfoProto usb_ports = 2;
optional bool enable_usb_data_signaling = 3;
+ optional HalVersion hal_version = 4;
}
message UsbPortInfoProto {
@@ -253,6 +263,7 @@
optional DataRole data_role = 4;
repeated UsbPortStatusRoleCombinationProto role_combinations = 5;
optional android.service.ContaminantPresenceStatus contaminant_presence_status = 6;
+ optional bool usb_data_enabled = 7;
}
message UsbPortStatusRoleCombinationProto {
diff --git a/core/tests/PackageInstallerSessions/Android.bp b/core/tests/PackageInstallerSessions/Android.bp
index c112cbb..de2a013 100644
--- a/core/tests/PackageInstallerSessions/Android.bp
+++ b/core/tests/PackageInstallerSessions/Android.bp
@@ -51,6 +51,5 @@
],
platform_apis: true,
- sdk_version: "core_platform",
test_suites: ["device-tests"],
}
diff --git a/core/tests/bugreports/Android.bp b/core/tests/bugreports/Android.bp
index f87797a..43a9679 100644
--- a/core/tests/bugreports/Android.bp
+++ b/core/tests/bugreports/Android.bp
@@ -35,7 +35,6 @@
"truth-prebuilt",
],
test_suites: ["general-tests"],
- sdk_version: "test_current",
platform_apis: true,
}
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 05ec00f..b521184 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -73,7 +73,6 @@
],
platform_apis: true,
- sdk_version: "core_platform",
test_suites: ["device-tests"],
certificate: "platform",
diff --git a/packages/CtsShim/build/Android.bp b/packages/CtsShim/build/Android.bp
index 0b3f9bb..5435113 100644
--- a/packages/CtsShim/build/Android.bp
+++ b/packages/CtsShim/build/Android.bp
@@ -45,6 +45,10 @@
jni_libs: ["libshim_jni"],
uses_libs: ["android.test.runner"],
+
+ apex_available: [
+ "com.android.apex.cts.shim.v2_apk_in_apex_upgrades",
+ ],
}
genrule {
@@ -84,6 +88,7 @@
"//apex_available:platform",
"com.android.apex.cts.shim.v1",
"com.android.apex.cts.shim.v2",
+ "com.android.apex.cts.shim.v2_apk_in_apex_upgrades",
"com.android.apex.cts.shim.v2_no_hashtree",
"com.android.apex.cts.shim.v2_legacy",
"com.android.apex.cts.shim.v2_sdk_target_p",
@@ -159,6 +164,7 @@
"//apex_available:platform",
"com.android.apex.cts.shim.v1",
"com.android.apex.cts.shim.v2",
+ "com.android.apex.cts.shim.v2_apk_in_apex_upgrades",
"com.android.apex.cts.shim.v2_no_hashtree",
"com.android.apex.cts.shim.v2_legacy",
"com.android.apex.cts.shim.v2_sdk_target_p",
diff --git a/packages/CtsShim/build/jni/Android.bp b/packages/CtsShim/build/jni/Android.bp
index ba586db..2dbf2a2 100644
--- a/packages/CtsShim/build/jni/Android.bp
+++ b/packages/CtsShim/build/jni/Android.bp
@@ -32,6 +32,7 @@
"//apex_available:platform",
"com.android.apex.cts.shim.v1",
"com.android.apex.cts.shim.v2",
+ "com.android.apex.cts.shim.v2_apk_in_apex_upgrades",
"com.android.apex.cts.shim.v2_no_hashtree",
"com.android.apex.cts.shim.v2_legacy",
"com.android.apex.cts.shim.v2_sdk_target_p",
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 40662536..4a3350e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -320,7 +320,7 @@
info.className = Switch::class.java.name
}
- override fun performAccessibilityAction(host: View?, action: Int, args: Bundle?): Boolean {
+ override fun performAccessibilityAction(host: View, action: Int, args: Bundle?): Boolean {
if (super.performAccessibilityAction(host, action, args)) {
return true
}
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 99e12a8..ce0e69c 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -91,6 +91,10 @@
if (!volume.isMountedWritable()) {
continue;
}
+ // gsid only supports vfat external storage.
+ if (!"vfat".equalsIgnoreCase(volume.fsType)) {
+ continue;
+ }
DiskInfo disk = volume.getDisk();
long mega = disk.size >> 20;
Slog.i(TAG, volume.getPath() + ": " + mega + " MB");
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 81627a0..2ab477f 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -1803,7 +1803,10 @@
mComputedNightMode = false;
return;
}
- resetNightModeOverrideLocked();
+ if (mNightMode != MODE_NIGHT_AUTO || (mTwilightManager != null
+ && mTwilightManager.getLastTwilightState() != null)) {
+ resetNightModeOverrideLocked();
+ }
}
private boolean resetNightModeOverrideLocked() {
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index dc80c4b..ca16f57 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2425,8 +2425,8 @@
if (!regularZygote) {
// webview and app zygote don't have the permission to create the nodes
if (Process.createProcessGroup(uid, startResult.pid) < 0) {
- Slog.e(ActivityManagerService.TAG, "Unable to create process group for "
- + app.processName + " (" + startResult.pid + ")");
+ throw new AssertionError("Unable to create process group for " + app.processName
+ + " (" + startResult.pid + ")");
}
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index c5ac390..d01030b 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -86,6 +86,7 @@
DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS,
DeviceConfig.NAMESPACE_LMKD_NATIVE,
DeviceConfig.NAMESPACE_MEDIA_NATIVE,
+ DeviceConfig.NAMESPACE_MGLRU_NATIVE,
DeviceConfig.NAMESPACE_NETD_NATIVE,
DeviceConfig.NAMESPACE_NNAPI_NATIVE,
DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 0c47efe..3858d7a 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -174,6 +174,7 @@
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
+import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkIdentity;
@@ -236,6 +237,7 @@
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
+import android.util.SparseSetArray;
import android.util.TypedXmlPullParser;
import android.util.TypedXmlSerializer;
import android.util.Xml;
@@ -624,6 +626,9 @@
/** Map from network ID to last observed roaming state */
@GuardedBy("mNetworkPoliciesSecondLock")
private final SparseBooleanArray mNetworkRoaming = new SparseBooleanArray();
+ /** Map from network ID to the last ifaces on it */
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ private SparseSetArray<String> mNetworkToIfaces = new SparseSetArray<>();
/** Map from netId to subId as of last update */
@GuardedBy("mNetworkPoliciesSecondLock")
@@ -1343,11 +1348,28 @@
return changed;
}
+ @GuardedBy("mNetworkPoliciesSecondLock")
+ private boolean updateNetworkToIfacesNL(int netId, @NonNull ArraySet<String> newIfaces) {
+ // TODO: Add a facility SparseSetArray.contains(key) to return whether the key exists.
+ final ArraySet<String> lastIfaces = mNetworkToIfaces.get(netId);
+ final boolean changed = lastIfaces == null ? true : !lastIfaces.equals(newIfaces);
+
+ if (changed) {
+ // Changed on the same network should remove last ifaces and add new ifaces.
+ // TODO: Add a facility SparseSetArray.put(key, value) for replacing the
+ // value for a given key.
+ mNetworkToIfaces.remove(netId);
+ for (String iface : newIfaces) {
+ mNetworkToIfaces.add(netId, iface);
+ }
+ }
+ return changed;
+ }
+
private final NetworkCallback mNetworkCallback = new NetworkCallback() {
@Override
- public void onCapabilitiesChanged(Network network,
- NetworkCapabilities networkCapabilities) {
- if (network == null || networkCapabilities == null) return;
+ public void onCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
synchronized (mNetworkPoliciesSecondLock) {
final boolean newMetered = !networkCapabilities
@@ -1366,6 +1388,25 @@
}
}
}
+
+ @Override
+ public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties lp) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ final ArraySet<String> newIfaces = new ArraySet<>(lp.getAllInterfaceNames());
+ final boolean ifacesChanged = updateNetworkToIfacesNL(network.getNetId(),
+ newIfaces);
+ if (ifacesChanged) {
+ updateNetworkRulesNL();
+ }
+ }
+ }
+
+ @Override
+ public void onLost(@NonNull Network network) {
+ synchronized (mNetworkPoliciesSecondLock) {
+ mNetworkToIfaces.remove(network.getNetId());
+ }
+ }
};
/**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index fad18d2..7d1dbc5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13257,7 +13257,8 @@
// Don't use profiles since that may cause compilation to be skipped.
final int res = performDexOptInternalWithDependenciesLI(pkg, pkgSetting,
new DexoptOptions(packageName,
- getDefaultCompilerFilter(),
+ REASON_CMDLINE,
+ getDefaultCompilerFilter(), null /* splitName */,
DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
index 7e4f0e7..0a03338 100644
--- a/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/test-apps/DeviceSide/Android.bp
@@ -25,7 +25,6 @@
android_test_helper_app {
name: "PackageManagerServiceDeviceSideTests",
- sdk_version: "test_current",
srcs: ["src/**/*.kt"],
libs: [
"android.test.base",
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 01feacd..4dc5423 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -29,6 +29,7 @@
"android.hardware.usb-V1.1-java",
"android.hardware.usb-V1.2-java",
"android.hardware.usb-V1.3-java",
+ "android.hardware.usb-V1-java",
"android.hardware.usb.gadget-V1.0-java",
"android.hardware.usb.gadget-V1.1-java",
"android.hardware.usb.gadget-V1.2-java",
diff --git a/services/usb/java/com/android/server/usb/UsbPortManager.java b/services/usb/java/com/android/server/usb/UsbPortManager.java
index ec28040..d472639 100644
--- a/services/usb/java/com/android/server/usb/UsbPortManager.java
+++ b/services/usb/java/com/android/server/usb/UsbPortManager.java
@@ -16,6 +16,8 @@
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_PROTECTION_NONE;
import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
@@ -25,6 +27,12 @@
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.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.writePortStatus;
@@ -38,6 +46,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbPort;
@@ -74,9 +83,13 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.dump.DualDumpOutputStream;
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.NoSuchElementException;
+import java.util.Objects;
/**
* Allows trusted components to control the properties of physical USB ports
@@ -109,16 +122,9 @@
// The system context.
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.
// Mostly due a command sent by the remote Usb device.
- private HALCallback mHALCallback = new HALCallback(null, this);
-
- // Cookie sent for usb hal death notification.
- private static final int USB_HAL_DEATH_COOKIE = 1000;
+ //private HALCallback mHALCallback = new HALCallback(null, this);
// Used as the key while sending the bundle to Main thread.
private static final String PORT_INFO = "port_info";
@@ -156,36 +162,23 @@
*/
private int mIsPortContaminatedNotificationId;
- private boolean mEnableUsbDataSignaling;
- protected int mCurrentUsbHalVersion;
+ private UsbPortHal mUsbPortHal;
+
+ private long mTransactionId;
public UsbPortManager(Context context) {
mContext = context;
- 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(null);
+ mUsbPortHal = UsbPortHalInstance.getInstance(this, null);
+ logAndPrint(Log.DEBUG, null, "getInstance done");
}
public void systemReady() {
- mSystemReady = true;
- if (mProxy != null) {
+ mSystemReady = true;
+ if (mUsbPortHal != null) {
+ mUsbPortHal.systemReady();
try {
- mProxy.queryPortStatus();
- mEnableUsbDataSignaling = true;
- } catch (RemoteException e) {
+ mUsbPortHal.queryPortStatus(++mTransactionId);
+ } catch (Exception e) {
logAndPrintException(null,
"ServiceStart: Failed to query port status", e);
}
@@ -340,13 +333,9 @@
}
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(portId, enable);
- } catch (RemoteException e) {
+ mUsbPortHal.enableContaminantPresenceDetection(portId, enable, ++mTransactionId);
+ } catch (Exception 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 @@
*
* @param enable enable or disable USB data signaling
*/
- public boolean enableUsbDataSignal(boolean enable) {
- try {
- mEnableUsbDataSignaling = enable;
- // Call into the hal. Use the castFrom method from HIDL.
- android.hardware.usb.V1_3.IUsb proxy = android.hardware.usb.V1_3.IUsb.castFrom(mProxy);
- return proxy.enableUsbDataSignal(enable);
- } catch (RemoteException e) {
- logAndPrintException(null, "Failed to set USB data signaling", e);
- return false;
- } catch (ClassCastException e) {
- logAndPrintException(null, "Method only applicable to V1.3 or above implementation", e);
+ public boolean enableUsbData(@NonNull String portId, boolean enable, int transactionId,
+ @NonNull IUsbOperationInternal callback, IndentingPrintWriter pw) {
+ Objects.requireNonNull(callback);
+ Objects.requireNonNull(portId);
+ final PortInfo portInfo = mPorts.get(portId);
+ if (portInfo == null) {
+ logAndPrint(Log.ERROR, pw, "enableUsbData: No such port: " + portId
+ + " opId:" + transactionId);
+ try {
+ callback.onOperationComplete(USB_OPERATION_ERROR_PORT_MISMATCH);
+ } catch (RemoteException e) {
+ logAndPrintException(pw,
+ "enableUsbData: Failed to call OperationComplete. opId:"
+ + transactionId, e);
+ }
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
*
* @param none
+ * @return {@link UsbManager#USB_HAL_RETRY} returned when hal version
+ * is yet to be determined.
*/
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;
}
- /**
- * update USB HAL version
- *
- * @param none
- */
- private void updateUsbHalVersion() {
- if (android.hardware.usb.V1_3.IUsb.castFrom(mProxy) != null) {
- mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_3;
- } else if (android.hardware.usb.V1_2.IUsb.castFrom(mProxy) != null) {
- mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_2;
- } else if (android.hardware.usb.V1_1.IUsb.castFrom(mProxy) != null) {
- mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_1;
- } else {
- mCurrentUsbHalVersion = UsbManager.USB_HAL_V1_0;
- }
- logAndPrint(Log.INFO, null, "USB HAL version: " + mCurrentUsbHalVersion);
+ private int toHalUsbDataRole(int usbDataRole) {
+ if (usbDataRole == DATA_ROLE_DEVICE)
+ return HAL_DATA_ROLE_DEVICE;
+ else
+ return HAL_DATA_ROLE_HOST;
+ }
+
+ private int toHalUsbPowerRole(int usbPowerRole) {
+ if (usbPowerRole == POWER_ROLE_SINK)
+ return HAL_POWER_ROLE_SINK;
+ else
+ return HAL_POWER_ROLE_SOURCE;
+ }
+
+ private int toHalUsbMode(int usbMode) {
+ if (usbMode == MODE_UFP)
+ return HAL_MODE_UFP;
+ else
+ return HAL_MODE_DFP;
}
public void setPortRoles(String portId, int newPowerRole, int newDataRole,
@@ -473,7 +495,7 @@
sim.currentPowerRole = newPowerRole;
sim.currentDataRole = newDataRole;
updatePortsLocked(pw, null);
- } else if (mProxy != null) {
+ } else if (mUsbPortHal != null) {
if (currentMode != newMode) {
// Changing the mode will have the side-effect of also changing
// the power and data roles but it might take some time to apply
@@ -485,44 +507,37 @@
logAndPrint(Log.ERROR, pw, "Trying to set the USB port mode: "
+ "portId=" + portId
+ ", newMode=" + UsbPort.modeToString(newMode));
- PortRole newRole = new PortRole();
- newRole.type = PortRoleType.MODE;
- newRole.role = newMode;
try {
- mProxy.switchRole(portId, newRole);
- } catch (RemoteException e) {
+ mUsbPortHal.switchMode(portId, toHalUsbMode(newMode), ++mTransactionId);
+ } catch (Exception e) {
logAndPrintException(pw, "Failed to set the USB port mode: "
+ "portId=" + portId
- + ", newMode=" + UsbPort.modeToString(newRole.role), e);
+ + ", newMode=" + UsbPort.modeToString(newMode), e);
}
} else {
// Change power and data role independently as needed.
if (currentPowerRole != newPowerRole) {
- PortRole newRole = new PortRole();
- newRole.type = PortRoleType.POWER_ROLE;
- newRole.role = newPowerRole;
try {
- mProxy.switchRole(portId, newRole);
- } catch (RemoteException e) {
+ mUsbPortHal.switchPowerRole(portId, toHalUsbPowerRole(newPowerRole),
+ ++mTransactionId);
+ } catch (Exception e) {
logAndPrintException(pw, "Failed to set the USB port power role: "
+ "portId=" + portId
+ ", newPowerRole=" + UsbPort.powerRoleToString
- (newRole.role),
+ (newPowerRole),
e);
return;
}
}
if (currentDataRole != newDataRole) {
- PortRole newRole = new PortRole();
- newRole.type = PortRoleType.DATA_ROLE;
- newRole.role = newDataRole;
try {
- mProxy.switchRole(portId, newRole);
- } catch (RemoteException e) {
+ mUsbPortHal.switchDataRole(portId, toHalUsbDataRole(newDataRole),
+ ++mTransactionId);
+ } catch (Exception e) {
logAndPrintException(pw, "Failed to set the USB port data role: "
+ "portId=" + portId
- + ", newDataRole=" + UsbPort.dataRoleToString(newRole
- .role),
+ + ", newDataRole=" + UsbPort.dataRoleToString
+ (newDataRole),
e);
}
}
@@ -531,6 +546,15 @@
}
}
+ 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) {
synchronized (mLock) {
if (mSimulatedPorts.containsKey(portId)) {
@@ -662,191 +686,12 @@
portInfo.dump(dump, "usb_ports", UsbPortManagerProto.USB_PORTS);
}
- dump.write("enable_usb_data_signaling", UsbPortManagerProto.ENABLE_USB_DATA_SIGNALING,
- mEnableUsbDataSignaling);
+ dump.write("usb_hal_version", UsbPortManagerProto.HAL_VERSION, getUsbHalVersion());
}
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.
* USB hal callback populates and sends the newPortInfo.
@@ -869,7 +714,8 @@
portInfo.supportsEnableContaminantPresenceProtection,
portInfo.contaminantProtectionStatus,
portInfo.supportsEnableContaminantPresenceDetection,
- portInfo.contaminantDetectionStatus, pw);
+ portInfo.contaminantDetectionStatus,
+ portInfo.usbDataEnabled, pw);
}
} else {
for (RawPortInfo currentPortInfo : newPortInfo) {
@@ -881,7 +727,8 @@
currentPortInfo.supportsEnableContaminantPresenceProtection,
currentPortInfo.contaminantProtectionStatus,
currentPortInfo.supportsEnableContaminantPresenceDetection,
- currentPortInfo.contaminantDetectionStatus, pw);
+ currentPortInfo.contaminantDetectionStatus,
+ currentPortInfo.usbDataEnabled, pw);
}
}
@@ -917,6 +764,7 @@
int contaminantProtectionStatus,
boolean supportsEnableContaminantPresenceDetection,
int contaminantDetectionStatus,
+ boolean usbDataEnabled,
IndentingPrintWriter pw) {
// Only allow mode switch capability for dual role ports.
// Validate that the current mode matches the supported modes we expect.
@@ -975,7 +823,7 @@
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus);
+ contaminantDetectionStatus, usbDataEnabled);
mPorts.put(portId, portInfo);
} else {
// Validate that ports aren't changing definition out from under us.
@@ -1012,7 +860,7 @@
currentPowerRole, canChangePowerRole,
currentDataRole, canChangeDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus)) {
+ contaminantDetectionStatus, usbDataEnabled)) {
portInfo.mDisposition = PortInfo.DISPOSITION_CHANGED;
} else {
portInfo.mDisposition = PortInfo.DISPOSITION_READY;
@@ -1141,14 +989,14 @@
}
}
- 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);
if (pw != null) {
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);
if (pw != null) {
pw.println(msg + e);
@@ -1179,7 +1027,7 @@
/**
* 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_CHANGED = 1;
public static final int DISPOSITION_READY = 2;
@@ -1224,7 +1072,7 @@
!= supportedRoleCombinations) {
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, UsbPortStatus.CONTAMINANT_PROTECTION_NONE,
- UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED);
+ UsbPortStatus.CONTAMINANT_DETECTION_NOT_SUPPORTED, true);
dispositionChanged = true;
}
@@ -1243,7 +1091,7 @@
int currentPowerRole, boolean canChangePowerRole,
int currentDataRole, boolean canChangeDataRole,
int supportedRoleCombinations, int contaminantProtectionStatus,
- int contaminantDetectionStatus) {
+ int contaminantDetectionStatus, boolean usbDataEnabled) {
boolean dispositionChanged = false;
mCanChangeMode = canChangeMode;
@@ -1258,10 +1106,12 @@
|| mUsbPortStatus.getContaminantProtectionStatus()
!= contaminantProtectionStatus
|| mUsbPortStatus.getContaminantDetectionStatus()
- != contaminantDetectionStatus) {
+ != contaminantDetectionStatus
+ || mUsbPortStatus.getUsbDataStatus()
+ != usbDataEnabled){
mUsbPortStatus = new UsbPortStatus(currentMode, currentPowerRole, currentDataRole,
supportedRoleCombinations, contaminantProtectionStatus,
- contaminantDetectionStatus);
+ contaminantDetectionStatus, usbDataEnabled);
dispositionChanged = true;
}
@@ -1290,7 +1140,6 @@
UsbPortInfoProto.CONNECTED_AT_MILLIS, mConnectedAtMillis);
dump.write("last_connect_duration_millis",
UsbPortInfoProto.LAST_CONNECT_DURATION_MILLIS, mLastConnectDurationMillis);
-
dump.end(token);
}
@@ -1304,115 +1153,4 @@
+ ", 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];
- }
- };
- }
}
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 3d3538d..28227fc 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -16,6 +16,7 @@
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_HOST;
import static android.hardware.usb.UsbPortStatus.MODE_DFP;
@@ -35,6 +36,7 @@
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.hardware.usb.IUsbManager;
+import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
@@ -44,6 +46,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.usb.UsbServiceDumpProto;
@@ -762,19 +765,30 @@
}
@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);
-
final long ident = Binder.clearCallingIdentity();
+ boolean wait;
try {
if (mPortManager != null) {
- return mPortManager.enableUsbDataSignal(enable);
+ wait = mPortManager.enableUsbData(portId, enable, operationId, callback, null);
} 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 {
Binder.restoreCallingIdentity(ident);
}
+ return wait;
}
@Override
diff --git a/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java b/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java
new file mode 100644
index 0000000..9c6cbbd
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/hal/port/RawPortInfo.java
@@ -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];
+ }
+ };
+}
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
new file mode 100644
index 0000000..1efcd9c
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.usb.hal.port;
+
+import static android.hardware.usb.UsbManager.USB_HAL_V2_0;
+import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL;
+import static android.hardware.usb.UsbOperationInternal.USB_OPERATION_SUCCESS;
+
+import static com.android.server.usb.UsbPortManager.logAndPrint;
+import static com.android.server.usb.UsbPortManager.logAndPrintException;
+
+import android.annotation.Nullable;
+import android.hardware.usb.ContaminantProtectionStatus;
+import android.hardware.usb.IUsb;
+import android.hardware.usb.IUsbOperationInternal;
+import android.hardware.usb.UsbManager.UsbHalVersion;
+import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
+import android.hardware.usb.PortMode;
+import android.hardware.usb.Status;
+import android.hardware.usb.IUsbCallback;
+import android.hardware.usb.PortRole;
+import android.hardware.usb.PortStatus;
+import android.os.ServiceManager;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.usb.UsbPortManager;
+import com.android.server.usb.hal.port.RawPortInfo;
+
+import java.util.ArrayList;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+
+/**
+ * Implements the methods to interact with AIDL USB HAL.
+ */
+public final class UsbPortAidl implements UsbPortHal {
+ private static final String TAG = UsbPortAidl.class.getSimpleName();
+ private static final String USB_AIDL_SERVICE =
+ "android.hardware.usb.IUsb/default";
+ private static final LongSparseArray<IUsbOperationInternal>
+ sCallbacks = new LongSparseArray<>();
+ // Proxy object for the usb hal daemon.
+ @GuardedBy("mLock")
+ private IUsb mProxy;
+ private UsbPortManager mPortManager;
+ public IndentingPrintWriter mPw;
+ // Mutex for all mutable shared state.
+ private final Object mLock = new Object();
+ // Callback when the UsbPort status is changed by the kernel.
+ private HALCallback mHALCallback;
+ private IBinder mBinder;
+ private boolean mSystemReady;
+ private long mTransactionId;
+
+ public @UsbHalVersion int getUsbHalVersion() throws RemoteException {
+ synchronized (mLock) {
+ if (mProxy == null) {
+ throw new RemoteException("IUsb not initialized yet");
+ }
+ }
+ logAndPrint(Log.INFO, null, "USB HAL AIDL version: USB_HAL_V2_0");
+ return USB_HAL_V2_0;
+ }
+
+ @Override
+ public void systemReady() {
+ mSystemReady = true;
+ }
+
+ public void serviceDied() {
+ logAndPrint(Log.ERROR, mPw, "Usb AIDL hal service died");
+ synchronized (mLock) {
+ mProxy = null;
+ }
+ connectToProxy(null);
+ }
+
+ private void connectToProxy(IndentingPrintWriter pw) {
+ synchronized (mLock) {
+ if (mProxy != null) {
+ return;
+ }
+
+ try {
+ mBinder = ServiceManager.waitForService(USB_AIDL_SERVICE);
+ mProxy = IUsb.Stub.asInterface(mBinder);
+ mBinder.linkToDeath(this::serviceDied, 0);
+ mProxy.setCallback(mHALCallback);
+ mProxy.queryPortStatus(++mTransactionId);
+ } catch (NoSuchElementException e) {
+ logAndPrintException(pw, "connectToProxy: usb hal service not found."
+ + " Did the service fail to start?", e);
+ } catch (RemoteException e) {
+ logAndPrintException(pw, "connectToProxy: usb hal service not responding", e);
+ }
+ }
+ }
+
+ static boolean isServicePresent(IndentingPrintWriter pw) {
+ try {
+ return ServiceManager.isDeclared(USB_AIDL_SERVICE);
+ } catch (NoSuchElementException e) {
+ logAndPrintException(pw, "connectToProxy: usb Aidl hal service not found.", e);
+ }
+
+ return false;
+ }
+
+ public UsbPortAidl(UsbPortManager portManager, IndentingPrintWriter pw) {
+ mPortManager = Objects.requireNonNull(portManager);
+ mPw = pw;
+ mHALCallback = new HALCallback(null, mPortManager, this);
+ connectToProxy(mPw);
+ }
+
+ @Override
+ public void enableContaminantPresenceDetection(String portName, boolean enable,
+ long operationID) {
+ synchronized (mLock) {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID: "
+ + operationID);
+ return;
+ }
+
+ try {
+ // Oneway call into the hal. Use the castFrom method from HIDL.
+ mProxy.enableContaminantPresenceDetection(portName, enable, operationID);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw, "Failed to set contaminant detection. opID:"
+ + operationID, e);
+ }
+ }
+ }
+
+ @Override
+ public void queryPortStatus(long operationID) {
+ synchronized (mLock) {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
+ + operationID);
+ return;
+ }
+
+ try {
+ mProxy.queryPortStatus(operationID);
+ } catch (RemoteException e) {
+ logAndPrintException(null, "ServiceStart: Failed to query port status. opID:"
+ + operationID, e);
+ }
+ }
+ }
+
+ @Override
+ public void switchMode(String portId, @HalUsbPortMode int newMode, long operationID) {
+ synchronized (mLock) {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
+ + operationID);
+ return;
+ }
+
+ PortRole newRole = new PortRole();
+ newRole.setMode((byte)newMode);
+ try {
+ mProxy.switchRole(portId, newRole, operationID);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw, "Failed to set the USB port mode: "
+ + "portId=" + portId
+ + ", newMode=" + UsbPort.modeToString(newMode)
+ + "opID:" + operationID, e);
+ }
+ }
+ }
+
+ @Override
+ public void switchPowerRole(String portId, @HalUsbPowerRole int newPowerRole,
+ long operationID) {
+ synchronized (mLock) {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
+ + operationID);
+ return;
+ }
+
+ PortRole newRole = new PortRole();
+ newRole.setPowerRole((byte)newPowerRole);
+ try {
+ mProxy.switchRole(portId, newRole, operationID);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw, "Failed to set the USB power role: portId=" + portId
+ + ", newPowerRole=" + UsbPort.powerRoleToString(newPowerRole)
+ + "opID:" + operationID, e);
+ }
+ }
+ }
+
+ @Override
+ public void switchDataRole(String portId, @HalUsbDataRole int newDataRole, long operationID) {
+ synchronized (mLock) {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw, "Proxy is null. Retry ! opID:"
+ + operationID);
+ return;
+ }
+
+ PortRole newRole = new PortRole();
+ newRole.setDataRole((byte)newDataRole);
+ try {
+ mProxy.switchRole(portId, newRole, operationID);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw, "Failed to set the USB data role: portId=" + portId
+ + ", newDataRole=" + UsbPort.dataRoleToString(newDataRole)
+ + "opID:" + operationID, e);
+ }
+ }
+ }
+
+ @Override
+ public boolean enableUsbData(String portName, boolean enable, long operationID,
+ IUsbOperationInternal callback) {
+ Objects.requireNonNull(portName);
+ Objects.requireNonNull(callback);
+ long key = operationID;
+ synchronized (mLock) {
+ try {
+ if (mProxy == null) {
+ logAndPrint(Log.ERROR, mPw,
+ "enableUsbData: Proxy is null. Retry !opID:"
+ + operationID);
+ callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ return false;
+ }
+ while (sCallbacks.get(key) != null) {
+ key = ThreadLocalRandom.current().nextInt();
+ }
+ if (key != operationID) {
+ logAndPrint(Log.INFO, mPw, "enableUsbData: operationID exists ! opID:"
+ + operationID + " key:" + key);
+ }
+ try {
+ sCallbacks.put(key, callback);
+ mProxy.enableUsbData(portName, enable, key);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw,
+ "enableUsbData: Failed to invoke enableUsbData: portID="
+ + portName + "opID:" + operationID, e);
+ callback.onOperationComplete(USB_OPERATION_ERROR_INTERNAL);
+ sCallbacks.remove(key);
+ return false;
+ }
+ } catch (RemoteException e) {
+ logAndPrintException(mPw,
+ "enableUsbData: Failed to call onOperationComplete portID="
+ + portName + "opID:" + operationID, e);
+ sCallbacks.remove(key);
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private static class HALCallback extends IUsbCallback.Stub {
+ public IndentingPrintWriter mPw;
+ public UsbPortManager mPortManager;
+ public UsbPortAidl mUsbPortAidl;
+
+ HALCallback(IndentingPrintWriter pw, UsbPortManager portManager, UsbPortAidl usbPortAidl) {
+ this.mPw = pw;
+ this.mPortManager = portManager;
+ this.mUsbPortAidl = usbPortAidl;
+ }
+
+ /**
+ * Converts from AIDL defined mode constants to UsbPortStatus constants.
+ * AIDL does not gracefully support bitfield when combined with enums.
+ */
+ private int toPortMode(byte aidlPortMode) {
+ switch (aidlPortMode) {
+ case PortMode.NONE:
+ return UsbPortStatus.MODE_NONE;
+ case PortMode.UFP:
+ return UsbPortStatus.MODE_UFP;
+ case PortMode.DFP:
+ return UsbPortStatus.MODE_DFP;
+ case PortMode.DRP:
+ return UsbPortStatus.MODE_DUAL;
+ case PortMode.AUDIO_ACCESSORY:
+ return UsbPortStatus.MODE_AUDIO_ACCESSORY;
+ case PortMode.DEBUG_ACCESSORY:
+ return UsbPortStatus.MODE_DEBUG_ACCESSORY;
+ default:
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, "Unrecognized aidlPortMode:"
+ + aidlPortMode);
+ return UsbPortStatus.MODE_NONE;
+ }
+ }
+
+ private int toSupportedModes(byte[] aidlPortModes) {
+ int supportedModes = UsbPortStatus.MODE_NONE;
+
+ for (byte aidlPortMode : aidlPortModes) {
+ supportedModes |= toPortMode(aidlPortMode);
+ }
+
+ return supportedModes;
+ }
+
+ /**
+ * Converts from AIDL defined contaminant protection constants to UsbPortStatus constants.
+ * AIDL does not gracefully support bitfield when combined with enums.
+ * Common to both ContaminantProtectionMode and ContaminantProtectionStatus.
+ */
+ private int toContaminantProtectionStatus(byte aidlContaminantProtection) {
+ switch (aidlContaminantProtection) {
+ case ContaminantProtectionStatus.NONE:
+ return UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
+ case ContaminantProtectionStatus.FORCE_SINK:
+ return UsbPortStatus.CONTAMINANT_PROTECTION_SINK;
+ case ContaminantProtectionStatus.FORCE_SOURCE:
+ return UsbPortStatus.CONTAMINANT_PROTECTION_SOURCE;
+ case ContaminantProtectionStatus.FORCE_DISABLE:
+ return UsbPortStatus.CONTAMINANT_PROTECTION_FORCE_DISABLE;
+ case ContaminantProtectionStatus.DISABLED:
+ return UsbPortStatus.CONTAMINANT_PROTECTION_DISABLED;
+ default:
+ UsbPortManager.logAndPrint(Log.ERROR, mPw,
+ "Unrecognized aidlContaminantProtection:"
+ + aidlContaminantProtection);
+ return UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
+ }
+ }
+
+ private int toSupportedContaminantProtectionModes(byte[] aidlModes) {
+ int supportedContaminantProtectionModes = UsbPortStatus.CONTAMINANT_PROTECTION_NONE;
+
+ for (byte aidlMode : aidlModes) {
+ supportedContaminantProtectionModes |= toContaminantProtectionStatus(aidlMode);
+ }
+
+ return supportedContaminantProtectionModes;
+ }
+
+ @Override
+ public void notifyPortStatusChange(
+ android.hardware.usb.PortStatus[] currentPortStatus, int retval) {
+ if (!mUsbPortAidl.mSystemReady) {
+ return;
+ }
+
+ if (retval != Status.SUCCESS) {
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, "port status enquiry failed");
+ return;
+ }
+
+ ArrayList<RawPortInfo> newPortInfo = new ArrayList<>();
+
+ int numStatus = currentPortStatus.length;
+ for (int i = 0; i < numStatus; i++) {
+ PortStatus current = currentPortStatus[i];
+ RawPortInfo temp = new RawPortInfo(current.portName,
+ toSupportedModes(current.supportedModes),
+ toSupportedContaminantProtectionModes(current
+ .supportedContaminantProtectionModes),
+ toPortMode(current.currentMode),
+ current.canChangeMode,
+ current.currentPowerRole,
+ current.canChangePowerRole,
+ current.currentDataRole,
+ current.canChangeDataRole,
+ current.supportsEnableContaminantPresenceProtection,
+ toContaminantProtectionStatus(current.contaminantProtectionStatus),
+ current.supportsEnableContaminantPresenceDetection,
+ current.contaminantDetectionStatus,
+ current.usbDataEnabled);
+ newPortInfo.add(temp);
+ UsbPortManager.logAndPrint(Log.INFO, mPw, "ClientCallback AIDL V1: "
+ + current.portName);
+ }
+ mPortManager.updatePorts(newPortInfo);
+ }
+
+ @Override
+ public void notifyRoleSwitchStatus(String portName, PortRole role, int retval,
+ long operationID) {
+ if (retval == Status.SUCCESS) {
+ UsbPortManager.logAndPrint(Log.INFO, mPw, portName
+ + " role switch successful. opID:"
+ + operationID);
+ } else {
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, portName + " role switch failed. err:"
+ + retval
+ + "opID:" + operationID);
+ }
+ }
+
+ @Override
+ public void notifyQueryPortStatus(String portName, int retval, long operationID) {
+ if (retval == Status.SUCCESS) {
+ UsbPortManager.logAndPrint(Log.INFO, mPw, portName + ": opID:"
+ + operationID + " successful");
+ } else {
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, portName + ": opID:"
+ + operationID + " failed. err:" + retval);
+ }
+ }
+
+ @Override
+ public void notifyEnableUsbDataStatus(String portName, boolean enable, int retval,
+ long operationID) {
+ if (retval == Status.SUCCESS) {
+ UsbPortManager.logAndPrint(Log.INFO, mPw, "notifyEnableUsbDataStatus:"
+ + portName + ": opID:"
+ + operationID + " enable:" + enable);
+ } else {
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
+ + "notifyEnableUsbDataStatus: opID:"
+ + operationID + " failed. err:" + retval);
+ }
+ try {
+ sCallbacks.get(operationID).onOperationComplete(retval == Status.SUCCESS
+ ? USB_OPERATION_SUCCESS
+ : USB_OPERATION_ERROR_INTERNAL);
+ } catch (RemoteException e) {
+ logAndPrintException(mPw,
+ "notifyEnableUsbDataStatus: Failed to call onOperationComplete",
+ e);
+ }
+ }
+
+ @Override
+ public void notifyContaminantEnabledStatus(String portName, boolean enable, int retval,
+ long operationID) {
+ if (retval == Status.SUCCESS) {
+ UsbPortManager.logAndPrint(Log.INFO, mPw, "notifyContaminantEnabledStatus:"
+ + portName + ": opID:"
+ + operationID + " enable:" + enable);
+ } else {
+ UsbPortManager.logAndPrint(Log.ERROR, mPw, portName
+ + "notifyContaminantEnabledStatus: opID:"
+ + operationID + " failed. err:" + retval);
+ }
+ }
+
+ @Override
+ public String getInterfaceHash() {
+ return IUsbCallback.HASH;
+ }
+
+ @Override
+ public int getInterfaceVersion() {
+ return IUsbCallback.VERSION;
+ }
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
new file mode 100644
index 0000000..e7f9bc2
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHal.java
@@ -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);
+}
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
new file mode 100644
index 0000000..41f9fae
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHalInstance.java
@@ -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;
+ }
+}
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
new file mode 100644
index 0000000..00d0d06
--- /dev/null
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortHidl.java
@@ -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");
+ }
+ }
+ }
+}
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 7ea4ab1..0aca293 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -27,7 +27,7 @@
static ApiVersion sDevelopmentSdkLevel = 10000;
static const auto sDevelopmentSdkCodeNames =
- std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu"});
+ std::unordered_set<StringPiece>({"Q", "R", "S", "Sv2", "Tiramisu", "UpsideDownCake"});
static const std::vector<std::pair<uint16_t, ApiVersion>> sAttrIdMap = {
{0x021c, 1},