diff options
author | 2017-03-05 08:12:18 -0700 | |
---|---|---|
committer | 2017-03-10 15:54:16 -0700 | |
commit | 71f672b98a0c31001ca28de86d9ac99fef0812b1 (patch) | |
tree | a4ca0e175f221a40870c7886f8a3033f5425cb12 /media/native | |
parent | f7683a6f173cca09b33e7eaeb51f3b867f68deaa (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.mk | 4 | ||||
-rw-r--r-- | media/native/midi/MidiDeviceRegistry.cpp | 106 | ||||
-rw-r--r-- | media/native/midi/MidiDeviceRegistry.h | 104 | ||||
-rw-r--r-- | media/native/midi/MidiPortRegistry.cpp | 200 | ||||
-rw-r--r-- | media/native/midi/MidiPortRegistry.h | 192 | ||||
-rw-r--r-- | media/native/midi/midi.cpp | 225 | ||||
-rw-r--r-- | media/native/midi/midi.h | 58 | ||||
-rw-r--r-- | media/native/midi/midi_internal.h | 27 |
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, ×tamp, 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_ |