Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57baee2e authored by Mike Lockwood's avatar Mike Lockwood Committed by Android (Google) Code Review
Browse files

Merge "MidiManager: Add MIDI device status notifications"

parents 70bea137 5ff9e2a1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -17,10 +17,12 @@
package android.media.midi;

import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceStatus;

/** @hide */
oneway interface IMidiDeviceListener
{
    void onDeviceAdded(in MidiDeviceInfo device);
    void onDeviceRemoved(in MidiDeviceInfo device);
    void onDeviceStatusChanged(in MidiDeviceStatus status);
}
+8 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package android.media.midi;
import android.media.midi.IMidiDeviceListener;
import android.media.midi.IMidiDeviceServer;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceStatus;
import android.os.Bundle;
import android.os.IBinder;

@@ -44,4 +45,11 @@ interface IMidiManager
    // used by MidiDeviceService to access the MidiDeviceInfo that was created based on its
    // manifest's meta-data
    MidiDeviceInfo getServiceDeviceInfo(String packageName, String className);

    // used for client's to retrieve a device's MidiDeviceStatus
    MidiDeviceStatus getDeviceStatus(in MidiDeviceInfo deviceInfo);

    // used by MIDI devices to report their status
    // the token is used by MidiService for death notification
    void setDeviceStatus(IBinder token, in MidiDeviceStatus status);
}
+67 −5
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package android.media.midi;

