summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Roy Luo <royluo@google.com> 2024-04-11 00:35:40 +0000
committer Roy Luo <royluo@google.com> 2024-06-13 03:33:18 +0000
commite36f88c420fe00112e11e85634851d047c0b623e (patch)
tree7161fbdb660c389a607892b64f2996d1e08d1fb0
parent2246bcc52e89d961d8d8d9bbaf708b44d1557ec8 (diff)
Support identifying usb midi device using usb sysfs
Out-of-tree ACK patches previously enabled MIDI device identification via the "/sys/class/android_usb/android0/f_midi/alsa" sysfs node. This change introduces a new, upstream-compliant method for MIDI device identification. This method requires the upstream patch [1] within the underlying ACK. [1] https://patchwork.kernel.org/project/linux-usb/patch/20240307030922.3573161-1-royluo@google.com/ Flag: android.hardware.usb.flags.enable_usb_sysfs_midi_identification Bug: 333778731 Test: exercise usb midi with the flag on/off Change-Id: I64635f083541bfc59bfa4857d0fc5f20a5f3c2f5
-rw-r--r--core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig9
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java75
2 files changed, 72 insertions, 12 deletions
diff --git a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
index 967fc42e8783..0f944cfb7f67 100644
--- a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
+++ b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
@@ -28,4 +28,11 @@ flag {
namespace: "preload_safety"
description: "Enables signal API with staking"
bug: "287498482"
-} \ No newline at end of file
+}
+
+flag {
+ name: "enable_usb_sysfs_midi_identification"
+ namespace: "system_sw_usb"
+ description: "Enable identifying midi device using USB sysfs"
+ bug: "333778731"
+}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index e8bac66a724a..175a09db54e3 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -80,6 +80,7 @@ import android.service.usb.UsbDeviceManagerProto;
import android.service.usb.UsbHandlerProto;
import android.util.Pair;
import android.util.Slog;
+import android.text.TextUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
@@ -110,6 +111,8 @@ import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* UsbDeviceManager manages USB state in device mode.
@@ -135,6 +138,11 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
*/
private static final String NORMAL_BOOT = "normal";
+ /**
+ * UDC controller for the ConfigFS USB Gadgets.
+ */
+ private static final String USB_CONTROLLER_NAME_PROPERTY = "sys.usb.controller";
+
private static final String USB_STATE_MATCH =
"DEVPATH=/devices/virtual/android_usb/android0";
private static final String ACCESSORY_START_MATCH =
@@ -932,6 +940,42 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
sEventLogger.enqueue(new EventLogger.StringEvent("USB intent: " + intent));
}
+ private void getMidiCardDevice() throws FileNotFoundException {
+ String controllerName = getSystemProperty(USB_CONTROLLER_NAME_PROPERTY, "");
+ if (TextUtils.isEmpty(controllerName)) {
+ throw new FileNotFoundException("controller name not found");
+ }
+
+ File soundDir = new File("/sys/class/udc/" + controllerName + "/gadget/sound");
+ if (!soundDir.exists()) {
+ throw new FileNotFoundException("sound device not found");
+ }
+
+ // There should be exactly one sound card
+ File[] cardDirs = FileUtils.listFilesOrEmpty(soundDir,
+ (dir, file) -> file.startsWith("card"));
+ if (cardDirs.length != 1) {
+ throw new FileNotFoundException("sound card not match");
+ }
+
+ // There should be exactly one midi device
+ File[] midis = FileUtils.listFilesOrEmpty(cardDirs[0],
+ (dir, file) -> file.startsWith("midi"));
+ if (midis.length != 1) {
+ throw new FileNotFoundException("MIDI device not match");
+ }
+
+ Pattern pattern = Pattern.compile("midiC(\\d+)D(\\d+)");
+ Matcher matcher = pattern.matcher(midis[0].getName());
+ if (matcher.matches()) {
+ mMidiCard = Integer.parseInt(matcher.group(1));
+ mMidiDevice = Integer.parseInt(matcher.group(2));
+ Slog.i(TAG, "Found MIDI card " + mMidiCard + " device " + mMidiDevice);
+ } else {
+ throw new FileNotFoundException("MIDI name not match");
+ }
+ }
+
private void updateUsbFunctions() {
updateMidiFunction();
updateMtpFunction();
@@ -941,17 +985,26 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser
boolean enabled = (mCurrentFunctions & UsbManager.FUNCTION_MIDI) != 0;
if (enabled != mMidiEnabled) {
if (enabled) {
- Scanner scanner = null;
- try {
- scanner = new Scanner(new File(MIDI_ALSA_PATH));
- mMidiCard = scanner.nextInt();
- mMidiDevice = scanner.nextInt();
- } catch (FileNotFoundException e) {
- Slog.e(TAG, "could not open MIDI file", e);
- enabled = false;
- } finally {
- if (scanner != null) {
- scanner.close();
+ if (android.hardware.usb.flags.Flags.enableUsbSysfsMidiIdentification()) {
+ try {
+ getMidiCardDevice();
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "could not identify MIDI device", e);
+ enabled = false;
+ }
+ } else {
+ Scanner scanner = null;
+ try {
+ scanner = new Scanner(new File(MIDI_ALSA_PATH));
+ mMidiCard = scanner.nextInt();
+ mMidiDevice = scanner.nextInt();
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "could not open MIDI file", e);
+ enabled = false;
+ } finally {
+ if (scanner != null) {
+ scanner.close();
+ }
}
}
}