am 946863b6: Merge "Fix USB audio disconnect logic" into lmp-mr1-dev
automerge: 61cf7e0
* commit '61cf7e0fe7e79df53ff00a25241041ec99096105':
Fix USB audio disconnect logic
This commit is contained in:
197
services/usb/java/com/android/server/usb/UsbAudioManager.java
Normal file
197
services/usb/java/com/android/server/usb/UsbAudioManager.java
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 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 an
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.server.usb;
|
||||||
|
|
||||||
|
import android.alsa.AlsaCardsParser;
|
||||||
|
import android.alsa.AlsaDevicesParser;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.hardware.usb.UsbConstants;
|
||||||
|
import android.hardware.usb.UsbDevice;
|
||||||
|
import android.hardware.usb.UsbInterface;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.util.Slog;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UsbAudioManager manages USB audio devices.
|
||||||
|
*/
|
||||||
|
public class UsbAudioManager {
|
||||||
|
private static final String TAG = UsbAudioManager.class.getSimpleName();
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
private final class AudioDevice {
|
||||||
|
public int mCard;
|
||||||
|
public int mDevice;
|
||||||
|
public boolean mHasPlayback;
|
||||||
|
public boolean mHasCapture;
|
||||||
|
public boolean mHasMIDI;
|
||||||
|
|
||||||
|
public AudioDevice(int card, int device,
|
||||||
|
boolean hasPlayback, boolean hasCapture, boolean hasMidi) {
|
||||||
|
mCard = card;
|
||||||
|
mDevice = device;
|
||||||
|
mHasPlayback = hasPlayback;
|
||||||
|
mHasCapture = hasCapture;
|
||||||
|
mHasMIDI = hasMidi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("AudioDevice: [card: " + mCard);
|
||||||
|
sb.append(", device: " + mDevice);
|
||||||
|
sb.append(", hasPlayback: " + mHasPlayback);
|
||||||
|
sb.append(", hasCapture: " + mHasCapture);
|
||||||
|
sb.append(", hasMidi: " + mHasMIDI);
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final HashMap<UsbDevice,AudioDevice> mAudioDevices
|
||||||
|
= new HashMap<UsbDevice,AudioDevice>();
|
||||||
|
|
||||||
|
/* package */ UsbAudioManager(Context context) {
|
||||||
|
mContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcasts the arrival/departure of a USB audio interface
|
||||||
|
// audioDevice - the AudioDevice that was added or removed
|
||||||
|
// enabled - if true, we're connecting a device (it's arrived), else disconnecting
|
||||||
|
private void sendDeviceNotification(AudioDevice audioDevice, boolean enabled) {
|
||||||
|
// send a sticky broadcast containing current USB state
|
||||||
|
Intent intent = new Intent(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG);
|
||||||
|
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
|
||||||
|
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
|
||||||
|
intent.putExtra("state", enabled ? 1 : 0);
|
||||||
|
intent.putExtra("card", audioDevice.mCard);
|
||||||
|
intent.putExtra("device", audioDevice.mDevice);
|
||||||
|
intent.putExtra("hasPlayback", audioDevice.mHasPlayback);
|
||||||
|
intent.putExtra("hasCapture", audioDevice.mHasCapture);
|
||||||
|
intent.putExtra("hasMIDI", audioDevice.mHasMIDI);
|
||||||
|
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean waitForAlsaFile(int card, int device, boolean capture) {
|
||||||
|
// These values were empirically determined.
|
||||||
|
final int kNumRetries = 5;
|
||||||
|
final int kSleepTime = 500; // ms
|
||||||
|
String alsaDevPath = "/dev/snd/pcmC" + card + "D" + device + (capture ? "c" : "p");
|
||||||
|
File alsaDevFile = new File(alsaDevPath);
|
||||||
|
boolean exists = false;
|
||||||
|
for (int retry = 0; !exists && retry < kNumRetries; retry++) {
|
||||||
|
exists = alsaDevFile.exists();
|
||||||
|
if (!exists) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(kSleepTime);
|
||||||
|
} catch (IllegalThreadStateException ex) {
|
||||||
|
Slog.d(TAG, "usb: IllegalThreadStateException while waiting for ALSA file.");
|
||||||
|
} catch (java.lang.InterruptedException ex) {
|
||||||
|
Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void deviceAdded(UsbDevice usbDevice) {
|
||||||
|
// Is there an audio interface in there?
|
||||||
|
boolean isAudioDevice = false;
|
||||||
|
|
||||||
|
// FIXME - handle multiple configurations?
|
||||||
|
int interfaceCount = usbDevice.getInterfaceCount();
|
||||||
|
for (int ntrfaceIndex = 0; !isAudioDevice && ntrfaceIndex < interfaceCount;
|
||||||
|
ntrfaceIndex++) {
|
||||||
|
UsbInterface ntrface = usbDevice.getInterface(ntrfaceIndex);
|
||||||
|
if (ntrface.getInterfaceClass() == UsbConstants.USB_CLASS_AUDIO) {
|
||||||
|
isAudioDevice = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!isAudioDevice) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO(pmclean) The "Parser" objects inspect files in "/proc/asound" which we presume is
|
||||||
|
// present, unlike the waitForAlsaFile() which waits on a file in /dev/snd. It is not
|
||||||
|
// clear why this works, or that it can be relied on going forward. Needs further
|
||||||
|
// research.
|
||||||
|
AlsaCardsParser cardsParser = new AlsaCardsParser();
|
||||||
|
cardsParser.scan();
|
||||||
|
// cardsParser.Log();
|
||||||
|
|
||||||
|
// But we need to parse the device to determine its capabilities.
|
||||||
|
AlsaDevicesParser devicesParser = new AlsaDevicesParser();
|
||||||
|
devicesParser.scan();
|
||||||
|
// devicesParser.Log();
|
||||||
|
|
||||||
|
// The protocol for now will be to select the last-connected (highest-numbered)
|
||||||
|
// Alsa Card.
|
||||||
|
int card = cardsParser.getNumCardRecords() - 1;
|
||||||
|
int device = 0;
|
||||||
|
|
||||||
|
boolean hasPlayback = devicesParser.hasPlaybackDevices(card);
|
||||||
|
boolean hasCapture = devicesParser.hasCaptureDevices(card);
|
||||||
|
boolean hasMidi = devicesParser.hasMIDIDevices(card);
|
||||||
|
|
||||||
|
// Playback device file needed/present?
|
||||||
|
if (hasPlayback &&
|
||||||
|
!waitForAlsaFile(card, device, false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture device file needed/present?
|
||||||
|
if (hasCapture &&
|
||||||
|
!waitForAlsaFile(card, device, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG,
|
||||||
|
"usb: hasPlayback:" + hasPlayback + " hasCapture:" + hasCapture);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioDevice audioDevice = new AudioDevice(card, device, hasPlayback, hasCapture, hasMidi);
|
||||||
|
mAudioDevices.put(usbDevice, audioDevice);
|
||||||
|
sendDeviceNotification(audioDevice, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ void deviceRemoved(UsbDevice device) {
|
||||||
|
if (DEBUG) {
|
||||||
|
Slog.d(TAG, "deviceRemoved(): " + device);
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioDevice audioDevice = mAudioDevices.remove(device);
|
||||||
|
if (audioDevice != null) {
|
||||||
|
sendDeviceNotification(audioDevice, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump(FileDescriptor fd, PrintWriter pw) {
|
||||||
|
pw.println(" USB AudioDevices:");
|
||||||
|
for (UsbDevice device : mAudioDevices.keySet()) {
|
||||||
|
pw.println(" " + device.getDeviceName() + ": " + mAudioDevices.get(device));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package com.android.server.usb;
|
package com.android.server.usb;
|
||||||
|
|
||||||
import android.alsa.AlsaCardsParser;
|
|
||||||
import android.alsa.AlsaDevicesParser;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.hardware.usb.UsbConfiguration;
|
import android.hardware.usb.UsbConfiguration;
|
||||||
@@ -25,16 +23,13 @@ import android.hardware.usb.UsbConstants;
|
|||||||
import android.hardware.usb.UsbDevice;
|
import android.hardware.usb.UsbDevice;
|
||||||
import android.hardware.usb.UsbEndpoint;
|
import android.hardware.usb.UsbEndpoint;
|
||||||
import android.hardware.usb.UsbInterface;
|
import android.hardware.usb.UsbInterface;
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.os.UserHandle;
|
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
|
||||||
import com.android.internal.annotations.GuardedBy;
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -46,11 +41,12 @@ import java.util.HashMap;
|
|||||||
*/
|
*/
|
||||||
public class UsbHostManager {
|
public class UsbHostManager {
|
||||||
private static final String TAG = UsbHostManager.class.getSimpleName();
|
private static final String TAG = UsbHostManager.class.getSimpleName();
|
||||||
private static final boolean DEBUG_AUDIO = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
// contains all connected USB devices
|
// contains all connected USB devices
|
||||||
private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
|
private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
|
||||||
|
|
||||||
|
|
||||||
// USB busses to exclude from USB host support
|
// USB busses to exclude from USB host support
|
||||||
private final String[] mHostBlacklist;
|
private final String[] mHostBlacklist;
|
||||||
|
|
||||||
@@ -64,14 +60,7 @@ public class UsbHostManager {
|
|||||||
private ArrayList<UsbInterface> mNewInterfaces;
|
private ArrayList<UsbInterface> mNewInterfaces;
|
||||||
private ArrayList<UsbEndpoint> mNewEndpoints;
|
private ArrayList<UsbEndpoint> mNewEndpoints;
|
||||||
|
|
||||||
// Attributes of any connected USB audio device.
|
private UsbAudioManager mUsbAudioManager;
|
||||||
//TODO(pmclean) When we extend to multiple, USB Audio devices, we will need to get
|
|
||||||
// more clever about this.
|
|
||||||
private int mConnectedUsbCard = -1;
|
|
||||||
private int mConnectedUsbDeviceNum = -1;
|
|
||||||
private boolean mConnectedHasPlayback = false;
|
|
||||||
private boolean mConnectedHasCapture = false;
|
|
||||||
private boolean mConnectedHasMIDI = false;
|
|
||||||
|
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private UsbSettingsManager mCurrentSettings;
|
private UsbSettingsManager mCurrentSettings;
|
||||||
@@ -80,6 +69,7 @@ public class UsbHostManager {
|
|||||||
mContext = context;
|
mContext = context;
|
||||||
mHostBlacklist = context.getResources().getStringArray(
|
mHostBlacklist = context.getResources().getStringArray(
|
||||||
com.android.internal.R.array.config_usbHostBlacklist);
|
com.android.internal.R.array.config_usbHostBlacklist);
|
||||||
|
mUsbAudioManager = new UsbAudioManager(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentSettings(UsbSettingsManager settings) {
|
public void setCurrentSettings(UsbSettingsManager settings) {
|
||||||
@@ -118,48 +108,6 @@ public class UsbHostManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Broadcasts the arrival/departure of a USB audio interface
|
|
||||||
// card - the ALSA card number of the physical interface
|
|
||||||
// device - the ALSA device number of the physical interface
|
|
||||||
// enabled - if true, we're connecting a device (it's arrived), else disconnecting
|
|
||||||
private void sendDeviceNotification(int card, int device, boolean enabled,
|
|
||||||
boolean hasPlayback, boolean hasCapture, boolean hasMIDI) {
|
|
||||||
// send a sticky broadcast containing current USB state
|
|
||||||
Intent intent = new Intent(AudioManager.ACTION_USB_AUDIO_DEVICE_PLUG);
|
|
||||||
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
|
|
||||||
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
|
|
||||||
intent.putExtra("state", enabled ? 1 : 0);
|
|
||||||
intent.putExtra("card", card);
|
|
||||||
intent.putExtra("device", device);
|
|
||||||
intent.putExtra("hasPlayback", hasPlayback);
|
|
||||||
intent.putExtra("hasCapture", hasCapture);
|
|
||||||
intent.putExtra("hasMIDI", hasMIDI);
|
|
||||||
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean waitForAlsaFile(int card, int device, boolean capture) {
|
|
||||||
// These values were empirically determined.
|
|
||||||
final int kNumRetries = 5;
|
|
||||||
final int kSleepTime = 500; // ms
|
|
||||||
String alsaDevPath = "/dev/snd/pcmC" + card + "D" + device + (capture ? "c" : "p");
|
|
||||||
File alsaDevFile = new File(alsaDevPath);
|
|
||||||
boolean exists = false;
|
|
||||||
for (int retry = 0; !exists && retry < kNumRetries; retry++) {
|
|
||||||
exists = alsaDevFile.exists();
|
|
||||||
if (!exists) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(kSleepTime);
|
|
||||||
} catch (IllegalThreadStateException ex) {
|
|
||||||
Slog.d(TAG, "usb: IllegalThreadStateException while waiting for ALSA file.");
|
|
||||||
} catch (java.lang.InterruptedException ex) {
|
|
||||||
Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return exists;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Called from JNI in monitorUsbHostBus() to report new USB devices
|
/* Called from JNI in monitorUsbHostBus() to report new USB devices
|
||||||
Returns true if successful, in which case the JNI code will continue adding configurations,
|
Returns true if successful, in which case the JNI code will continue adding configurations,
|
||||||
interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
|
interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
|
||||||
@@ -169,7 +117,7 @@ public class UsbHostManager {
|
|||||||
int deviceClass, int deviceSubclass, int deviceProtocol,
|
int deviceClass, int deviceSubclass, int deviceProtocol,
|
||||||
String manufacturerName, String productName, String serialNumber) {
|
String manufacturerName, String productName, String serialNumber) {
|
||||||
|
|
||||||
if (DEBUG_AUDIO) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
|
Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
|
||||||
// Audio Class Codes:
|
// Audio Class Codes:
|
||||||
// Audio: 0x01
|
// Audio: 0x01
|
||||||
@@ -254,7 +202,7 @@ public class UsbHostManager {
|
|||||||
|
|
||||||
/* Called from JNI in monitorUsbHostBus() to finish adding a new device */
|
/* Called from JNI in monitorUsbHostBus() to finish adding a new device */
|
||||||
private void endUsbDeviceAdded() {
|
private void endUsbDeviceAdded() {
|
||||||
if (DEBUG_AUDIO) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
|
Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
|
||||||
}
|
}
|
||||||
if (mNewInterface != null) {
|
if (mNewInterface != null) {
|
||||||
@@ -266,16 +214,6 @@ public class UsbHostManager {
|
|||||||
mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
|
mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is there an audio interface in there?
|
|
||||||
final int kUsbClassId_Audio = 0x01;
|
|
||||||
boolean isAudioDevice = false;
|
|
||||||
for (int ntrfaceIndex = 0; !isAudioDevice && ntrfaceIndex < mNewInterfaces.size();
|
|
||||||
ntrfaceIndex++) {
|
|
||||||
UsbInterface ntrface = mNewInterfaces.get(ntrfaceIndex);
|
|
||||||
if (ntrface.getInterfaceClass() == kUsbClassId_Audio) {
|
|
||||||
isAudioDevice = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mNewDevice != null) {
|
if (mNewDevice != null) {
|
||||||
@@ -284,6 +222,7 @@ public class UsbHostManager {
|
|||||||
mDevices.put(mNewDevice.getDeviceName(), mNewDevice);
|
mDevices.put(mNewDevice.getDeviceName(), mNewDevice);
|
||||||
Slog.d(TAG, "Added device " + mNewDevice);
|
Slog.d(TAG, "Added device " + mNewDevice);
|
||||||
getCurrentSettings().deviceAttached(mNewDevice);
|
getCurrentSettings().deviceAttached(mNewDevice);
|
||||||
|
mUsbAudioManager.deviceAdded(mNewDevice);
|
||||||
} else {
|
} else {
|
||||||
Slog.e(TAG, "mNewDevice is null in endUsbDeviceAdded");
|
Slog.e(TAG, "mNewDevice is null in endUsbDeviceAdded");
|
||||||
}
|
}
|
||||||
@@ -292,81 +231,14 @@ public class UsbHostManager {
|
|||||||
mNewInterfaces = null;
|
mNewInterfaces = null;
|
||||||
mNewEndpoints = null;
|
mNewEndpoints = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isAudioDevice) {
|
|
||||||
return; // bail
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO(pmclean) The "Parser" objects inspect files in "/proc/asound" which we presume is
|
|
||||||
// present, unlike the waitForAlsaFile() which waits on a file in /dev/snd. It is not
|
|
||||||
// clear why this works, or that it can be relied on going forward. Needs further
|
|
||||||
// research.
|
|
||||||
AlsaCardsParser cardsParser = new AlsaCardsParser();
|
|
||||||
cardsParser.scan();
|
|
||||||
// cardsParser.Log();
|
|
||||||
|
|
||||||
// But we need to parse the device to determine its capabilities.
|
|
||||||
AlsaDevicesParser devicesParser = new AlsaDevicesParser();
|
|
||||||
devicesParser.scan();
|
|
||||||
// devicesParser.Log();
|
|
||||||
|
|
||||||
// The protocol for now will be to select the last-connected (highest-numbered)
|
|
||||||
// Alsa Card.
|
|
||||||
mConnectedUsbCard = cardsParser.getNumCardRecords() - 1;
|
|
||||||
mConnectedUsbDeviceNum = 0;
|
|
||||||
|
|
||||||
mConnectedHasPlayback = devicesParser.hasPlaybackDevices(mConnectedUsbCard);
|
|
||||||
mConnectedHasCapture = devicesParser.hasCaptureDevices(mConnectedUsbCard);
|
|
||||||
mConnectedHasMIDI = devicesParser.hasMIDIDevices(mConnectedUsbCard);
|
|
||||||
|
|
||||||
// Playback device file needed/present?
|
|
||||||
if (mConnectedHasPlayback &&
|
|
||||||
!waitForAlsaFile(mConnectedUsbCard, mConnectedUsbDeviceNum, false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Capture device file needed/present?
|
|
||||||
if (mConnectedHasCapture &&
|
|
||||||
!waitForAlsaFile(mConnectedUsbCard, mConnectedUsbDeviceNum, true)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DEBUG_AUDIO) {
|
|
||||||
Slog.d(TAG,
|
|
||||||
"usb: hasPlayback:" + mConnectedHasPlayback + " hasCapture:" + mConnectedHasCapture);
|
|
||||||
}
|
|
||||||
|
|
||||||
sendDeviceNotification(mConnectedUsbCard,
|
|
||||||
mConnectedUsbDeviceNum,
|
|
||||||
true,
|
|
||||||
mConnectedHasPlayback,
|
|
||||||
mConnectedHasCapture,
|
|
||||||
mConnectedHasMIDI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called from JNI in monitorUsbHostBus to report USB device removal */
|
/* Called from JNI in monitorUsbHostBus to report USB device removal */
|
||||||
private void usbDeviceRemoved(String deviceName) {
|
private void usbDeviceRemoved(String deviceName) {
|
||||||
if (DEBUG_AUDIO) {
|
|
||||||
Slog.d(TAG, "usb:UsbHostManager.usbDeviceRemoved() nm:" + deviceName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mConnectedUsbCard != -1 && mConnectedUsbDeviceNum != -1) {
|
|
||||||
sendDeviceNotification(mConnectedUsbCard,
|
|
||||||
mConnectedUsbDeviceNum,
|
|
||||||
false,
|
|
||||||
mConnectedHasPlayback,
|
|
||||||
mConnectedHasCapture,
|
|
||||||
mConnectedHasMIDI);
|
|
||||||
mConnectedUsbCard = -1;
|
|
||||||
mConnectedUsbDeviceNum = -1;
|
|
||||||
mConnectedHasPlayback = false;
|
|
||||||
mConnectedHasCapture = false;
|
|
||||||
mConnectedHasMIDI = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
UsbDevice device = mDevices.remove(deviceName);
|
UsbDevice device = mDevices.remove(deviceName);
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
|
mUsbAudioManager.deviceRemoved(device);
|
||||||
getCurrentSettings().deviceDetached(device);
|
getCurrentSettings().deviceDetached(device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -418,6 +290,7 @@ public class UsbHostManager {
|
|||||||
pw.println(" " + name + ": " + mDevices.get(name));
|
pw.println(" " + name + ": " + mDevices.get(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mUsbAudioManager.dump(fd, pw);
|
||||||
}
|
}
|
||||||
|
|
||||||
private native void monitorUsbHostBus();
|
private native void monitorUsbHostBus();
|
||||||
|
|||||||
Reference in New Issue
Block a user