import android.os.IBinder;
import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
@@ -61,7 +61,25 @@ public final class MidiDeviceServer implements Closeable {
    private final CopyOnWriteArrayList<MidiInputPort> mInputPorts
            = new CopyOnWriteArrayList<MidiInputPort>();


    // for reporting device status
    private final IBinder mDeviceStatusToken = new Binder();
    private final boolean[] mInputPortBusy;
    private final int[] mOutputPortOpenCount;

    private final CloseGuard mGuard = CloseGuard.get();
    private boolean mIsClosed;

    private final Callback mCallback;

    public interface Callback {
        /**
         * Called to notify when an our device status has changed
         * @param server the {@link MidiDeviceServer} that changed
         * @param status the {@link MidiDeviceStatus} for the device
         */
        public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status);
    }

    abstract private class PortClient implements IBinder.DeathRecipient {
        final IBinder mToken;
@@ -96,7 +114,10 @@ public final class MidiDeviceServer implements Closeable {
        void close() {
            mToken.unlinkToDeath(this, 0);
            synchronized (mInputPortOutputPorts) {
                mInputPortOutputPorts[mOutputPort.getPortNumber()] = null;
                int portNumber = mOutputPort.getPortNumber();
                mInputPortOutputPorts[portNumber] = null;
                mInputPortBusy[portNumber] = false;
                updateDeviceStatus();
            }
            IoUtils.closeQuietly(mOutputPort);
        }
@@ -113,7 +134,15 @@ public final class MidiDeviceServer implements Closeable {
        @Override
        void close() {
            mToken.unlinkToDeath(this, 0);
            mOutputPortDispatchers[mInputPort.getPortNumber()].getSender().disconnect(mInputPort);
            int portNumber = mInputPort.getPortNumber();
            MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber];
            synchronized (dispatcher) {
                dispatcher.getSender().disconnect(mInputPort);
                int openCount = dispatcher.getReceiverCount();
                mOutputPortOpenCount[portNumber] = openCount;
                updateDeviceStatus();
           }

            mInputPorts.remove(mInputPort);
            IoUtils.closeQuietly(mInputPort);
        }
@@ -153,6 +182,8 @@ public final class MidiDeviceServer implements Closeable {
                    synchronized (mPortClients) {
                        mPortClients.put(token, client);
                    }
                    mInputPortBusy[portNumber] = true;
                    updateDeviceStatus();
                    return pair[1];
                } catch (IOException e) {
                    Log.e(TAG, "unable to create ParcelFileDescriptors in openInputPort");
@@ -178,7 +209,14 @@ public final class MidiDeviceServer implements Closeable {
                ParcelFileDescriptor[] pair = ParcelFileDescriptor.createSocketPair(
                                                    OsConstants.SOCK_SEQPACKET);
                MidiInputPort inputPort = new MidiInputPort(pair[0], portNumber);
                mOutputPortDispatchers[portNumber].getSender().connect(inputPort);
                MidiDispatcher dispatcher = mOutputPortDispatchers[portNumber];
                synchronized (dispatcher) {
                    dispatcher.getSender().connect(inputPort);
                    int openCount = dispatcher.getReceiverCount();
                    mOutputPortOpenCount[portNumber] = openCount;
                    updateDeviceStatus();
                }

                mInputPorts.add(inputPort);
                OutputPortClient client = new OutputPortClient(token, inputPort);
                synchronized (mPortClients) {
@@ -215,11 +253,12 @@ public final class MidiDeviceServer implements Closeable {
    };

    /* package */ MidiDeviceServer(IMidiManager midiManager, MidiReceiver[] inputPortReceivers,
            int numOutputPorts) {
            int numOutputPorts, Callback callback) {
        mMidiManager = midiManager;
        mInputPortReceivers = inputPortReceivers;
        mInputPortCount = inputPortReceivers.length;
        mOutputPortCount = numOutputPorts;
        mCallback = callback;

        mInputPortOutputPorts = new MidiOutputPort[mInputPortCount];

@@ -228,6 +267,9 @@ public final class MidiDeviceServer implements Closeable {
            mOutputPortDispatchers[i] = new MidiDispatcher();
        }

        mInputPortBusy = new boolean[mInputPortCount];
        mOutputPortOpenCount = new int[numOutputPorts];

        mGuard.open("close");
    }

@@ -242,9 +284,28 @@ public final class MidiDeviceServer implements Closeable {
        mDeviceInfo = deviceInfo;
    }

    private void updateDeviceStatus() {
        // clear calling identity, since we may be in a Binder call from one of our clients
        long identityToken = Binder.clearCallingIdentity();

        MidiDeviceStatus status = new MidiDeviceStatus(mDeviceInfo, mInputPortBusy,
                mOutputPortOpenCount);
        if (mCallback != null) {
            mCallback.onDeviceStatusChanged(this, status);
        }
        try {
            mMidiManager.setDeviceStatus(mDeviceStatusToken, status);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in updateDeviceStatus");
        } finally {
            Binder.restoreCallingIdentity(identityToken);
        }
    }

    @Override
    public void close() throws IOException {
        synchronized (mGuard) {
            if (mIsClosed) return;
            mGuard.close();

            for (int i = 0; i < mInputPortCount; i++) {
@@ -263,6 +324,7 @@ public final class MidiDeviceServer implements Closeable {
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in unregisterDeviceServer");
            }
            mIsClosed = true;
        }
    }

+15 −1
Original line number Diff line number Diff line
@@ -57,6 +57,13 @@ abstract public class MidiDeviceService extends Service {
    private MidiDeviceServer mServer;
    private MidiDeviceInfo mDeviceInfo;

    private final MidiDeviceServer.Callback mCallback = new MidiDeviceServer.Callback() {
        @Override
        public void onDeviceStatusChanged(MidiDeviceServer server, MidiDeviceStatus status) {
            MidiDeviceService.this.onDeviceStatusChanged(status);
        }
    };

    @Override
    public void onCreate() {
        mMidiManager = IMidiManager.Stub.asInterface(
@@ -75,7 +82,7 @@ abstract public class MidiDeviceService extends Service {
                inputPortReceivers = new MidiReceiver[0];
            }
            server = new MidiDeviceServer(mMidiManager, inputPortReceivers,
                    deviceInfo.getOutputPortCount());
                    deviceInfo.getOutputPortCount(), mCallback);
            server.setDeviceInfo(deviceInfo);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in IMidiManager.getServiceDeviceInfo");
@@ -114,6 +121,13 @@ abstract public class MidiDeviceService extends Service {
        return mDeviceInfo;
    }

    /**
     * Called to notify when an our {@link MidiDeviceStatus} has changed
     * @param status the number of the port that was opened
     */
    public void onDeviceStatusChanged(MidiDeviceStatus status) {
    }

    @Override
    public IBinder onBind(Intent intent) {
        if (SERVICE_INTERFACE.equals(intent.getAction()) && mServer != null) {
+19 −0
Original line number Diff line number Diff line
/*
 * 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;

parcelable MidiDeviceStatus;
Loading