summaryrefslogtreecommitdiff
path: root/media/native/midi/MidiPortRegistry.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/native/midi/MidiPortRegistry.cpp')
-rw-r--r--media/native/midi/MidiPortRegistry.cpp200
1 files changed, 200 insertions, 0 deletions
diff --git a/media/native/midi/MidiPortRegistry.cpp b/media/native/midi/MidiPortRegistry.cpp
new file mode 100644
index 000000000000..fa70af8d0947
--- /dev/null
+++ b/media/native/midi/MidiPortRegistry.cpp
@@ -0,0 +1,200 @@
+/*
+ * 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