summaryrefslogtreecommitdiff
path: root/media/native
diff options
context:
space:
mode:
author Paul McLean <pmclean@google.com> 2017-03-05 08:12:18 -0700
committer Paul McLean <pmclean@google.com> 2017-03-10 15:54:16 -0700
commit71f672b98a0c31001ca28de86d9ac99fef0812b1 (patch)
treea4ca0e175f221a40870c7886f8a3033f5425cb12 /media/native
parentf7683a6f173cca09b33e7eaeb51f3b867f68deaa (diff)
Switching Native MIDI API to an "opaque pointers" model.
Test: manual Change-Id: Ic181008427e6e81106d867cc3a70deef8c591841
Diffstat (limited to 'media/native')
-rw-r--r--media/native/midi/Android.mk4
-rw-r--r--media/native/midi/MidiDeviceRegistry.cpp106
-rw-r--r--media/native/midi/MidiDeviceRegistry.h104
-rw-r--r--media/native/midi/MidiPortRegistry.cpp200
-rw-r--r--media/native/midi/MidiPortRegistry.h192
-rw-r--r--media/native/midi/midi.cpp225
-rw-r--r--media/native/midi/midi.h58
-rw-r--r--media/native/midi/midi_internal.h27
8 files changed, 138 insertions, 778 deletions
diff --git a/media/native/midi/Android.mk b/media/native/midi/Android.mk
index b91c430e2bca..dbc5eed004db 100644
--- a/media/native/midi/Android.mk
+++ b/media/native/midi/Android.mk
@@ -4,9 +4,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
../../java/android/media/midi/IMidiDeviceServer.aidl \
- midi.cpp \
- MidiDeviceRegistry.cpp \
- MidiPortRegistry.cpp
+ midi.cpp
LOCAL_AIDL_INCLUDES := \
$(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
diff --git a/media/native/midi/MidiDeviceRegistry.cpp b/media/native/midi/MidiDeviceRegistry.cpp
deleted file mode 100644
index 8854a08a0a45..000000000000
--- a/media/native/midi/MidiDeviceRegistry.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#include "MidiDeviceRegistry.h"
-
-namespace android {
-
-ANDROID_SINGLETON_STATIC_INSTANCE(media::midi::MidiDeviceRegistry);
-
-namespace media {
-namespace midi {
-
-MidiDeviceRegistry::MidiDeviceRegistry() : mNextDeviceToken(1) {
-}
-
-status_t MidiDeviceRegistry::addDevice(sp<BpMidiDeviceServer> server, int32_t deviceId) {
- if (server.get() == nullptr) {
- return -EINVAL;
- }
-
- std::lock_guard<std::mutex> guard(mMapsLock);
- mServers[deviceId] = server;
- return OK;
-}
-
-status_t MidiDeviceRegistry::removeDevice(int32_t deviceId) {
- std::lock_guard<std::mutex> guard(mMapsLock);
- mServers.erase(deviceId);
- const auto& iter = mUidToToken.find(deviceId);
- if (iter != mUidToToken.end()) {
- mTokenToUid.erase(iter->second);
- mUidToToken.erase(iter);
- }
- return OK;
-}
-
-//NOTE: This creates an entry if not found, or returns an existing one.
-status_t MidiDeviceRegistry::obtainDeviceToken(int32_t deviceId, AMIDI_Device *deviceTokenPtr) {
- std::lock_guard<std::mutex> guard(mMapsLock);
- const auto& serversIter = mServers.find(deviceId);
- if (serversIter == mServers.end()) {
- // Not found.
- return -EINVAL;
- }
-
- const auto& iter = mUidToToken.find(deviceId);
- if (iter != mUidToToken.end()) {
- *deviceTokenPtr = iter->second;
- } else {
- *deviceTokenPtr = mNextDeviceToken++;
- mTokenToUid[*deviceTokenPtr] = deviceId;
- mUidToToken[deviceId] = *deviceTokenPtr;
- }
- return OK;
-}
-
-status_t MidiDeviceRegistry::releaseDevice(AMIDI_Device deviceToken) {
- std::lock_guard<std::mutex> guard(mMapsLock);
- const auto& iter = mTokenToUid.find(deviceToken);
- if (iter == mTokenToUid.end()) {
- // Not found
- return -EINVAL;
- }
-
- mServers.erase(iter->second);
- mUidToToken.erase(iter->second);
- mTokenToUid.erase(iter);
- return OK;
-}
-
-status_t MidiDeviceRegistry::getDeviceByToken(
- AMIDI_Device deviceToken, sp<BpMidiDeviceServer> *devicePtr) {
- std::lock_guard<std::mutex> guard(mMapsLock);
- int32_t id = -1;
- {
- const auto& iter = mTokenToUid.find(deviceToken);
- if (iter == mTokenToUid.end()) {
- return -EINVAL;
- }
- id = iter->second;
- }
- const auto& iter = mServers.find(id);
- if (iter == mServers.end()) {
- return -EINVAL;
- }
-
- *devicePtr = iter->second;
- return OK;
-}
-
-} // namespace midi
-} // namespace media
-} // namespace android
diff --git a/media/native/midi/MidiDeviceRegistry.h b/media/native/midi/MidiDeviceRegistry.h
deleted file mode 100644
index 93be7338385b..000000000000
--- a/media/native/midi/MidiDeviceRegistry.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef ANDROID_MEDIA_MIDI_DEVICE_REGISTRY_H_
-#define ANDROID_MEDIA_MIDI_DEVICE_REGISTRY_H_
-
-#include <map>
-#include <mutex>
-
-#include <binder/IBinder.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
-#include "android/media/midi/BpMidiDeviceServer.h"
-#include "midi.h"
-
-namespace android {
-namespace media {
-namespace midi {
-
-/*
- * Maintains a thread-safe, (singleton) list of MIDI devices with associated Binder interfaces,
- * which are exposed to the Native API via (Java) MidiDevice.mirrorToNative() &
- * MidiDevice.removeFromNative().
- * (Called via MidiDeviceManager::addDevice() MidiManager::removeDevice()).
- */
-class MidiDeviceRegistry : public Singleton<MidiDeviceRegistry> {
- public:
- /* Add a MIDI Device to the registry.
- *
- * server The Binder interface to the MIDI device server.
- * deviceUId The unique ID of the device obtained from
- * the Java API via MidiDeviceInfo.getId().
- */
- status_t addDevice(sp<BpMidiDeviceServer> server, int32_t deviceId);
-
- /* Remove the device (and associated server) from the Device registry.
- *
- * deviceUid The ID of the device which was used in the call to addDevice().
- */
- status_t removeDevice(int32_t deviceId);
-
- /* Gets a device token associated with the device ID. This is used by the
- * native API to identify/access the device.
- * Multiple calls without releasing the token will return the same value.
- *
- * deviceUid The ID of the device.
- * deviceTokenPtr Receives the device (native) token associated with the device ID.
- * returns: OK on success, error code otherwise.
- */
- status_t obtainDeviceToken(int32_t deviceId, AMIDI_Device *deviceTokenPtr);
-
- /*
- * Releases the native API device token associated with a MIDI device.
- *
- * deviceToken The device (native) token associated with the device ID.
- */
- status_t releaseDevice(AMIDI_Device deviceToken);
-
- /*
- * Gets the Device server binder interface associated with the device token.
- *
- * deviceToken The device (native) token associated with the device ID.
- */
- status_t getDeviceByToken(AMIDI_Device deviceToken, sp<BpMidiDeviceServer> *devicePtr);
-
- private:
- friend class Singleton<MidiDeviceRegistry>;
- MidiDeviceRegistry();
-
- // Access Mutex
- std::mutex mMapsLock;
-
- // maps device IDs to servers
- std::map<int32_t, sp<BpMidiDeviceServer>> mServers;
-
- // maps device tokens to device ID
- std::map<AMIDI_Device, int32_t> mTokenToUid;
-
- // maps device IDs to device tokens
- std::map<int32_t, AMIDI_Device> mUidToToken;
-
- // Value of next device token to dole out.
- AMIDI_Device mNextDeviceToken;
-};
-
-} // namespace midi
-} // namespace media
-} // namespace android
-
-#endif // ANDROID_MEDIA_MIDI_DEVICE_REGISTRY_H_
diff --git a/media/native/midi/MidiPortRegistry.cpp b/media/native/midi/MidiPortRegistry.cpp
deleted file mode 100644
index fa70af8d0947..000000000000
--- a/media/native/midi/MidiPortRegistry.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#include "MidiPortRegistry.h"
-
-namespace android {
-
-ANDROID_SINGLETON_STATIC_INSTANCE(media::midi::MidiPortRegistry);
-
-namespace media {
-namespace midi {
-
-//TODO Note that these 2 are identical
-struct MidiPortRegistry::OutputPort {
- AMIDI_Device device;
- sp<IBinder> binderToken;
- base::unique_fd ufd;
-};
-
-struct MidiPortRegistry::InputPort {
- AMIDI_Device device;
- sp<IBinder> binderToken;
- base::unique_fd ufd;
-};
-
-MidiPortRegistry::MidiPortRegistry() : mNextOutputPortToken(0), mNextInputPortToken(0) {
-}
-
-status_t MidiPortRegistry::addOutputPort(
- AMIDI_Device device,
- sp<IBinder> portToken,
- base::unique_fd &&ufd,
- AMIDI_OutputPort *portPtr) {
- *portPtr = mNextOutputPortToken++;
-
- OutputPortEntry* portEntry = new OutputPortEntry;
- portEntry->port = new OutputPort;
- portEntry->state = MIDI_OUTPUT_PORT_STATE_OPEN_IDLE;
- portEntry->port = new OutputPort;
- portEntry->port->device = device;
- portEntry->port->binderToken = portToken;
- portEntry->port->ufd = std::move(ufd);
-
- mOutputPortMap[*portPtr] = portEntry;
-
- return OK;
-}
-
-status_t MidiPortRegistry::removeOutputPort(
- AMIDI_OutputPort port,
- AMIDI_Device *devicePtr,
- sp<IBinder> *portTokenPtr) {
- OutputPortMap::iterator itr = mOutputPortMap.find(port);
- if (itr == mOutputPortMap.end()) {
- return -EINVAL;
- }
-
- OutputPortEntry *entry = mOutputPortMap[port];
- int portState = MIDI_OUTPUT_PORT_STATE_OPEN_IDLE;
- while (!entry->state.compare_exchange_weak(portState, MIDI_OUTPUT_PORT_STATE_CLOSED)) {
- if (portState == MIDI_OUTPUT_PORT_STATE_CLOSED) {
- return -EINVAL; // Already closed
- }
- }
- *devicePtr = entry->port->device;
- *portTokenPtr = entry->port->binderToken;
- delete entry->port;
- entry->port = nullptr;
-
- mOutputPortMap.erase(itr);
-
- return OK;
-}
-
-status_t MidiPortRegistry::getOutputPortFdAndLock(
- AMIDI_OutputPort port, base::unique_fd **ufdPtr) {
- if (mOutputPortMap.find(port) == mOutputPortMap.end()) {
- return -EINVAL;
- }
-
- OutputPortEntry *entry = mOutputPortMap[port];
- int portState = MIDI_OUTPUT_PORT_STATE_OPEN_IDLE;
- if (!entry->state.compare_exchange_strong(portState, MIDI_OUTPUT_PORT_STATE_OPEN_ACTIVE)) {
- // The port has been closed.
- return -EPIPE;
- }
- *ufdPtr = &entry->port->ufd;
-
- return OK;
-}
-
-status_t MidiPortRegistry::unlockOutputPort(AMIDI_OutputPort port) {
- if (mOutputPortMap.find(port) == mOutputPortMap.end()) {
- return -EINVAL;
- }
-
- OutputPortEntry *entry = mOutputPortMap[port];
- entry->state.store(MIDI_OUTPUT_PORT_STATE_OPEN_IDLE);
- return OK;
-}
-
-status_t MidiPortRegistry::addInputPort(
- AMIDI_Device device,
- sp<IBinder> portToken,
- base::unique_fd &&ufd,
- AMIDI_InputPort *portPtr) {
- *portPtr = mNextInputPortToken++;
-
- InputPortEntry *entry = new InputPortEntry;
-
- entry->state = MIDI_INPUT_PORT_STATE_OPEN_IDLE;
- entry->port = new InputPort;
- entry->port->device = device;
- entry->port->binderToken = portToken;
- entry->port->ufd = std::move(ufd);
-
- mInputPortMap[*portPtr] = entry;
-
- return OK;
-}
-
-status_t MidiPortRegistry::removeInputPort(
- AMIDI_InputPort port,
- AMIDI_Device *devicePtr,
- sp<IBinder> *portTokenPtr) {
- InputPortMap::iterator itr = mInputPortMap.find(port);
- if (itr == mInputPortMap.end()) {
- return -EINVAL;
- }
-
- InputPortEntry *entry = mInputPortMap[port];
- int portState = MIDI_INPUT_PORT_STATE_OPEN_IDLE;
- while (!entry->state.compare_exchange_weak(portState, MIDI_INPUT_PORT_STATE_CLOSED)) {
- if (portState == MIDI_INPUT_PORT_STATE_CLOSED) return -EINVAL; // Already closed
- }
-
- *devicePtr = entry->port->device;
- *portTokenPtr = entry->port->binderToken;
- delete entry->port;
- entry->port = nullptr;
-
- mInputPortMap.erase(itr);
-
- return OK;
-}
-
-status_t MidiPortRegistry::getInputPortFd(AMIDI_InputPort port, base::unique_fd **ufdPtr) {
- if (mInputPortMap.find(port) == mInputPortMap.end()) {
- return -EINVAL;
- }
-
- InputPortEntry *entry = mInputPortMap[port];
-
- *ufdPtr = &entry->port->ufd;
-
- return OK;
-}
-
-status_t MidiPortRegistry::getInputPortFdAndLock(AMIDI_InputPort port, base::unique_fd **ufdPtr) {
- if (mInputPortMap.find(port) == mInputPortMap.end()) {
- return -EINVAL;
- }
-
- InputPortEntry *entry = mInputPortMap[port];
-
- int portState = MIDI_INPUT_PORT_STATE_OPEN_IDLE;
- if (!entry->state.compare_exchange_strong(portState, MIDI_INPUT_PORT_STATE_OPEN_ACTIVE)) {
- // The port has been closed.
- return -EPIPE;
- }
- *ufdPtr = &entry->port->ufd;
- return OK;
-}
-
-status_t MidiPortRegistry::MidiPortRegistry::unlockInputPort(AMIDI_InputPort port) {
- if (mInputPortMap.find(port) == mInputPortMap.end()) {
- return -EINVAL;
- }
-
- InputPortEntry *entry = mInputPortMap[port];
- entry->state.store(MIDI_INPUT_PORT_STATE_OPEN_IDLE);
- return OK;
-}
-
-} // namespace midi
-} // namespace media
-} // namespace android
diff --git a/media/native/midi/MidiPortRegistry.h b/media/native/midi/MidiPortRegistry.h
deleted file mode 100644
index f1ffb78e98ab..000000000000
--- a/media/native/midi/MidiPortRegistry.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2017 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.
- */
-
-#ifndef ANDROID_MEDIA_MIDI_PORT_REGISTRY_H_
-#define ANDROID_MEDIA_MIDI_PORT_REGISTRY_H_
-
-#include <atomic>
-#include <map>
-
-#include <android-base/unique_fd.h>
-#include <binder/IBinder.h>
-#include <utils/Errors.h>
-#include <utils/Singleton.h>
-
-#include "midi.h"
-
-namespace android {
-namespace media {
-namespace midi {
-
-/*
- * Maintains lists of all active input and output MIDI ports and controls access to them. Provides
- * exclusive access to specific MIDI ports.
- */
-class MidiPortRegistry : public Singleton<MidiPortRegistry> {
- public:
- /*
- * Creates an output port entry and associates it with the specified MIDI device.
- * Called by AMIDI_openOutputPort();
- *
- * device The native API device ID.
- * portToken The port token (returned from the device server).
- * udf File descriptor for the data port associated with the MIDI output port.
- * portPtr Receives the native API port ID of the port being opened.
- */
- status_t addOutputPort(
- AMIDI_Device device,
- sp<IBinder> portToken,
- base::unique_fd &&ufd,
- AMIDI_OutputPort *portPtr);
-
- /*
- * Removes for the output port list a previously added output port.
- * Called by AMIDI_closeOutputPort();
- *
- * port The native API port ID of the port being closed.
- * devicePtr Receives the native API device ID associated with the port.
- * portTokenPtr Receives the binder token associated with the port.
- */
- status_t removeOutputPort(
- AMIDI_OutputPort port,
- AMIDI_Device *devicePtr,
- sp<IBinder> *portTokenPtr);
-
- /*
- * Creates an input port entry and associates it with the specified MIDI device.
- * Called by AMIDI_openInputPort();
- *
- * device The native API device ID.
- * portToken The port token (returned from the device server).
- * udf File descriptor for the data port associated with the MIDI input port.
- * portPtr Receives the native API port ID of the port being opened.
- */
- status_t addInputPort(
- AMIDI_Device device,
- sp<IBinder> portToken,
- base::unique_fd &&ufd,
- AMIDI_InputPort *portPtr);
-
- /*
- * Removes for the input port list a previously added input port.
- * Called by AMIDI_closeINputPort();
- *
- * port The native API port ID of the port being closed.
- * devicePtr Receives the native API device ID associated with the port.
- * portTokenPtr Receives the binder token associated with the port.
- */
- status_t removeInputPort(
- AMIDI_InputPort port,
- AMIDI_Device *devicePtr,
- sp<IBinder> *portTokenPtr);
-
- /*
- * Retrieves an exclusive-access file descriptor for an output port.
- * Called from AMIDI_receive().
- *
- * port The native API id of the output port.
- * ufdPtr Receives the exclusive-access file descriptor for the output port.
- */
- status_t getOutputPortFdAndLock(AMIDI_OutputPort port, base::unique_fd **ufdPtr);
-
- /*
- * Releases exclusive-access to the port and invalidates the previously received file
- * descriptor.
- * Called from AMIDI_receive().
- *
- * port The native API id of the output port.
- */
- status_t unlockOutputPort(AMIDI_OutputPort port);
-
- /*
- * Retrieves an exclusive-access file descriptor for an input port.
- * (Not being used as (perhaps) AMIDI_sendWithTimestamp() doesn't need exclusive access
- * to the port).
- *
- * port The native API id of the input port.
- * ufdPtr Receives the exclusive-access file descriptor for the input port.
- */
- status_t getInputPortFdAndLock(AMIDI_InputPort port, base::unique_fd **ufdPtr);
-
- /*
- * Releases exclusive-access to the port and invalidates the previously received file
- * descriptor.
- * (Not used. See above).
- *
- * port The native API id of the input port.
- */
- status_t unlockInputPort(AMIDI_InputPort port);
-
- /*
- * Retrieves an unlocked (multi-access) file descriptor for an input port.
- * Used by AMIDI_sendWith(), AMIDI_sendWithTimestamp & AMIDI_flush.
- *
- * port The native API id of the input port.
- * ufdPtr Receives the multi-access file descriptor for the input port.
- */
- status_t getInputPortFd(AMIDI_InputPort port, base::unique_fd **ufdPtr);
-
- private:
- friend class Singleton<MidiPortRegistry>;
- MidiPortRegistry();
-
- /*
- * Output (data receiving) ports.
- */
- struct OutputPort;
- enum {
- MIDI_OUTPUT_PORT_STATE_CLOSED = 0,
- MIDI_OUTPUT_PORT_STATE_OPEN_IDLE,
- MIDI_OUTPUT_PORT_STATE_OPEN_ACTIVE
- };
-
- struct OutputPortEntry {
- std::atomic_int state;
- OutputPort *port;
- };
-
- typedef std::map<AMIDI_OutputPort, OutputPortEntry*> OutputPortMap;
- // Access is synchronized per record via 'state' field.
- std::atomic<AMIDI_OutputPort> mNextOutputPortToken;
- OutputPortMap mOutputPortMap;
-
- /*
- * Input (data sending) ports.
- */
- struct InputPort;
- enum {
- MIDI_INPUT_PORT_STATE_CLOSED = 0,
- MIDI_INPUT_PORT_STATE_OPEN_IDLE,
- MIDI_INPUT_PORT_STATE_OPEN_ACTIVE
- };
-
- struct InputPortEntry {
- std::atomic_int state;
- InputPort *port;
- };
-
- typedef std::map<AMIDI_OutputPort, InputPortEntry*> InputPortMap;
- // Access is synchronized per record via 'state' field.
- std::atomic<AMIDI_InputPort> mNextInputPortToken;
- InputPortMap mInputPortMap;
-
-};
-
-} // namespace midi
-} // namespace media
-} // namespace android
-
-#endif // ANDROID_MEDIA_MIDI_PORT_REGISTRY_H_
diff --git a/media/native/midi/midi.cpp b/media/native/midi/midi.cpp
index 1bf0bd080e94..17b92da3325e 100644
--- a/media/native/midi/midi.cpp
+++ b/media/native/midi/midi.cpp
@@ -25,10 +25,9 @@
#include "android/media/midi/BpMidiDeviceServer.h"
#include "media/MidiDeviceInfo.h"
-#include "MidiDeviceRegistry.h"
-#include "MidiPortRegistry.h"
#include "midi.h"
+#include "midi_internal.h"
using android::IBinder;
using android::BBinder;
@@ -37,13 +36,28 @@ using android::sp;
using android::status_t;
using android::base::unique_fd;
using android::binder::Status;
-using android::media::midi::BpMidiDeviceServer;
using android::media::midi::MidiDeviceInfo;
-using android::media::midi::MidiDeviceRegistry;
-using android::media::midi::MidiPortRegistry;
+
+struct AMIDI_Port {
+ std::atomic_int state;
+ AMIDI_Device *device;
+ sp<IBinder> binderToken;
+ unique_fd ufd;
+};
#define SIZE_MIDIRECEIVEBUFFER AMIDI_BUFFER_SIZE
+enum {
+ MIDI_PORT_STATE_CLOSED = 0,
+ MIDI_PORT_STATE_OPEN_IDLE,
+ MIDI_PORT_STATE_OPEN_ACTIVE
+};
+
+enum {
+ PORTTYPE_OUTPUT = 0,
+ PORTTYPE_INPUT = 1
+};
+
/* TRANSFER PACKET FORMAT (as defined in MidiPortImpl.java)
*
* Transfer packet format is as follows (see MidiOutputPort.mThread.run() to see decomposition):
@@ -63,20 +77,12 @@ using android::media::midi::MidiPortRegistry;
* So 'read()' always returns a whole message.
*/
-status_t AMIDI_getDeviceById(int32_t id, AMIDI_Device *devicePtr) {
- return MidiDeviceRegistry::getInstance().obtainDeviceToken(id, devicePtr);
-}
-
-status_t AMIDI_getDeviceInfo(AMIDI_Device device, AMIDI_DeviceInfo *deviceInfoPtr) {
- sp<BpMidiDeviceServer> deviceServer;
- status_t result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
- if (result != OK) {
- ALOGE("AMIDI_getDeviceInfo bad device token %d: %d", device, result);
- return result;
- }
-
+/*
+ * Device Functions
+ */
+status_t AMIDI_getDeviceInfo(AMIDI_Device *device, AMIDI_DeviceInfo *deviceInfoPtr) {
MidiDeviceInfo deviceInfo;
- Status txResult = deviceServer->getDeviceInfo(&deviceInfo);
+ Status txResult = device->server->getDeviceInfo(&deviceInfo);
if (!txResult.isOk()) {
ALOGE("AMIDI_getDeviceInfo transaction error: %d", txResult.transactionError());
return txResult.transactionError();
@@ -87,49 +93,74 @@ status_t AMIDI_getDeviceInfo(AMIDI_Device device, AMIDI_DeviceInfo *deviceInfoPt
deviceInfoPtr->isPrivate = deviceInfo.isPrivate();
deviceInfoPtr->inputPortCount = deviceInfo.getInputPortNames().size();
deviceInfoPtr->outputPortCount = deviceInfo.getOutputPortNames().size();
+
return OK;
}
/*
- * Output (receiving) API
+ * Port Helpers
*/
-status_t AMIDI_openOutputPort(AMIDI_Device device, int portNumber, AMIDI_OutputPort *outputPortPtr) {
- sp<BpMidiDeviceServer> deviceServer;
- status_t result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
- if (result != OK) {
- ALOGE("AMIDI_openOutputPort bad device token %d: %d", device, result);
- return result;
- }
-
+static status_t AMIDI_openPort(AMIDI_Device *device, int portNumber, int type,
+ AMIDI_Port **portPtr) {
sp<BBinder> portToken(new BBinder());
unique_fd ufd;
- Status txResult = deviceServer->openOutputPort(portToken, portNumber, &ufd);
+ Status txResult = type == PORTTYPE_OUTPUT
+ ? device->server->openOutputPort(portToken, portNumber, &ufd)
+ : device->server->openInputPort(portToken, portNumber, &ufd);
if (!txResult.isOk()) {
- ALOGE("AMIDI_openOutputPort transaction error: %d", txResult.transactionError());
+ ALOGE("AMIDI_openPort transaction error: %d", txResult.transactionError());
return txResult.transactionError();
}
- result = MidiPortRegistry::getInstance().addOutputPort(
- device, portToken, std::move(ufd), outputPortPtr);
- if (result != OK) {
- ALOGE("AMIDI_openOutputPort port registration error: %d", result);
- // Close port
- return result;
+ AMIDI_Port* port = new AMIDI_Port;
+ port->state = MIDI_PORT_STATE_OPEN_IDLE;
+ port->device = device;
+ port->binderToken = portToken;
+ port->ufd = std::move(ufd);
+
+ *portPtr = port;
+
+ return OK;
+}
+
+static status_t AMIDI_closePort(AMIDI_Port *port) {
+ int portState = MIDI_PORT_STATE_OPEN_IDLE;
+ while (!port->state.compare_exchange_weak(portState, MIDI_PORT_STATE_CLOSED)) {
+ if (portState == MIDI_PORT_STATE_CLOSED) {
+ return -EINVAL; // Already closed
+ }
+ }
+
+ Status txResult = port->device->server->closePort(port->binderToken);
+ if (!txResult.isOk()) {
+ return txResult.transactionError();
}
+
+ delete port;
+
return OK;
}
-ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssize_t maxMessages) {
- unique_fd *ufd;
- // TODO: May return a nicer self-unlocking object
- status_t result = MidiPortRegistry::getInstance().getOutputPortFdAndLock(outputPort, &ufd);
- if (result != OK) {
- return result;
+/*
+ * Output (receiving) API
+ */
+status_t AMIDI_openOutputPort(AMIDI_Device *device, int portNumber,
+ AMIDI_OutputPort **outputPortPtr) {
+ return AMIDI_openPort(device, portNumber, PORTTYPE_OUTPUT, (AMIDI_Port**)outputPortPtr);
+}
+
+ssize_t AMIDI_receive(AMIDI_OutputPort *outputPort, AMIDI_Message *messages, ssize_t maxMessages) {
+ AMIDI_Port *port = (AMIDI_Port*)outputPort;
+ int portState = MIDI_PORT_STATE_OPEN_IDLE;
+ if (!port->state.compare_exchange_strong(portState, MIDI_PORT_STATE_OPEN_ACTIVE)) {
+ // The port has been closed.
+ return -EPIPE;
}
+ status_t result = OK;
ssize_t messagesRead = 0;
while (messagesRead < maxMessages) {
- struct pollfd checkFds[1] = { { *ufd, POLLIN, 0 } };
+ struct pollfd checkFds[1] = { { port->ufd, POLLIN, 0 } };
int pollResult = poll(checkFds, 1, 0);
if (pollResult < 1) {
result = android::INVALID_OPERATION;
@@ -139,7 +170,7 @@ ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssiz
AMIDI_Message *message = &messages[messagesRead];
uint8_t readBuffer[AMIDI_PACKET_SIZE];
memset(readBuffer, 0, sizeof(readBuffer));
- ssize_t readCount = read(*ufd, readBuffer, sizeof(readBuffer));
+ ssize_t readCount = read(port->ufd, readBuffer, sizeof(readBuffer));
if (readCount == EINTR) {
continue;
}
@@ -157,100 +188,38 @@ ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssiz
if (dataSize) {
memcpy(message->buffer, readBuffer + 1, dataSize);
}
- message->timestamp = *(uint64_t*) (readBuffer + readCount - sizeof(uint64_t));
+ message->timestamp = *(uint64_t*)(readBuffer + readCount - sizeof(uint64_t));
}
message->len = dataSize;
++messagesRead;
}
- MidiPortRegistry::getInstance().unlockOutputPort(outputPort);
+ port->state.store(MIDI_PORT_STATE_OPEN_IDLE);
+
return result == OK ? messagesRead : result;
}
-status_t AMIDI_closeOutputPort(AMIDI_OutputPort outputPort) {
- AMIDI_Device device;
- sp<IBinder> portToken;
- status_t result =
- MidiPortRegistry::getInstance().removeOutputPort(outputPort, &device, &portToken);
- if (result != OK) {
- return result;
- }
-
- sp<BpMidiDeviceServer> deviceServer;
- result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
- if (result != OK) {
- return result;
- }
-
- Status txResult = deviceServer->closePort(portToken);
- if (!txResult.isOk()) {
- return txResult.transactionError();
- }
- return OK;
+status_t AMIDI_closeOutputPort(AMIDI_OutputPort *outputPort) {
+ return AMIDI_closePort((AMIDI_Port*)outputPort);
}
/*
* Input (sending) API
*/
-status_t AMIDI_openInputPort(AMIDI_Device device, int portNumber, AMIDI_InputPort *inputPortPtr) {
- sp<BpMidiDeviceServer> deviceServer;
- status_t result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
- if (result != OK) {
- ALOGE("AMIDI_openInputPort bad device token %d: %d", device, result);
- return result;
- }
-
- sp<BBinder> portToken(new BBinder());
- unique_fd ufd; // this is the file descriptor of the "receive" port s
- Status txResult = deviceServer->openInputPort(portToken, portNumber, &ufd);
- if (!txResult.isOk()) {
- ALOGE("AMIDI_openInputPort transaction error: %d", txResult.transactionError());
- return txResult.transactionError();
- }
-
- result = MidiPortRegistry::getInstance().addInputPort(
- device, portToken, std::move(ufd), inputPortPtr);
- if (result != OK) {
- ALOGE("AMIDI_openInputPort port registration error: %d", result);
- // Close port
- return result;
- }
-
- return OK;
+status_t AMIDI_openInputPort(AMIDI_Device *device, int portNumber, AMIDI_InputPort **inputPortPtr) {
+ return AMIDI_openPort(device, portNumber, PORTTYPE_INPUT, (AMIDI_Port**)inputPortPtr);
}
-status_t AMIDI_closeInputPort(AMIDI_InputPort inputPort) {
- AMIDI_Device device;
- sp<IBinder> portToken;
- status_t result = MidiPortRegistry::getInstance().removeInputPort(
- inputPort, &device, &portToken);
- if (result != OK) {
- ALOGE("AMIDI_closeInputPort remove port error: %d", result);
- return result;
- }
-
- sp<BpMidiDeviceServer> deviceServer;
- result = MidiDeviceRegistry::getInstance().getDeviceByToken(device, &deviceServer);
- if (result != OK) {
- ALOGE("AMIDI_closeInputPort can't find device error: %d", result);
- return result;
- }
-
- Status txResult = deviceServer->closePort(portToken);
- if (!txResult.isOk()) {
- result = txResult.transactionError();
- ALOGE("AMIDI_closeInputPort transaction error: %d", result);
- return result;
- }
-
- return OK;
+status_t AMIDI_closeInputPort(AMIDI_InputPort *inputPort) {
+ return AMIDI_closePort((AMIDI_Port*)inputPort);
}
-ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort /*inputPort*/) {
+ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort */*inputPort*/) {
return SIZE_MIDIRECEIVEBUFFER;
}
-static ssize_t AMIDI_makeSendBuffer(uint8_t *buffer, uint8_t *data, ssize_t numBytes, uint64_t timestamp) {
+static ssize_t AMIDI_makeSendBuffer(
+ uint8_t *buffer, uint8_t *data, ssize_t numBytes,uint64_t timestamp) {
buffer[0] = AMIDI_OPCODE_DATA;
memcpy(buffer + 1, data, numBytes);
memcpy(buffer + 1 + numBytes, &timestamp, sizeof(timestamp));
@@ -264,11 +233,11 @@ static ssize_t AMIDI_makeSendBuffer(uint8_t *buffer, uint8_t *data, ssize_t numB
// }
//}
-ssize_t AMIDI_send(AMIDI_InputPort inputPort, uint8_t *buffer, ssize_t numBytes) {
+ssize_t AMIDI_send(AMIDI_InputPort *inputPort, uint8_t *buffer, ssize_t numBytes) {
return AMIDI_sendWithTimestamp(inputPort, buffer, numBytes, 0);
}
-ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *data,
+ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort *inputPort, uint8_t *data,
ssize_t numBytes, int64_t timestamp) {
if (numBytes > SIZE_MIDIRECEIVEBUFFER) {
@@ -277,15 +246,9 @@ ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *data,
// AMIDI_logBuffer(data, numBytes);
- unique_fd *ufd = NULL;
- status_t result = MidiPortRegistry::getInstance().getInputPortFd(inputPort, &ufd);
- if (result != OK) {
- return result;
- }
-
uint8_t writeBuffer[SIZE_MIDIRECEIVEBUFFER + AMIDI_PACKET_OVERHEAD];
ssize_t numTransferBytes = AMIDI_makeSendBuffer(writeBuffer, data, numBytes, timestamp);
- ssize_t numWritten = write(*ufd, writeBuffer, numTransferBytes);
+ ssize_t numWritten = write(((AMIDI_Port*)inputPort)->ufd, writeBuffer, numTransferBytes);
if (numWritten < numTransferBytes) {
ALOGE("AMIDI_sendWithTimestamp Couldn't write MIDI data buffer. requested:%zu, written%zu",
@@ -295,16 +258,10 @@ ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *data,
return numWritten - AMIDI_PACKET_OVERHEAD;
}
-status_t AMIDI_flush(AMIDI_InputPort inputPort) {
- unique_fd *ufd = NULL;
- status_t result = MidiPortRegistry::getInstance().getInputPortFd(inputPort, &ufd);
- if (result != OK) {
- return result;
- }
-
+status_t AMIDI_flush(AMIDI_InputPort *inputPort) {
uint8_t opCode = AMIDI_OPCODE_FLUSH;
ssize_t numTransferBytes = 1;
- ssize_t numWritten = write(*ufd, &opCode, numTransferBytes);
+ ssize_t numWritten = write(((AMIDI_Port*)inputPort)->ufd, &opCode, numTransferBytes);
if (numWritten < numTransferBytes) {
ALOGE("AMIDI_flush Couldn't write MIDI flush. requested:%zu, written%zu",
diff --git a/media/native/midi/midi.h b/media/native/midi/midi.h
index 717bc666253e..9332b44dddd2 100644
--- a/media/native/midi/midi.h
+++ b/media/native/midi/midi.h
@@ -29,22 +29,11 @@ using android::status_t;
extern "C" {
#endif
-//typedef struct _AMIDI_Device;
-//typedef struct _AMIDI_InputPort;
-//typedef struct _AMIDI_OutputPort;
-//typedef _AMIDI_Device* AMIDI_Device;
-//typedef _AMIDI_InputPort* AMIDI_InputPort;
-//typedef _AMIDI_OutputPort* AMIDI_OutputPort;
+struct AMIDI_Device;
+struct AMIDI_InputPort;
+struct AMIDI_OutputPort;
-typedef int32_t AMIDI_Device;
-typedef int32_t AMIDI_InputPort;
-typedef int32_t AMIDI_OutputPort;
-
-//TODO - Do we want to wrap this stuff in namespace android { namespace media { namespace midi {?
-
-enum {
- AMIDI_INVALID_HANDLE = -1
-};
+#define AMIDI_INVALID_HANDLE NULL
enum {
AMIDI_OPCODE_DATA = 1,
@@ -56,10 +45,10 @@ enum {
};
typedef struct {
- uint32_t opcode;
- uint8_t buffer[AMIDI_BUFFER_SIZE];
- size_t len;
- int64_t timestamp;
+ uint32_t opcode;
+ uint8_t buffer[AMIDI_BUFFER_SIZE];
+ size_t len;
+ int64_t timestamp;
} AMIDI_Message;
enum {
@@ -80,16 +69,6 @@ typedef struct {
* Device API
*/
/*
- * Retrieves the native API device token for the specified Java API device ID.
- *
- * uid The Java API id of the device.
- * devicePtr Receives the associated native API token for the device.
- *
- * Returns OK or a (negative) error code.
- */
-status_t AMIDI_getDeviceById(int32_t id, AMIDI_Device *devicePtr);
-
-/*
* Retrieves information for the native MIDI device.
*
* device The Native API token for the device.
@@ -97,7 +76,7 @@ status_t AMIDI_getDeviceById(int32_t id, AMIDI_Device *devicePtr);
*
* Returns OK or a (negative) error code.
*/
-status_t AMIDI_getDeviceInfo(AMIDI_Device device, AMIDI_DeviceInfo *deviceInfoPtr);
+status_t AMIDI_getDeviceInfo(AMIDI_Device *device, AMIDI_DeviceInfo *deviceInfoPtr);
/*
* API for receiving data from the Output port of a device.
@@ -111,7 +90,8 @@ status_t AMIDI_getDeviceInfo(AMIDI_Device device, AMIDI_DeviceInfo *deviceInfoPt
*
* Returns OK, or a (negative) error code.
*/
-status_t AMIDI_openOutputPort(AMIDI_Device device, int portNumber, AMIDI_OutputPort *outputPortPtr);
+status_t AMIDI_openOutputPort(AMIDI_Device *device, int portNumber,
+ AMIDI_OutputPort **outputPortPtr);
/*
* Receives any pending MIDI messages (up to the specified maximum number of messages).
@@ -122,7 +102,7 @@ status_t AMIDI_openOutputPort(AMIDI_Device device, int portNumber, AMIDI_OutputP
*
* Returns the number of messages received, or a (negative) error code.
*/
-ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssize_t maxMessages);
+ssize_t AMIDI_receive(AMIDI_OutputPort *outputPort, AMIDI_Message *messages, ssize_t maxMessages);
/*
* Closes the output port.
@@ -131,7 +111,7 @@ ssize_t AMIDI_receive(AMIDI_OutputPort outputPort, AMIDI_Message *messages, ssiz
*
* Returns OK, or a (negative) error code.
*/
-status_t AMIDI_closeOutputPort(AMIDI_OutputPort outputPort);
+status_t AMIDI_closeOutputPort(AMIDI_OutputPort *outputPort);
/*
* API for sending data to the Input port of a device.
@@ -145,12 +125,12 @@ status_t AMIDI_closeOutputPort(AMIDI_OutputPort outputPort);
*
* Returns OK, or a (negative) error code.
*/
-status_t AMIDI_openInputPort(AMIDI_Device device, int portNumber, AMIDI_InputPort *inputPortPtr);
+status_t AMIDI_openInputPort(AMIDI_Device *device, int portNumber, AMIDI_InputPort **inputPortPtr);
/*
* Returns the maximum number of bytes that can be received in a single MIDI message.
*/
-ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort inputPort);
+ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort *inputPort);
/*
* Sends data to the specified input port.
@@ -161,7 +141,7 @@ ssize_t AMIDI_getMaxMessageSizeInBytes(AMIDI_InputPort inputPort);
*
* Returns The number of bytes sent or a (negative) error code.
*/
-ssize_t AMIDI_send(AMIDI_InputPort inputPort, uint8_t *buffer, ssize_t numBytes);
+ssize_t AMIDI_send(AMIDI_InputPort *inputPort, uint8_t *buffer, ssize_t numBytes);
/*
* Sends data to the specified input port with a timestamp.
@@ -173,7 +153,7 @@ ssize_t AMIDI_send(AMIDI_InputPort inputPort, uint8_t *buffer, ssize_t numBytes)
*
* Returns The number of bytes sent or a (negative) error code.
*/
-ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *buffer,
+ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort *inputPort, uint8_t *buffer,
ssize_t numBytes, int64_t timestamp);
/*
@@ -183,7 +163,7 @@ ssize_t AMIDI_sendWithTimestamp(AMIDI_InputPort inputPort, uint8_t *buffer,
*
* Returns OK, or a (negative) error code.
*/
-status_t AMIDI_flush(AMIDI_InputPort inputPort);
+status_t AMIDI_flush(AMIDI_InputPort *inputPort);
/*
* Closes the input port.
@@ -193,7 +173,7 @@ status_t AMIDI_flush(AMIDI_InputPort inputPort);
*
* Returns OK, or a (negative) error code.
*/
-status_t AMIDI_closeInputPort(AMIDI_InputPort inputPort);
+status_t AMIDI_closeInputPort(AMIDI_InputPort *inputPort);
#ifdef __cplusplus
}
diff --git a/media/native/midi/midi_internal.h b/media/native/midi/midi_internal.h
new file mode 100644
index 000000000000..fd4770e05d6c
--- /dev/null
+++ b/media/native/midi/midi_internal.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef ANDROID_MEDIA_MIDI_INTERNAL_H_
+#define ANDROID_MEDIA_MIDI_INTERNAL_H_
+
+#include "android/media/midi/BpMidiDeviceServer.h"
+
+struct AMIDI_Device {
+ android::sp<android::media::midi::BpMidiDeviceServer> server;
+ int32_t deviceId;
+};
+
+#endif // ANDROID_MEDIA_MIDI_INTERNAL_H_