Merge "MidiManager: Add MIDI device status notifications"
This commit is contained in:
committed by
Android (Google) Code Review
commit
57baee2e12
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
media/java/android/media/midi/MidiDeviceStatus.aidl
Normal file
19
media/java/android/media/midi/MidiDeviceStatus.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 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;
|
||||
141
media/java/android/media/midi/MidiDeviceStatus.java
Normal file
141
media/java/android/media/midi/MidiDeviceStatus.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* This is an immutable class that describes the current status of a MIDI device's ports.
|
||||
*
|
||||
* CANDIDATE FOR PUBLIC API
|
||||
* @hide
|
||||
*/
|
||||
public final class MidiDeviceStatus implements Parcelable {
|
||||
|
||||
private static final String TAG = "MidiDeviceStatus";
|
||||
|
||||
private final MidiDeviceInfo mDeviceInfo;
|
||||
// true if input ports are busy
|
||||
private final boolean mInputPortBusy[];
|
||||
// open counts for output ports
|
||||
private final int mOutputPortOpenCount[];
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public MidiDeviceStatus(MidiDeviceInfo deviceInfo, boolean inputPortBusy[],
|
||||
int outputPortOpenCount[]) {
|
||||
// MidiDeviceInfo is immutable so we can share references
|
||||
mDeviceInfo = deviceInfo;
|
||||
|
||||
// make copies of the arrays
|
||||
mInputPortBusy = new boolean[inputPortBusy.length];
|
||||
System.arraycopy(inputPortBusy, 0, mInputPortBusy, 0, inputPortBusy.length);
|
||||
mOutputPortOpenCount = new int[outputPortOpenCount.length];
|
||||
System.arraycopy(outputPortOpenCount, 0, mOutputPortOpenCount, 0,
|
||||
outputPortOpenCount.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MidiDeviceStatus with false for all input port busy values
|
||||
* and zero for all output port open counts
|
||||
* @hide
|
||||
*/
|
||||
public MidiDeviceStatus(MidiDeviceInfo deviceInfo) {
|
||||
mDeviceInfo = deviceInfo;
|
||||
mInputPortBusy = new boolean[deviceInfo.getInputPortCount()];
|
||||
mOutputPortOpenCount = new int[deviceInfo.getOutputPortCount()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link MidiDeviceInfo} of the device.
|
||||
*
|
||||
* @return the device info
|
||||
*/
|
||||
public MidiDeviceInfo getDeviceInfo() {
|
||||
return mDeviceInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an input port is busy.
|
||||
*
|
||||
* @param input port's port number
|
||||
* @return input port busy status
|
||||
*/
|
||||
public boolean isInputPortBusy(int portNumber) {
|
||||
return mInputPortBusy[portNumber];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the open count for an output port.
|
||||
*
|
||||
* @param output port's port number
|
||||
* @return output port open count
|
||||
*/
|
||||
public int getOutputPortOpenCount(int portNumber) {
|
||||
return mOutputPortOpenCount[portNumber];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder(mDeviceInfo.toString());
|
||||
int inputPortCount = mDeviceInfo.getInputPortCount();
|
||||
int outputPortCount = mDeviceInfo.getOutputPortCount();
|
||||
builder.append(" mInputPortBusy=[");
|
||||
for (int i = 0; i < inputPortCount; i++) {
|
||||
builder.append(mInputPortBusy[i]);
|
||||
if (i < inputPortCount -1) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
builder.append("] mOutputPortOpenCount=[");
|
||||
for (int i = 0; i < outputPortCount; i++) {
|
||||
builder.append(mOutputPortOpenCount[i]);
|
||||
if (i < outputPortCount -1) {
|
||||
builder.append(",");
|
||||
}
|
||||
}
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<MidiDeviceStatus> CREATOR =
|
||||
new Parcelable.Creator<MidiDeviceStatus>() {
|
||||
public MidiDeviceStatus createFromParcel(Parcel in) {
|
||||
ClassLoader classLoader = MidiDeviceInfo.class.getClassLoader();
|
||||
MidiDeviceInfo deviceInfo = in.readParcelable(classLoader);
|
||||
boolean[] inputPortBusy = in.createBooleanArray();
|
||||
int[] outputPortOpenCount = in.createIntArray();
|
||||
return new MidiDeviceStatus(deviceInfo, inputPortBusy, outputPortOpenCount);
|
||||
}
|
||||
|
||||
public MidiDeviceStatus[] newArray(int size) {
|
||||
return new MidiDeviceStatus[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeParcelable(mDeviceInfo, flags);
|
||||
parcel.writeBooleanArray(mInputPortBusy);
|
||||
parcel.writeIntArray(mOutputPortOpenCount);
|
||||
}
|
||||
}
|
||||
@@ -55,11 +55,11 @@ public final class MidiDispatcher extends MidiReceiver {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether this dispatcher contains any receivers.
|
||||
* @return true if the receiver list is not empty
|
||||
* Returns the number of {@link MidiReceiver}s this dispatcher contains.
|
||||
* @return the number of receivers
|
||||
*/
|
||||
public boolean hasReceivers() {
|
||||
return mReceivers.size() > 0;
|
||||
public int getReceiverCount() {
|
||||
return mReceivers.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,6 +62,7 @@ public final class MidiManager {
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceAdded(MidiDeviceInfo device) {
|
||||
if (mHandler != null) {
|
||||
final MidiDeviceInfo deviceF = device;
|
||||
@@ -75,6 +76,7 @@ public final class MidiManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceRemoved(MidiDeviceInfo device) {
|
||||
if (mHandler != null) {
|
||||
final MidiDeviceInfo deviceF = device;
|
||||
@@ -87,25 +89,49 @@ public final class MidiManager {
|
||||
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
|
||||
*/
|
||||
abstract public static class DeviceCallback {
|
||||
public static class DeviceCallback {
|
||||
/**
|
||||
* Called to notify when a new MIDI device has been added
|
||||
*
|
||||
* @param device a {@link MidiDeviceInfo} for the newly added device
|
||||
*/
|
||||
abstract public void onDeviceAdded(MidiDeviceInfo device);
|
||||
public void onDeviceAdded(MidiDeviceInfo device) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to notify when a MIDI device has been removed
|
||||
*
|
||||
* @param device a {@link MidiDeviceInfo} for the removed device
|
||||
*/
|
||||
abstract public void onDeviceRemoved(MidiDeviceInfo device);
|
||||
public void onDeviceRemoved(MidiDeviceInfo device) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to notify when the status of a MIDI device has changed
|
||||
*
|
||||
* @param device a {@link MidiDeviceStatus} for the changed device
|
||||
*/
|
||||
public void onDeviceStatusChanged(MidiDeviceStatus status) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,10 +277,10 @@ public final class MidiManager {
|
||||
|
||||
/** @hide */
|
||||
public MidiDeviceServer createDeviceServer(MidiReceiver[] inputPortReceivers,
|
||||
int numOutputPorts, Bundle properties, int type) {
|
||||
int numOutputPorts, Bundle properties, int type, MidiDeviceServer.Callback callback) {
|
||||
try {
|
||||
MidiDeviceServer server = new MidiDeviceServer(mService, inputPortReceivers,
|
||||
numOutputPorts);
|
||||
numOutputPorts, callback);
|
||||
MidiDeviceInfo deviceInfo = mService.registerDeviceServer(server.getBinderInterface(),
|
||||
inputPortReceivers.length, numOutputPorts, properties, type);
|
||||
if (deviceInfo == null) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.media.midi.IMidiDeviceServer;
|
||||
import android.media.midi.IMidiManager;
|
||||
import android.media.midi.MidiDeviceInfo;
|
||||
import android.media.midi.MidiDeviceService;
|
||||
import android.media.midi.MidiDeviceStatus;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -147,6 +148,19 @@ public class MidiService extends IMidiManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
public void deviceStatusChanged(Device device, MidiDeviceStatus status) {
|
||||
// ignore private devices that our client cannot access
|
||||
if (!device.isUidAllowed(mUid)) return;
|
||||
|
||||
try {
|
||||
for (IMidiDeviceListener listener : mListeners) {
|
||||
listener.onDeviceStatusChanged(status);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "remote exception", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void binderDied() {
|
||||
removeClient(mToken);
|
||||
}
|
||||
@@ -187,6 +201,8 @@ public class MidiService extends IMidiManager.Stub {
|
||||
private final class Device implements IBinder.DeathRecipient {
|
||||
private final IMidiDeviceServer mServer;
|
||||
private final MidiDeviceInfo mDeviceInfo;
|
||||
private MidiDeviceStatus mDeviceStatus;
|
||||
private IBinder mDeviceStatusToken;
|
||||
// ServiceInfo for the device's MidiDeviceServer implementation (virtual devices only)
|
||||
private final ServiceInfo mServiceInfo;
|
||||
// UID of device implementation
|
||||
@@ -204,6 +220,33 @@ public class MidiService extends IMidiManager.Stub {
|
||||
return mDeviceInfo;
|
||||
}
|
||||
|
||||
public MidiDeviceStatus getDeviceStatus() {
|
||||
return mDeviceStatus;
|
||||
}
|
||||
|
||||
public void setDeviceStatus(IBinder token, MidiDeviceStatus status) {
|
||||
mDeviceStatus = status;
|
||||
|
||||
if (mDeviceStatusToken == null && token != null) {
|
||||
// register a death recipient so we can clear the status when the device dies
|
||||
try {
|
||||
token.linkToDeath(new IBinder.DeathRecipient() {
|
||||
@Override
|
||||
public void binderDied() {
|
||||
// reset to default status and clear the token
|
||||
mDeviceStatus = new MidiDeviceStatus(mDeviceInfo);
|
||||
mDeviceStatusToken = null;
|
||||
notifyDeviceStatusChanged(Device.this, mDeviceStatus);
|
||||
}
|
||||
}, 0);
|
||||
mDeviceStatusToken = token;
|
||||
} catch (RemoteException e) {
|
||||
// reset to default status
|
||||
mDeviceStatus = new MidiDeviceStatus(mDeviceInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IMidiDeviceServer getDeviceServer() {
|
||||
return mServer;
|
||||
}
|
||||
@@ -216,6 +259,10 @@ public class MidiService extends IMidiManager.Stub {
|
||||
return (mServiceInfo == null ? null : mServiceInfo.packageName);
|
||||
}
|
||||
|
||||
public int getUid() {
|
||||
return mUid;
|
||||
}
|
||||
|
||||
public boolean isUidAllowed(int uid) {
|
||||
return (!mDeviceInfo.isPrivate() || mUid == uid);
|
||||
}
|
||||
@@ -302,13 +349,14 @@ public class MidiService extends IMidiManager.Stub {
|
||||
@Override
|
||||
public MidiDeviceInfo registerDeviceServer(IMidiDeviceServer server, int numInputPorts,
|
||||
int numOutputPorts, Bundle properties, int type) {
|
||||
if (type != MidiDeviceInfo.TYPE_VIRTUAL && Binder.getCallingUid() != Process.SYSTEM_UID) {
|
||||
int uid = Binder.getCallingUid();
|
||||
if (type != MidiDeviceInfo.TYPE_VIRTUAL && uid != Process.SYSTEM_UID) {
|
||||
throw new SecurityException("only system can create non-virtual devices");
|
||||
}
|
||||
|
||||
synchronized (mDevicesByInfo) {
|
||||
return addDeviceLocked(type, numInputPorts, numOutputPorts, properties,
|
||||
server, null, false, -1);
|
||||
server, null, false, uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +385,39 @@ public class MidiService extends IMidiManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MidiDeviceStatus getDeviceStatus(MidiDeviceInfo deviceInfo) {
|
||||
Device device = mDevicesByInfo.get(deviceInfo);
|
||||
if (device == null) {
|
||||
throw new IllegalArgumentException("no such device for " + deviceInfo);
|
||||
}
|
||||
return device.getDeviceStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDeviceStatus(IBinder token, MidiDeviceStatus status) {
|
||||
MidiDeviceInfo deviceInfo = status.getDeviceInfo();
|
||||
Device device = mDevicesByInfo.get(deviceInfo);
|
||||
if (device == null) {
|
||||
// Just return quietly here if device no longer exists
|
||||
return;
|
||||
}
|
||||
if (Binder.getCallingUid() != device.getUid()) {
|
||||
throw new SecurityException("setDeviceStatus() caller UID " + Binder.getCallingUid()
|
||||
+ " does not match device's UID " + device.getUid());
|
||||
}
|
||||
device.setDeviceStatus(token, status);
|
||||
notifyDeviceStatusChanged(device, status);
|
||||
}
|
||||
|
||||
private void notifyDeviceStatusChanged(Device device, MidiDeviceStatus status) {
|
||||
synchronized (mClients) {
|
||||
for (Client c : mClients.values()) {
|
||||
c.deviceStatusChanged(device, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// synchronize on mDevicesByInfo
|
||||
private MidiDeviceInfo addDeviceLocked(int type, int numInputPorts, int numOutputPorts,
|
||||
Bundle properties, IMidiDeviceServer server, ServiceInfo serviceInfo,
|
||||
@@ -469,17 +550,15 @@ public class MidiService extends IMidiManager.Stub {
|
||||
continue;
|
||||
}
|
||||
|
||||
int uid = -1;
|
||||
if (isPrivate) {
|
||||
try {
|
||||
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
|
||||
serviceInfo.packageName, 0);
|
||||
uid = appInfo.uid;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "could not fetch ApplicationInfo for "
|
||||
+ serviceInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
int uid;
|
||||
try {
|
||||
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
|
||||
serviceInfo.packageName, 0);
|
||||
uid = appInfo.uid;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG, "could not fetch ApplicationInfo for "
|
||||
+ serviceInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
|
||||
synchronized (mDevicesByInfo) {
|
||||
|
||||
@@ -121,7 +121,7 @@ public final class UsbMidiDevice implements Closeable {
|
||||
|
||||
int outputCount = mOutputStreams.length;
|
||||
mServer = midiManager.createDeviceServer(mInputPortReceivers, outputCount,
|
||||
properties, MidiDeviceInfo.TYPE_USB);
|
||||
properties, MidiDeviceInfo.TYPE_USB, null);
|
||||
if (mServer == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user