Usb: Add UVC support to UsbManager and UsbDeviceManager
This CL adds support for UVC gadget function in USB System service.
Bug: 242344221
Test: Manually tested that the UVC function can be enabled when needed.
API-Coverage-Bug: 267667903
Change-Id: Ifd93f065426a224274ec39f53366dd6e3fee0bfa
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 4a0b2eb..3c6014c 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5832,6 +5832,7 @@
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions();
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List<android.hardware.usb.UsbPort> getPorts();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String);
+ method public static boolean isUvcSupportEnabled();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public boolean registerDisplayPortAltModeInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.usb.UsbManager.DisplayPortAltModeInfoListener);
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbGadget();
method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
@@ -5853,6 +5854,7 @@
field public static final long FUNCTION_NONE = 0L; // 0x0L
field public static final long FUNCTION_PTP = 16L; // 0x10L
field public static final long FUNCTION_RNDIS = 32L; // 0x20L
+ field public static final long FUNCTION_UVC = 128L; // 0x80L
field public static final String USB_CONFIGURED = "configured";
field public static final String USB_CONNECTED = "connected";
field public static final String USB_FUNCTION_NCM = "ncm";
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 0483b71..71ec1c6 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -45,6 +45,7 @@
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -99,6 +100,8 @@
* audio source function is enabled
* <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
* MIDI function is enabled
+ * <li> {@link #USB_FUNCTION_UVC} boolean extra indicating whether the
+ * UVC function is enabled
* </ul>
* If the sticky intent has not been found, that indicates USB is disconnected,
* USB is not configured, MTP function is enabled, and all the other functions are disabled.
@@ -314,6 +317,14 @@
public static final String USB_FUNCTION_NCM = "ncm";
/**
+ * Name of the UVC USB function.
+ * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+ *
+ * @hide
+ */
+ public static final String USB_FUNCTION_UVC = "uvc";
+
+ /**
* Name of Gadget Hal Not Present;
*
* @hide
@@ -683,8 +694,17 @@
@SystemApi
public static final long FUNCTION_NCM = 1 << 10;
+ /**
+ * Code for the uvc usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
+ * Only supported if {@link #isUvcSupportEnabled()} returns true.
+ * Must be equal to {@link GadgetFunction#UVC}
+ * @hide
+ */
+ @SystemApi
+ public static final long FUNCTION_UVC = 1 << 7;
+
private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
- | FUNCTION_MIDI | FUNCTION_NCM;
+ | FUNCTION_MIDI | FUNCTION_NCM | FUNCTION_UVC;
private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
@@ -702,6 +722,7 @@
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM);
+ FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_UVC, FUNCTION_UVC);
}
/** @hide */
@@ -715,6 +736,7 @@
FUNCTION_AUDIO_SOURCE,
FUNCTION_ADB,
FUNCTION_NCM,
+ FUNCTION_UVC,
})
public @interface UsbFunctionMode {}
@@ -1337,6 +1359,21 @@
}
/**
+ * Returns whether UVC is advertised to be supported or not. SELinux
+ * enforces that this function returns {@code false} when called from a
+ * process that doesn't belong either to a system app, or the
+ * DeviceAsWebcam Service.
+ *
+ * @return true if UVC is supported, false if UVC is not supported or if
+ * called from a non-system app that isn't DeviceAsWebcam Service.
+ * @hide
+ */
+ @SystemApi
+ public static boolean isUvcSupportEnabled() {
+ return SystemProperties.getBoolean("ro.usb.uvc.enabled", false);
+ }
+
+ /**
* Enable/Disable the USB data signaling.
* <p>
* Enables/Disables USB data path of all USB ports.
@@ -1716,7 +1753,7 @@
/**
* Returns whether the given functions are valid inputs to UsbManager.
- * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM are accepted.
+ * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM, UVC are accepted.
*
* Only one function may be set at a time, except for RNDIS and NCM, which can be set together
* because from a user perspective they are the same function (tethering).
@@ -1762,6 +1799,9 @@
if ((functions & FUNCTION_NCM) != 0) {
joiner.add(UsbManager.USB_FUNCTION_NCM);
}
+ if ((functions & FUNCTION_UVC) != 0) {
+ joiner.add(UsbManager.USB_FUNCTION_UVC);
+ }
if ((functions & FUNCTION_ADB) != 0) {
joiner.add(UsbManager.USB_FUNCTION_ADB);
}
diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto
index c98e346..8889320 100644
--- a/core/proto/android/service/usb.proto
+++ b/core/proto/android/service/usb.proto
@@ -45,7 +45,7 @@
message UsbHandlerProto {
option (android.msg_privacy).dest = DEST_AUTOMATIC;
- /* Same as android.hardware.usb.gadget.V1_0.GadgetFunction.* */
+ /* Same as android.hardware.usb.gadget.GadgetFunction.* */
enum Function {
FUNCTION_ADB = 1;
FUNCTION_ACCESSORY = 2;
@@ -54,6 +54,7 @@
FUNCTION_PTP = 16;
FUNCTION_RNDIS = 32;
FUNCTION_AUDIO_SOURCE = 64;
+ FUNCTION_UVC = 128;
}
repeated Function current_functions = 1;
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index da44c2e..db43813 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3699,6 +3699,8 @@
<string name="usb_tether_notification_title">USB tethering turned on</string>
<!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in MIDI mode. This is the title -->
<string name="usb_midi_notification_title">MIDI via USB turned on</string>
+ <!-- USB_PREFERENCES: Notification for when the user connects the phone to a computer via USB in UVC mode. This is the title -->
+ <string name="usb_uvc_notification_title">Device connected as Webcam</string>
<!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title -->
<string name="usb_accessory_notification_title">USB accessory connected</string>
<!-- See USB_PREFERENCES. This is the message. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7754256..c4be8c2 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2143,6 +2143,7 @@
<java-symbol type="string" name="usb_power_notification_message" />
<java-symbol type="string" name="usb_ptp_notification_title" />
<java-symbol type="string" name="usb_midi_notification_title" />
+ <java-symbol type="string" name="usb_uvc_notification_title" />
<java-symbol type="string" name="usb_tether_notification_title" />
<java-symbol type="string" name="usb_supplying_notification_title" />
<java-symbol type="string" name="usb_unsupported_audio_accessory_title" />
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 12e7226..12a8230 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -306,6 +306,10 @@
// Package: android
NOTE_BT_APM_NOTIFICATION = 74;
+ // Inform that USB is configured as a Universal Video Class gadget
+ // Package: android
+ NOTE_USB_UVC = 75;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index a480ebd..12e5ed9 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -44,7 +44,6 @@
import android.debug.AdbNotifications;
import android.debug.AdbTransportType;
import android.debug.IAdbTransport;
-import android.hardware.usb.IUsbOperationInternal;
import android.hardware.usb.ParcelableUsbPort;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbConfiguration;
@@ -57,7 +56,6 @@
import android.hardware.usb.gadget.V1_0.GadgetFunction;
import android.hardware.usb.gadget.V1_0.Status;
import android.hardware.usb.gadget.V1_2.UsbSpeed;
-import android.hidl.manager.V1_0.IServiceManager;
import android.hidl.manager.V1_0.IServiceNotification;
import android.os.BatteryManager;
import android.os.Environment;
@@ -1351,6 +1349,9 @@
|| (mCurrentFunctions == UsbManager.FUNCTION_NCM)) {
titleRes = com.android.internal.R.string.usb_tether_notification_title;
id = SystemMessage.NOTE_USB_TETHER;
+ } else if (mCurrentFunctions == UsbManager.FUNCTION_UVC) {
+ titleRes = com.android.internal.R.string.usb_uvc_notification_title;
+ id = SystemMessage.NOTE_USB_UVC;
} else if (mCurrentFunctions == UsbManager.FUNCTION_ACCESSORY) {
titleRes = com.android.internal.R.string.usb_accessory_notification_title;
id = SystemMessage.NOTE_USB_ACCESSORY;
@@ -2403,6 +2404,9 @@
MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_RNDIS);
} else if (functions == UsbManager.FUNCTION_ACCESSORY) {
MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_ACCESSORY);
+ } else if (functions == UsbManager.FUNCTION_UVC) {
+ // MetricsLogger.action(mContext, MetricsEvent.ACTION_USB_CONFIG_UVC);
+ // TODO: Add MetricsEvent for UVC?
}
mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, operationId);
}