/*
 * 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 and
 * limitations under the License.
 */

package android.media.midi;

import android.annotation.RequiresFeature;
import android.annotation.SystemService;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.IBinder;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;

import java.util.concurrent.ConcurrentHashMap;

This class is the public application interface to the MIDI service.
/** * This class is the public application interface to the MIDI service. */
@SystemService(Context.MIDI_SERVICE) @RequiresFeature(PackageManager.FEATURE_MIDI) public final class MidiManager { private static final String TAG = "MidiManager";
Intent for starting BluetoothMidiService
@hide
/** * Intent for starting BluetoothMidiService * @hide */
public static final String BLUETOOTH_MIDI_SERVICE_INTENT = "android.media.midi.BluetoothMidiService";
BluetoothMidiService package name
@hide
/** * BluetoothMidiService package name * @hide */
public static final String BLUETOOTH_MIDI_SERVICE_PACKAGE = "com.android.bluetoothmidiservice";
BluetoothMidiService class name
@hide
/** * BluetoothMidiService class name * @hide */
public static final String BLUETOOTH_MIDI_SERVICE_CLASS = "com.android.bluetoothmidiservice.BluetoothMidiService"; private final IMidiManager mService; private final IBinder mToken = new Binder(); private ConcurrentHashMap<DeviceCallback,DeviceListener> mDeviceListeners = new ConcurrentHashMap<DeviceCallback,DeviceListener>(); // Binder stub for receiving device notifications from MidiService private class DeviceListener extends IMidiDeviceListener.Stub { private final DeviceCallback mCallback; private final Handler mHandler; public DeviceListener(DeviceCallback callback, Handler handler) { mCallback = callback; mHandler = handler; } @Override public void onDeviceAdded(MidiDeviceInfo device) { if (mHandler != null) { final MidiDeviceInfo deviceF = device; mHandler.post(new Runnable() { @Override public void run() { mCallback.onDeviceAdded(deviceF); } }); } else { mCallback.onDeviceAdded(device); } } @Override public void onDeviceRemoved(MidiDeviceInfo device) { if (mHandler != null) { final MidiDeviceInfo deviceF = device; mHandler.post(new Runnable() { @Override public void run() { mCallback.onDeviceRemoved(deviceF); } }); } else { mCallback.onDeviceRemoved(device); } } @Override public void onDeviceStatusChanged(MidiDeviceStatus status) { if (mHandler != null) { final MidiDeviceStatus statusF = status; mHandler.post(new Runnable() { @Override public void run() { mCallback.onDeviceStatusChanged(statusF); } }); } else { mCallback.onDeviceStatusChanged(status); } } }
Callback class used for clients to receive MIDI device added and removed notifications
/** * Callback class used for clients to receive MIDI device added and removed notifications */
public static class DeviceCallback {
Called to notify when a new MIDI device has been added
Params:
/** * Called to notify when a new MIDI device has been added * * @param device a {@link MidiDeviceInfo} for the newly added device */
public void onDeviceAdded(MidiDeviceInfo device) { }
Called to notify when a MIDI device has been removed
Params:
/** * Called to notify when a MIDI device has been removed * * @param device a {@link MidiDeviceInfo} for the removed device */
public void onDeviceRemoved(MidiDeviceInfo device) { }
Called to notify when the status of a MIDI device has changed
Params:
/** * Called to notify when the status of a MIDI device has changed * * @param status a {@link MidiDeviceStatus} for the changed device */
public void onDeviceStatusChanged(MidiDeviceStatus status) { } }
Listener class used for receiving the results of openDevice and openBluetoothDevice
/** * Listener class used for receiving the results of {@link #openDevice} and * {@link #openBluetoothDevice} */
public interface OnDeviceOpenedListener {
Called to respond to a openDevice request
Params:
  • device – a MidiDevice for opened device, or null if opening failed
/** * Called to respond to a {@link #openDevice} request * * @param device a {@link MidiDevice} for opened device, or null if opening failed */
abstract public void onDeviceOpened(MidiDevice device); }
@hide
/** * @hide */
public MidiManager(IMidiManager service) { mService = service; }
Registers a callback to receive notifications when MIDI devices are added and removed. The DeviceCallback.onDeviceStatusChanged method will be called immediately for any devices that have open ports. This allows applications to know which input ports are already in use and, therefore, unavailable. Applications should call getDevices before registering the callback to get a list of devices already added.
Params:
  • callback – a DeviceCallback for MIDI device notifications
  • handler – The Handler that will be used for delivering the device notifications. If handler is null, then the thread used for the callback is unspecified.
/** * Registers a callback to receive notifications when MIDI devices are added and removed. * * The {@link DeviceCallback#onDeviceStatusChanged} method will be called immediately * for any devices that have open ports. This allows applications to know which input * ports are already in use and, therefore, unavailable. * * Applications should call {@link #getDevices} before registering the callback * to get a list of devices already added. * * @param callback a {@link DeviceCallback} for MIDI device notifications * @param handler The {@link android.os.Handler Handler} that will be used for delivering the * device notifications. If handler is null, then the thread used for the * callback is unspecified. */
public void registerDeviceCallback(DeviceCallback callback, Handler handler) { DeviceListener deviceListener = new DeviceListener(callback, handler); try { mService.registerListener(mToken, deviceListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mDeviceListeners.put(callback, deviceListener); }
Unregisters a DeviceCallback.
Params:
/** * Unregisters a {@link DeviceCallback}. * * @param callback a {@link DeviceCallback} to unregister */
public void unregisterDeviceCallback(DeviceCallback callback) { DeviceListener deviceListener = mDeviceListeners.remove(callback); if (deviceListener != null) { try { mService.unregisterListener(mToken, deviceListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
Gets the list of all connected MIDI devices.
Returns:an array of all MIDI devices
/** * Gets the list of all connected MIDI devices. * * @return an array of all MIDI devices */
public MidiDeviceInfo[] getDevices() { try { return mService.getDevices(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private void sendOpenDeviceResponse(final MidiDevice device, final OnDeviceOpenedListener listener, Handler handler) { if (handler != null) { handler.post(new Runnable() { @Override public void run() { listener.onDeviceOpened(device); } }); } else { listener.onDeviceOpened(device); } }
Opens a MIDI device for reading and writing.
Params:
  • deviceInfo – a MidiDeviceInfo to open
  • listener – a OnDeviceOpenedListener to be called to receive the result
  • handler – the Handler that will be used for delivering the result. If handler is null, then the thread used for the listener is unspecified.
/** * 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 * 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 * listener is unspecified. */
public void openDevice(MidiDeviceInfo deviceInfo, OnDeviceOpenedListener listener, Handler handler) { final MidiDeviceInfo deviceInfoF = deviceInfo; final OnDeviceOpenedListener listenerF = listener; final Handler handlerF = handler; 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; } sendOpenDeviceResponse(device, listenerF, handlerF); } }; try { mService.openDevice(mToken, deviceInfo, callback); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
Opens a Bluetooth MIDI device for reading and writing.
Params:
  • bluetoothDevice – a BluetoothDevice to open as a MIDI device
  • listener – a OnDeviceOpenedListener to be called to receive the result
  • handler – the Handler that will be used for delivering the result. If handler is null, then the thread used for the listener is unspecified.
/** * Opens a Bluetooth MIDI device for reading and writing. * * @param bluetoothDevice a {@link android.bluetooth.BluetoothDevice} to open as a MIDI device * @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 * listener is unspecified. */
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(); device = new MidiDevice(deviceInfo, server, mService, mToken, deviceToken); } catch (RemoteException e) { Log.e(TAG, "remote exception in getDeviceInfo()"); } } sendOpenDeviceResponse(device, listenerF, handlerF); } }; try { mService.openBluetoothDevice(mToken, bluetoothDevice, callback); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }
@hide
/** @hide */
public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers, int numOutputPorts, String[] inputPortNames, String[] outputPortNames, Bundle properties, int type, MidiDeviceServer.Callback callback) { try { MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers, numOutputPorts, callback); MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(), inputPortReceivers.length, numOutputPorts, inputPortNames, outputPortNames, properties, type); if (deviceInfo == null) { Log.e(TAG, "registerVirtualDevice failed"); return null; } return server; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }