/* * Copyright (C) 2016 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. */ #define LOG_TAG "MidiDeviceInfo" #include <media/MidiDeviceInfo.h> #include <binder/Parcel.h> #include <log/log.h> #include <utils/Errors.h> #include <utils/String16.h> namespace android { namespace media { namespace midi { // The constant values need to be kept in sync with MidiDeviceInfo.java. // static const char* const MidiDeviceInfo::PROPERTY_NAME = "name"; const char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer"; const char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product"; const char* const MidiDeviceInfo::PROPERTY_VERSION = "version"; const char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number"; const char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card"; const char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device"; String16 MidiDeviceInfo::getProperty(const char* propertyName) { String16 value; if (mProperties.getString(String16(propertyName), &value)) { return value; } else { return String16(); } } #define RETURN_IF_FAILED(calledOnce) \ { \ status_t returnStatus = calledOnce; \ if (returnStatus) { \ ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \ return returnStatus; \ } \ } status_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const { // Needs to be kept in sync with code in MidiDeviceInfo.java RETURN_IF_FAILED(parcel->writeInt32(mType)); RETURN_IF_FAILED(parcel->writeInt32(mId)); RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size())); RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size())); RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames)); RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames)); RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0)); RETURN_IF_FAILED(mProperties.writeToParcel(parcel)); // This corresponds to "extra" properties written by Java code RETURN_IF_FAILED(mProperties.writeToParcel(parcel)); return OK; } status_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) { // Needs to be kept in sync with code in MidiDeviceInfo.java RETURN_IF_FAILED(parcel->readInt32(&mType)); RETURN_IF_FAILED(parcel->readInt32(&mId)); int32_t inputPortCount; RETURN_IF_FAILED(parcel->readInt32(&inputPortCount)); int32_t outputPortCount; RETURN_IF_FAILED(parcel->readInt32(&outputPortCount)); RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount)); RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount)); int32_t isPrivate; RETURN_IF_FAILED(parcel->readInt32(&isPrivate)); mIsPrivate = isPrivate == 1; RETURN_IF_FAILED(mProperties.readFromParcel(parcel)); // Ignore "extra" properties as they may contain Java Parcelables return OK; } status_t MidiDeviceInfo::readStringVector( const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) { std::unique_ptr<std::vector<std::unique_ptr<String16>>> v; status_t result = parcel->readString16Vector(&v); if (result != OK) return result; vectorPtr->clear(); if (v.get() != nullptr) { for (const auto& iter : *v) { if (iter.get() != nullptr) { vectorPtr->push_back(*iter); } else { vectorPtr->push_back(String16()); } } } else { vectorPtr->resize(defaultLength); } return OK; } status_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const { std::vector<String16> v; for (size_t i = 0; i < vector.size(); ++i) { v.push_back(vector[i]); } return parcel->writeString16Vector(v); } // Vector does not define operator== static inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) { if (lhs.size() != rhs.size()) return false; for (size_t i = 0; i < lhs.size(); ++i) { if (lhs[i] != rhs[i]) return false; } return true; } bool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) { return (lhs.mType == rhs.mType && lhs.mId == rhs.mId && areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) && areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) && lhs.mProperties == rhs.mProperties && lhs.mIsPrivate == rhs.mIsPrivate); } } // namespace midi } // namespace media } // namespace android