lin
2025-08-20 171e08343a9b6df6c31197f5b4800e8004800f5b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/*
 * 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