1f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov/*
2f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * Copyright (C) 2016 The Android Open Source Project
3f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov *
4f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * Licensed under the Apache License, Version 2.0 (the "License");
5f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * you may not use this file except in compliance with the License.
6f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * You may obtain a copy of the License at
7f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov *
8f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov *      http://www.apache.org/licenses/LICENSE-2.0
9f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov *
10f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * Unless required by applicable law or agreed to in writing, software
11f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * distributed under the License is distributed on an "AS IS" BASIS,
12f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * See the License for the specific language governing permissions and
14f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov * limitations under the License.
15f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov */
16f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
17f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#define LOG_TAG "MidiDeviceInfo"
18f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
19f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#include "MidiDeviceInfo.h"
20f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
21f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#include <binder/Parcel.h>
22f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#include <log/log.h>
23f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#include <utils/Errors.h>
24f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#include <utils/String16.h>
25f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
26f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovnamespace android {
27f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovnamespace media {
28f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovnamespace midi {
29f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
30f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov// The constant values need to be kept in sync with MidiDeviceInfo.java.
31f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov// static
32f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_NAME = "name";
33f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_MANUFACTURER = "manufacturer";
34f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_PRODUCT = "product";
35f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_VERSION = "version";
36f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_SERIAL_NUMBER = "serial_number";
37f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_ALSA_CARD = "alsa_card";
38f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovconst char* const MidiDeviceInfo::PROPERTY_ALSA_DEVICE = "alsa_device";
39f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
40f28256f3113212db62aa8527b9ceae4caa414be3Mikhail NaganovString16 MidiDeviceInfo::getProperty(const char* propertyName) {
41f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    String16 value;
42f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    if (mProperties.getString(String16(propertyName), &value)) {
43f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        return value;
44f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    } else {
45f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        return String16();
46f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    }
47f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
48f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
49f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov#define RETURN_IF_FAILED(calledOnce)                                     \
50f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    {                                                                    \
51f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        status_t returnStatus = calledOnce;                              \
52f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        if (returnStatus) {                                              \
53f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
54f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            return returnStatus;                                         \
55f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov         }                                                               \
56f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    }
57f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
58f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovstatus_t MidiDeviceInfo::writeToParcel(Parcel* parcel) const {
59f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    // Needs to be kept in sync with code in MidiDeviceInfo.java
60f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->writeInt32(mType));
61f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->writeInt32(mId));
62f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mInputPortNames.size()));
63f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->writeInt32((int32_t)mOutputPortNames.size()));
64f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(writeStringVector(parcel, mInputPortNames));
65f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(writeStringVector(parcel, mOutputPortNames));
66f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->writeInt32(mIsPrivate ? 1 : 0));
67f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
68f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    // This corresponds to "extra" properties written by Java code
69f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(mProperties.writeToParcel(parcel));
70f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    return OK;
71f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
72f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
73f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovstatus_t MidiDeviceInfo::readFromParcel(const Parcel* parcel) {
74f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    // Needs to be kept in sync with code in MidiDeviceInfo.java
75f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->readInt32(&mType));
76f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->readInt32(&mId));
77f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    int32_t inputPortCount;
78f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->readInt32(&inputPortCount));
79f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    int32_t outputPortCount;
80f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->readInt32(&outputPortCount));
81f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(readStringVector(parcel, &mInputPortNames, inputPortCount));
82f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(readStringVector(parcel, &mOutputPortNames, outputPortCount));
83f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    int32_t isPrivate;
84f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(parcel->readInt32(&isPrivate));
85f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    mIsPrivate = isPrivate == 1;
86f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    RETURN_IF_FAILED(mProperties.readFromParcel(parcel));
87f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    // Ignore "extra" properties as they may contain Java Parcelables
88f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    return OK;
89f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
90f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
91f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovstatus_t MidiDeviceInfo::readStringVector(
92f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        const Parcel* parcel, Vector<String16> *vectorPtr, size_t defaultLength) {
93f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    std::unique_ptr<std::vector<std::unique_ptr<String16>>> v;
94f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    status_t result = parcel->readString16Vector(&v);
95f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    if (result != OK) return result;
96f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    vectorPtr->clear();
97f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    if (v.get() != nullptr) {
98f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        for (const auto& iter : *v) {
99f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            if (iter.get() != nullptr) {
100f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov                vectorPtr->push_back(*iter);
101f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            } else {
102f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov                vectorPtr->push_back(String16());
103f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            }
104f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        }
105f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    } else {
106f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        vectorPtr->resize(defaultLength);
107f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    }
108f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    return OK;
109f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
110f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
111f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovstatus_t MidiDeviceInfo::writeStringVector(Parcel* parcel, const Vector<String16>& vector) const {
112f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    std::vector<String16> v;
113f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    for (size_t i = 0; i < vector.size(); ++i) {
114f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        v.push_back(vector[i]);
115f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    }
116f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    return parcel->writeString16Vector(v);
117f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
118f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
119f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov// Vector does not define operator==
120f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovstatic inline bool areVectorsEqual(const Vector<String16>& lhs, const Vector<String16>& rhs) {
121f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    if (lhs.size() != rhs.size()) return false;
122f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    for (size_t i = 0; i < lhs.size(); ++i) {
123f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov        if (lhs[i] != rhs[i]) return false;
124f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    }
125f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    return true;
126f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
127f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
128f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganovbool operator==(const MidiDeviceInfo& lhs, const MidiDeviceInfo& rhs) {
129f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov    return (lhs.mType == rhs.mType && lhs.mId == rhs.mId &&
130f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            areVectorsEqual(lhs.mInputPortNames, rhs.mInputPortNames) &&
131f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            areVectorsEqual(lhs.mOutputPortNames, rhs.mOutputPortNames) &&
132f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            lhs.mProperties == rhs.mProperties &&
133f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov            lhs.mIsPrivate == rhs.mIsPrivate);
134f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}
135f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov
136f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}  // namespace midi
137f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}  // namespace media
138f28256f3113212db62aa8527b9ceae4caa414be3Mikhail Naganov}  // namespace android
139