summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorMike Lockwood <lockwood@google.com>2015-06-04 13:43:56 -0700
committerMike Lockwood <lockwood@google.com>2015-06-04 19:16:23 -0700
commite0a6ca64fac5bd4f10139321604031816e90adb4 (patch)
treeaf84954409f063e07e3845c5b8a8fe703106da7a /media
parentec7100d0114d50f12c4ad95eaeac61e93a6d5a96 (diff)
downloadframeworks_base-e0a6ca64fac5bd4f10139321604031816e90adb4.zip
frameworks_base-e0a6ca64fac5bd4f10139321604031816e90adb4.tar.gz
frameworks_base-e0a6ca64fac5bd4f10139321604031816e90adb4.tar.bz2
MidiManager: proxy all requests to open devices through MidiService
Previously when a MidiManager client opened a virtual or Bluetooth device, the client bound directly to the virtual device's MidiDeviceService or BluetoothMidiDevice's IMidiDeviceServer for the given BluetoothDevice. Only USB devices were opened in MidiService. Now opening any type of MIDI device is done via IMidiManager.openDevice() or IMidiManager.openBluetoothDevice(). MidiService tracks all connnections between clients and devices. Services that implement virtual devices must now require android.permission.BIND_MIDI_DEVICE_SERVICE so only MidiService can bind to these services. Bug: 21044677 Change-Id: I7172f7b1e0cbfe4a2a87dff376c32dc9b41aa563
Diffstat (limited to 'media')
-rw-r--r--media/java/android/media/midi/IMidiDeviceOpenCallback.aidl25
-rw-r--r--media/java/android/media/midi/IMidiDeviceServer.aidl1
-rw-r--r--media/java/android/media/midi/IMidiManager.aidl15
-rw-r--r--media/java/android/media/midi/MidiDevice.java27
-rw-r--r--media/java/android/media/midi/MidiDeviceServer.java16
-rw-r--r--media/java/android/media/midi/MidiDeviceService.java11
-rw-r--r--media/java/android/media/midi/MidiManager.java118
-rw-r--r--media/java/android/media/midi/package.html6
-rw-r--r--media/packages/BluetoothMidiService/AndroidManifest.xml3
-rw-r--r--media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java26
10 files changed, 140 insertions, 108 deletions
diff --git a/media/java/android/media/midi/IMidiDeviceOpenCallback.aidl b/media/java/android/media/midi/IMidiDeviceOpenCallback.aidl
new file mode 100644
index 0000000..6e3dbbf
--- /dev/null
+++ b/media/java/android/media/midi/IMidiDeviceOpenCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 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.media.midi;
+
+import android.media.midi.IMidiDeviceServer;
+
+/** @hide */
+oneway interface IMidiDeviceOpenCallback
+{
+ void onDeviceOpened(in IMidiDeviceServer server, IBinder token);
+}
diff --git a/media/java/android/media/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
index 96d12fd..e30796d 100644
--- a/media/java/android/media/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -25,6 +25,7 @@ interface IMidiDeviceServer
ParcelFileDescriptor openInputPort(IBinder token, int portNumber);
ParcelFileDescriptor openOutputPort(IBinder token, int portNumber);
void closePort(IBinder token);
+ void closeDevice();
// connects the input port pfd to the specified output port
void connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
diff --git a/media/java/android/media/midi/IMidiManager.aidl b/media/java/android/media/midi/IMidiManager.aidl
index fcd4aff..d3c8e0a 100644
--- a/media/java/android/media/midi/IMidiManager.aidl
+++ b/media/java/android/media/midi/IMidiManager.aidl
@@ -16,7 +16,10 @@
package android.media.midi;
+import android.bluetooth.BluetoothDevice;
import android.media.midi.IMidiDeviceListener;
+import android.media.midi.IMidiDeviceOpenCallback;
+import android.media.midi.IMidiDeviceServer;
import android.media.midi.IMidiDeviceServer;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceStatus;
@@ -29,11 +32,13 @@ interface IMidiManager
MidiDeviceInfo[] getDevices();
// for device creation & removal notifications
- void registerListener(IBinder token, in IMidiDeviceListener listener);
- void unregisterListener(IBinder token, in IMidiDeviceListener listener);
+ void registerListener(IBinder clientToken, in IMidiDeviceListener listener);
+ void unregisterListener(IBinder clientToken, in IMidiDeviceListener listener);
- // for opening built-in MIDI devices
- IMidiDeviceServer openDevice(IBinder token, in MidiDeviceInfo device);
+ void openDevice(IBinder clientToken, in MidiDeviceInfo device, in IMidiDeviceOpenCallback callback);
+ void openBluetoothDevice(IBinder clientToken, in BluetoothDevice bluetoothDevice,
+ in IMidiDeviceOpenCallback callback);
+ void closeDevice(IBinder clientToken, IBinder deviceToken);
// for registering built-in MIDI devices
MidiDeviceInfo registerDeviceServer(in IMidiDeviceServer server, int numInputPorts,
@@ -52,5 +57,5 @@ interface IMidiManager
// used by MIDI devices to report their status
// the token is used by MidiService for death notification
- void setDeviceStatus(IBinder token, in MidiDeviceStatus status);
+ void setDeviceStatus(in IMidiDeviceServer server, in MidiDeviceStatus status);
}
diff --git a/media/java/android/media/midi/MidiDevice.java b/media/java/android/media/midi/MidiDevice.java
index 6526adc..7998a92 100644
--- a/media/java/android/media/midi/MidiDevice.java
+++ b/media/java/android/media/midi/MidiDevice.java
@@ -16,8 +16,6 @@
package android.media.midi;
-import android.content.Context;
-import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
@@ -40,9 +38,9 @@ public final class MidiDevice implements Closeable {
private final MidiDeviceInfo mDeviceInfo;
private final IMidiDeviceServer mDeviceServer;
- private Context mContext;
- private ServiceConnection mServiceConnection;
-
+ private final IMidiManager mMidiManager;
+ private final IBinder mClientToken;
+ private final IBinder mDeviceToken;
private final CloseGuard mGuard = CloseGuard.get();
@@ -71,16 +69,13 @@ public final class MidiDevice implements Closeable {
}
}
- /* package */ MidiDevice(MidiDeviceInfo deviceInfo, IMidiDeviceServer server) {
- this(deviceInfo, server, null, null);
- }
-
/* package */ MidiDevice(MidiDeviceInfo deviceInfo, IMidiDeviceServer server,
- Context context, ServiceConnection serviceConnection) {
+ IMidiManager midiManager, IBinder clientToken, IBinder deviceToken) {
mDeviceInfo = deviceInfo;
mDeviceServer = server;
- mContext = context;
- mServiceConnection = serviceConnection;
+ mMidiManager = midiManager;
+ mClientToken = clientToken;
+ mDeviceToken = deviceToken;
mGuard.open("close");
}
@@ -170,10 +165,10 @@ public final class MidiDevice implements Closeable {
public void close() throws IOException {
synchronized (mGuard) {
mGuard.close();
- if (mContext != null && mServiceConnection != null) {
- mContext.unbindService(mServiceConnection);
- mContext = null;
- mServiceConnection = null;
+ try {
+ mMidiManager.closeDevice(mClientToken, mDeviceToken);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in closeDevice");
}
}
}
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index a316a44..1b56e1c 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -65,7 +65,6 @@ public final class MidiDeviceServer implements Closeable {
// for reporting device status
- private final IBinder mDeviceStatusToken = new Binder();
private final boolean[] mInputPortOpen;
private final int[] mOutputPortOpenCount;
@@ -81,6 +80,11 @@ public final class MidiDeviceServer implements Closeable {
* @param status the {@link MidiDeviceStatus} for the device
*/
public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status);
+
+ /**
+ * Called to notify when the device is closed
+ */
+ public void onClose();
}
abstract private class PortClient implements IBinder.DeathRecipient {
@@ -242,6 +246,14 @@ public final class MidiDeviceServer implements Closeable {
}
@Override
+ public void closeDevice() {
+ if (mCallback != null) {
+ mCallback.onClose();
+ }
+ IoUtils.closeQuietly(MidiDeviceServer.this);
+ }
+
+ @Override
public void connectPorts(IBinder token, ParcelFileDescriptor pfd,
int outputPortNumber) {
MidiInputPort inputPort = new MidiInputPort(pfd, outputPortNumber);
@@ -305,7 +317,7 @@ public final class MidiDeviceServer implements Closeable {
mCallback.onDeviceStatusChanged(this, status);
}
try {
- mMidiManager.setDeviceStatus(mDeviceStatusToken, status);
+ mMidiManager.setDeviceStatus(mServer, status);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in updateDeviceStatus");
} finally {
diff --git a/media/java/android/media/midi/MidiDeviceService.java b/media/java/android/media/midi/MidiDeviceService.java
index ce12a4f..d897ad2 100644
--- a/media/java/android/media/midi/MidiDeviceService.java
+++ b/media/java/android/media/midi/MidiDeviceService.java
@@ -59,6 +59,11 @@ abstract public class MidiDeviceService extends Service {
public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status) {
MidiDeviceService.this.onDeviceStatusChanged(status);
}
+
+ @Override
+ public void onClose() {
+ MidiDeviceService.this.onClose();
+ }
};
@Override
@@ -125,6 +130,12 @@ abstract public class MidiDeviceService extends Service {
public void onDeviceStatusChanged(MidiDeviceStatus status) {
}
+ /**
+ * Called to notify when our device has been closed by all its clients
+ */
+ public void onClose() {
+ }
+
@Override
public IBinder onBind(Intent intent) {
if (SERVICE_INTERFACE.equals(intent.getAction()) && mServer != null) {
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index d19cf36..0beb9a4 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -17,11 +17,6 @@
package android.media.midi;
import android.bluetooth.BluetoothDevice;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ServiceInfo;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
@@ -52,16 +47,17 @@ public final class MidiManager {
/**
* BluetoothMidiService package name
+ * @hide
*/
- private static final String BLUETOOTH_MIDI_SERVICE_PACKAGE = "com.android.bluetoothmidiservice";
+ public static final String BLUETOOTH_MIDI_SERVICE_PACKAGE = "com.android.bluetoothmidiservice";
/**
* BluetoothMidiService class name
+ * @hide
*/
- private static final String BLUETOOTH_MIDI_SERVICE_CLASS =
+ public static final String BLUETOOTH_MIDI_SERVICE_CLASS =
"com.android.bluetoothmidiservice.BluetoothMidiService";
- private final Context mContext;
private final IMidiManager mService;
private final IBinder mToken = new Binder();
@@ -166,8 +162,7 @@ public final class MidiManager {
/**
* @hide
*/
- public MidiManager(Context context, IMidiManager service) {
- mContext = context;
+ public MidiManager(IMidiManager service) {
mService = service;
}
@@ -237,7 +232,7 @@ public final class MidiManager {
* Opens a MIDI device for reading and writing.
*
* @param deviceInfo a {@link android.media.midi.MidiDeviceInfo} to open
- * @param listener a {@link MidiManager.OnDeviceOpenedListener} to be called
+ * @param listener a {@link MidiManager.OnDeviceOpenedListener} to be called
* to receive the result
* @param handler the {@link android.os.Handler Handler} that will be used for delivering
* the result. If handler is null, then the thread used for the
@@ -245,52 +240,28 @@ public final class MidiManager {
*/
public void openDevice(MidiDeviceInfo deviceInfo, OnDeviceOpenedListener listener,
Handler handler) {
- MidiDevice device = null;
- try {
- IMidiDeviceServer server = mService.openDevice(mToken, deviceInfo);
- if (server == null) {
- ServiceInfo serviceInfo = (ServiceInfo)deviceInfo.getProperties().getParcelable(
- MidiDeviceInfo.PROPERTY_SERVICE_INFO);
- if (serviceInfo == null) {
- Log.e(TAG, "no ServiceInfo for " + deviceInfo);
- } else {
- Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE);
- intent.setComponent(new ComponentName(serviceInfo.packageName,
- serviceInfo.name));
- final MidiDeviceInfo deviceInfoF = deviceInfo;
- final OnDeviceOpenedListener listenerF = listener;
- final Handler handlerF = handler;
- if (mContext.bindService(intent,
- new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder binder) {
- IMidiDeviceServer server =
- IMidiDeviceServer.Stub.asInterface(binder);
- MidiDevice device = new MidiDevice(deviceInfoF, server, mContext,
- this);
- sendOpenDeviceResponse(device, listenerF, handlerF);
- }
+ final MidiDeviceInfo deviceInfoF = deviceInfo;
+ final OnDeviceOpenedListener listenerF = listener;
+ final Handler handlerF = handler;
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // FIXME - anything to do here?
- }
- },
- Context.BIND_AUTO_CREATE))
- {
- // return immediately to avoid calling sendOpenDeviceResponse below
- return;
- } else {
- Log.e(TAG, "Unable to bind service: " + intent);
- }
+ IMidiDeviceOpenCallback callback = new IMidiDeviceOpenCallback.Stub() {
+ @Override
+ public void onDeviceOpened(IMidiDeviceServer server, IBinder deviceToken) {
+ MidiDevice device;
+ if (server != null) {
+ device = new MidiDevice(deviceInfoF, server, mService, mToken, deviceToken);
+ } else {
+ device = null;
}
- } else {
- device = new MidiDevice(deviceInfo, server);
+ sendOpenDeviceResponse(device, listenerF, handlerF);
}
+ };
+
+ try {
+ mService.openDevice(mToken, deviceInfo, callback);
} catch (RemoteException e) {
Log.e(TAG, "RemoteException in openDevice");
}
- sendOpenDeviceResponse(device, listener, handler);
}
/**
@@ -303,38 +274,33 @@ public final class MidiManager {
* the result. If handler is null, then the thread used for the
* listener is unspecified.
*/
- public void openBluetoothDevice(final BluetoothDevice bluetoothDevice,
- final OnDeviceOpenedListener listener, final Handler handler) {
- Intent intent = new Intent(BLUETOOTH_MIDI_SERVICE_INTENT);
- intent.setComponent(new ComponentName(BLUETOOTH_MIDI_SERVICE_PACKAGE,
- BLUETOOTH_MIDI_SERVICE_CLASS));
- intent.putExtra("device", bluetoothDevice);
- if (!mContext.bindService(intent,
- new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder binder) {
- IMidiDeviceServer server =
- IMidiDeviceServer.Stub.asInterface(binder);
+ public void openBluetoothDevice(BluetoothDevice bluetoothDevice,
+ OnDeviceOpenedListener listener, Handler handler) {
+ final OnDeviceOpenedListener listenerF = listener;
+ final Handler handlerF = handler;
+
+ IMidiDeviceOpenCallback callback = new IMidiDeviceOpenCallback.Stub() {
+ @Override
+ public void onDeviceOpened(IMidiDeviceServer server, IBinder deviceToken) {
+ MidiDevice device = null;
+ if (server != null) {
try {
// fetch MidiDeviceInfo from the server
MidiDeviceInfo deviceInfo = server.getDeviceInfo();
- MidiDevice device = new MidiDevice(deviceInfo, server, mContext, this);
- sendOpenDeviceResponse(device, listener, handler);
+ device = new MidiDevice(deviceInfo, server, mService, mToken, deviceToken);
+ sendOpenDeviceResponse(device, listenerF, handlerF);
} catch (RemoteException e) {
- Log.e(TAG, "remote exception in onServiceConnected");
- sendOpenDeviceResponse(null, listener, handler);
+ Log.e(TAG, "remote exception in getDeviceInfo()");
}
}
+ sendOpenDeviceResponse(device, listenerF, handlerF);
+ }
+ };
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // FIXME - anything to do here?
- }
- },
- Context.BIND_AUTO_CREATE))
- {
- Log.e(TAG, "Unable to bind service: " + intent);
- sendOpenDeviceResponse(null, listener, handler);
+ try {
+ mService.openBluetoothDevice(mToken, bluetoothDevice, callback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in openDevice");
}
}
diff --git a/media/java/android/media/midi/package.html b/media/java/android/media/midi/package.html
index bd589a9..8b2bd16 100644
--- a/media/java/android/media/midi/package.html
+++ b/media/java/android/media/midi/package.html
@@ -241,7 +241,8 @@ messages.</p>
<p>An app can provide a MIDI Service that can be used by other apps. For example,
-an app can provide a custom synthesizer that other apps can send messages to. </p>
+an app can provide a custom synthesizer that other apps can send messages to.
+The service must be guarded with permission &quot;android.permission.BIND_MIDI_DEVICE_SERVICE&quot;.</p>
<h2 id=manifest_files>Manifest Files</h2>
@@ -250,7 +251,8 @@ an app can provide a custom synthesizer that other apps can send messages to. </
AndroidManifest.xml file.</p>
<pre class=prettyprint>
-&lt;service android:name="<strong>MySynthDeviceService</strong>">
+&lt;service android:name="<strong>MySynthDeviceService</strong>"
+ android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE">
&lt;intent-filter>
&lt;action android:name="android.media.midi.MidiDeviceService" />
&lt;/intent-filter>
diff --git a/media/packages/BluetoothMidiService/AndroidManifest.xml b/media/packages/BluetoothMidiService/AndroidManifest.xml
index 15aa581..b0b389a 100644
--- a/media/packages/BluetoothMidiService/AndroidManifest.xml
+++ b/media/packages/BluetoothMidiService/AndroidManifest.xml
@@ -8,7 +8,8 @@
<application
android:label="@string/app_name">
- <service android:name="BluetoothMidiService">
+ <service android:name="BluetoothMidiService"
+ android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE">
<intent-filter>
<action android:name="android.media.midi.BluetoothMidiService" />
</intent-filter>
diff --git a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
index 60c6570..e6d59e4 100644
--- a/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
+++ b/media/packages/BluetoothMidiService/src/com/android/bluetoothmidiservice/BluetoothMidiDevice.java
@@ -24,10 +24,11 @@ import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
-import android.media.midi.MidiReceiver;
-import android.media.midi.MidiManager;
-import android.media.midi.MidiDeviceServer;
import android.media.midi.MidiDeviceInfo;
+import android.media.midi.MidiDeviceServer;
+import android.media.midi.MidiDeviceStatus;
+import android.media.midi.MidiManager;
+import android.media.midi.MidiReceiver;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
@@ -81,6 +82,18 @@ public final class BluetoothMidiDevice {
private final BluetoothPacketDecoder mPacketDecoder
= new BluetoothPacketDecoder(MAX_PACKET_SIZE);
+ private final MidiDeviceServer.Callback mDeviceServerCallback
+ = new MidiDeviceServer.Callback() {
+ @Override
+ public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status) {
+ }
+
+ @Override
+ public void onClose() {
+ close();
+ }
+ };
+
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status,
@@ -213,7 +226,7 @@ public final class BluetoothMidiDevice {
inputPortReceivers[0] = mEventScheduler.getReceiver();
mDeviceServer = mMidiManager.createDeviceServer(inputPortReceivers, 1,
- null, null, properties, MidiDeviceInfo.TYPE_BLUETOOTH, null);
+ null, null, properties, MidiDeviceInfo.TYPE_BLUETOOTH, mDeviceServerCallback);
mOutputReceiver = mDeviceServer.getOutputPortReceivers()[0];
@@ -248,11 +261,12 @@ public final class BluetoothMidiDevice {
private void close() {
synchronized (mBluetoothDevice) {
- mEventScheduler.close();
+ mEventScheduler.close();
+ mService.deviceClosed(mBluetoothDevice);
+
if (mDeviceServer != null) {
IoUtils.closeQuietly(mDeviceServer);
mDeviceServer = null;
- mService.deviceClosed(mBluetoothDevice);
}
if (mBluetoothGatt != null) {
mBluetoothGatt.close();