diff options
| author | 2024-04-11 00:35:40 +0000 | |
|---|---|---|
| committer | 2024-06-13 03:33:18 +0000 | |
| commit | e36f88c420fe00112e11e85634851d047c0b623e (patch) | |
| tree | 7161fbdb660c389a607892b64f2996d1e08d1fb0 | |
| parent | 2246bcc52e89d961d8d8d9bbaf708b44d1557ec8 (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.aconfig | 9 | ||||
| -rw-r--r-- | services/usb/java/com/android/server/usb/UsbDeviceManager.java | 75 |
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(); + } } } } |