diff options
author | Mike Lockwood <lockwood@google.com> | 2015-06-08 19:37:00 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-06-08 19:37:36 +0000 |
commit | 383ce580b1c9e706d1b06a23d81986f3b4ed83fb (patch) | |
tree | 9a672b4825f4f470d03526a3697ad6781ec77c0c /media | |
parent | e4bd7c98323b39a47682216bebf442de206a95dd (diff) | |
parent | e0a6ca64fac5bd4f10139321604031816e90adb4 (diff) | |
download | frameworks_base-383ce580b1c9e706d1b06a23d81986f3b4ed83fb.zip frameworks_base-383ce580b1c9e706d1b06a23d81986f3b4ed83fb.tar.gz frameworks_base-383ce580b1c9e706d1b06a23d81986f3b4ed83fb.tar.bz2 |
Merge "MidiManager: proxy all requests to open devices through MidiService" into mnc-dev
Diffstat (limited to 'media')
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 "android.permission.BIND_MIDI_DEVICE_SERVICE".</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> -<service android:name="<strong>MySynthDeviceService</strong>"> +<service android:name="<strong>MySynthDeviceService</strong>" + android:permission="android.permission.BIND_MIDI_DEVICE_SERVICE"> <intent-filter> <action android:name="android.media.midi.MidiDeviceService" /> </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(); |