1a64c8c79af1a15911c55306d83a797fa50969f77niko/*
2a64c8c79af1a15911c55306d83a797fa50969f77niko * Copyright (C) 2009 The Android Open Source Project
3a64c8c79af1a15911c55306d83a797fa50969f77niko *
4a64c8c79af1a15911c55306d83a797fa50969f77niko * Licensed under the Apache License, Version 2.0 (the "License");
5a64c8c79af1a15911c55306d83a797fa50969f77niko * you may not use this file except in compliance with the License.
6a64c8c79af1a15911c55306d83a797fa50969f77niko * You may obtain a copy of the License at
7a64c8c79af1a15911c55306d83a797fa50969f77niko *
8a64c8c79af1a15911c55306d83a797fa50969f77niko *      http://www.apache.org/licenses/LICENSE-2.0
9a64c8c79af1a15911c55306d83a797fa50969f77niko *
10a64c8c79af1a15911c55306d83a797fa50969f77niko * Unless required by applicable law or agreed to in writing, software
11a64c8c79af1a15911c55306d83a797fa50969f77niko * distributed under the License is distributed on an "AS IS" BASIS,
12a64c8c79af1a15911c55306d83a797fa50969f77niko * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a64c8c79af1a15911c55306d83a797fa50969f77niko * See the License for the specific language governing permissions and
14a64c8c79af1a15911c55306d83a797fa50969f77niko * limitations under the License.
15a64c8c79af1a15911c55306d83a797fa50969f77niko */
16a64c8c79af1a15911c55306d83a797fa50969f77niko
17a64c8c79af1a15911c55306d83a797fa50969f77niko//#define LOG_NDEBUG 0
18a64c8c79af1a15911c55306d83a797fa50969f77niko#define LOG_TAG "Metadata"
19a64c8c79af1a15911c55306d83a797fa50969f77niko#include <utils/Log.h>
20a64c8c79af1a15911c55306d83a797fa50969f77niko
21a64c8c79af1a15911c55306d83a797fa50969f77niko#include <sys/types.h>
22a64c8c79af1a15911c55306d83a797fa50969f77niko#include <media/Metadata.h>
23a64c8c79af1a15911c55306d83a797fa50969f77niko#include <binder/Parcel.h>
24a64c8c79af1a15911c55306d83a797fa50969f77niko#include <utils/Errors.h>
25a64c8c79af1a15911c55306d83a797fa50969f77niko#include <utils/RefBase.h>
26a64c8c79af1a15911c55306d83a797fa50969f77niko
27a64c8c79af1a15911c55306d83a797fa50969f77niko// This file contains code to serialize Metadata triples (key, type,
28a64c8c79af1a15911c55306d83a797fa50969f77niko// value) into a parcel. The Parcel is destinated to be decoded by the
29a64c8c79af1a15911c55306d83a797fa50969f77niko// Metadata.java class.
30a64c8c79af1a15911c55306d83a797fa50969f77niko
31a64c8c79af1a15911c55306d83a797fa50969f77nikonamespace {
32a64c8c79af1a15911c55306d83a797fa50969f77niko// All these constants below must be kept in sync with Metadata.java.
33a64c8c79af1a15911c55306d83a797fa50969f77nikoenum MetadataId {
34a64c8c79af1a15911c55306d83a797fa50969f77niko    FIRST_SYSTEM_ID = 1,
358e51d58fca9b7669f271378f9245e180f4360cbcGloria Wang    LAST_SYSTEM_ID = 31,
36a64c8c79af1a15911c55306d83a797fa50969f77niko    FIRST_CUSTOM_ID = 8192
37a64c8c79af1a15911c55306d83a797fa50969f77niko};
38a64c8c79af1a15911c55306d83a797fa50969f77niko
39a64c8c79af1a15911c55306d83a797fa50969f77niko// Types
40a64c8c79af1a15911c55306d83a797fa50969f77nikoenum Types {
41a64c8c79af1a15911c55306d83a797fa50969f77niko    STRING_VAL = 1,
42a64c8c79af1a15911c55306d83a797fa50969f77niko    INTEGER_VAL,
43a64c8c79af1a15911c55306d83a797fa50969f77niko    BOOLEAN_VAL,
44a64c8c79af1a15911c55306d83a797fa50969f77niko    LONG_VAL,
45a64c8c79af1a15911c55306d83a797fa50969f77niko    DOUBLE_VAL,
46a64c8c79af1a15911c55306d83a797fa50969f77niko    DATE_VAL,
47a64c8c79af1a15911c55306d83a797fa50969f77niko    BYTE_ARRAY_VAL,
48a64c8c79af1a15911c55306d83a797fa50969f77niko};
49a64c8c79af1a15911c55306d83a797fa50969f77niko
50a64c8c79af1a15911c55306d83a797fa50969f77nikoconst size_t kRecordHeaderSize = 3 * sizeof(int32_t);
51a64c8c79af1a15911c55306d83a797fa50969f77nikoconst int32_t kMetaMarker = 0x4d455441;  // 'M' 'E' 'T' 'A'
52a64c8c79af1a15911c55306d83a797fa50969f77niko
53a64c8c79af1a15911c55306d83a797fa50969f77niko}  // anonymous namespace
54a64c8c79af1a15911c55306d83a797fa50969f77niko
55a64c8c79af1a15911c55306d83a797fa50969f77nikonamespace android {
56a64c8c79af1a15911c55306d83a797fa50969f77nikonamespace media {
57a64c8c79af1a15911c55306d83a797fa50969f77niko
58a64c8c79af1a15911c55306d83a797fa50969f77nikoMetadata::Metadata(Parcel *p)
59a64c8c79af1a15911c55306d83a797fa50969f77niko    :mData(p),
60e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten      mBegin(p->dataPosition()) { }
61a64c8c79af1a15911c55306d83a797fa50969f77niko
62a64c8c79af1a15911c55306d83a797fa50969f77nikoMetadata::~Metadata() { }
63a64c8c79af1a15911c55306d83a797fa50969f77niko
64a64c8c79af1a15911c55306d83a797fa50969f77nikovoid Metadata::resetParcel()
65a64c8c79af1a15911c55306d83a797fa50969f77niko{
66a64c8c79af1a15911c55306d83a797fa50969f77niko    mData->setDataPosition(mBegin);
67a64c8c79af1a15911c55306d83a797fa50969f77niko}
68a64c8c79af1a15911c55306d83a797fa50969f77niko
69a64c8c79af1a15911c55306d83a797fa50969f77niko// Update the 4 bytes int at the beginning of the parcel which holds
70a64c8c79af1a15911c55306d83a797fa50969f77niko// the number of bytes written so far.
71a64c8c79af1a15911c55306d83a797fa50969f77nikovoid Metadata::updateLength()
72a64c8c79af1a15911c55306d83a797fa50969f77niko{
73a64c8c79af1a15911c55306d83a797fa50969f77niko    const size_t end = mData->dataPosition();
74a64c8c79af1a15911c55306d83a797fa50969f77niko
75a64c8c79af1a15911c55306d83a797fa50969f77niko    mData->setDataPosition(mBegin);
76a64c8c79af1a15911c55306d83a797fa50969f77niko    mData->writeInt32(end - mBegin);
77a64c8c79af1a15911c55306d83a797fa50969f77niko    mData->setDataPosition(end);
78a64c8c79af1a15911c55306d83a797fa50969f77niko}
79a64c8c79af1a15911c55306d83a797fa50969f77niko
80a64c8c79af1a15911c55306d83a797fa50969f77niko// Write the header. The java layer will look for the marker.
81a64c8c79af1a15911c55306d83a797fa50969f77nikobool Metadata::appendHeader()
82a64c8c79af1a15911c55306d83a797fa50969f77niko{
83a64c8c79af1a15911c55306d83a797fa50969f77niko    bool ok = true;
84a64c8c79af1a15911c55306d83a797fa50969f77niko
85a64c8c79af1a15911c55306d83a797fa50969f77niko    // Placeholder for the length of the metadata
86a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(-1) == OK;
87a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(kMetaMarker) == OK;
88a64c8c79af1a15911c55306d83a797fa50969f77niko    return ok;
89a64c8c79af1a15911c55306d83a797fa50969f77niko}
90a64c8c79af1a15911c55306d83a797fa50969f77niko
91a64c8c79af1a15911c55306d83a797fa50969f77nikobool Metadata::appendBool(int key, bool val)
92a64c8c79af1a15911c55306d83a797fa50969f77niko{
93a64c8c79af1a15911c55306d83a797fa50969f77niko    if (!checkKey(key)) {
94a64c8c79af1a15911c55306d83a797fa50969f77niko        return false;
95a64c8c79af1a15911c55306d83a797fa50969f77niko    }
96a64c8c79af1a15911c55306d83a797fa50969f77niko
97a64c8c79af1a15911c55306d83a797fa50969f77niko    const size_t begin = mData->dataPosition();
98a64c8c79af1a15911c55306d83a797fa50969f77niko    bool ok = true;
99a64c8c79af1a15911c55306d83a797fa50969f77niko
100a64c8c79af1a15911c55306d83a797fa50969f77niko    // 4 int32s: size, key, type, value.
101a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
102a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(key) == OK;
103a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(BOOLEAN_VAL) == OK;
104a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(val ? 1 : 0) == OK;
105a64c8c79af1a15911c55306d83a797fa50969f77niko    if (!ok) {
106a64c8c79af1a15911c55306d83a797fa50969f77niko        mData->setDataPosition(begin);
107a64c8c79af1a15911c55306d83a797fa50969f77niko    }
108a64c8c79af1a15911c55306d83a797fa50969f77niko    return ok;
109a64c8c79af1a15911c55306d83a797fa50969f77niko}
110a64c8c79af1a15911c55306d83a797fa50969f77niko
111a64c8c79af1a15911c55306d83a797fa50969f77nikobool Metadata::appendInt32(int key, int32_t val)
112a64c8c79af1a15911c55306d83a797fa50969f77niko{
113a64c8c79af1a15911c55306d83a797fa50969f77niko    if (!checkKey(key)) {
114a64c8c79af1a15911c55306d83a797fa50969f77niko        return false;
115a64c8c79af1a15911c55306d83a797fa50969f77niko    }
116a64c8c79af1a15911c55306d83a797fa50969f77niko
117a64c8c79af1a15911c55306d83a797fa50969f77niko    const size_t begin = mData->dataPosition();
118a64c8c79af1a15911c55306d83a797fa50969f77niko    bool ok = true;
119a64c8c79af1a15911c55306d83a797fa50969f77niko
120a64c8c79af1a15911c55306d83a797fa50969f77niko    // 4 int32s: size, key, type, value.
121a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(4 * sizeof(int32_t)) == OK;
122a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(key) == OK;
123a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(INTEGER_VAL) == OK;
124a64c8c79af1a15911c55306d83a797fa50969f77niko    ok = ok && mData->writeInt32(val) == OK;
125a64c8c79af1a15911c55306d83a797fa50969f77niko    if (!ok) {
126a64c8c79af1a15911c55306d83a797fa50969f77niko        mData->setDataPosition(begin);
127a64c8c79af1a15911c55306d83a797fa50969f77niko    }
128a64c8c79af1a15911c55306d83a797fa50969f77niko    return ok;
129a64c8c79af1a15911c55306d83a797fa50969f77niko}
130a64c8c79af1a15911c55306d83a797fa50969f77niko
131a64c8c79af1a15911c55306d83a797fa50969f77niko// Check the key (i.e metadata id) is valid if it is a system one.
132a64c8c79af1a15911c55306d83a797fa50969f77niko// Loop over all the exiting ones in the Parcel to check for duplicate
133a64c8c79af1a15911c55306d83a797fa50969f77niko// (not allowed).
134a64c8c79af1a15911c55306d83a797fa50969f77nikobool Metadata::checkKey(int key)
135a64c8c79af1a15911c55306d83a797fa50969f77niko{
136a64c8c79af1a15911c55306d83a797fa50969f77niko    if (key < FIRST_SYSTEM_ID ||
137a64c8c79af1a15911c55306d83a797fa50969f77niko        (LAST_SYSTEM_ID < key && key < FIRST_CUSTOM_ID)) {
13829357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Bad key %d", key);
139a64c8c79af1a15911c55306d83a797fa50969f77niko        return false;
140a64c8c79af1a15911c55306d83a797fa50969f77niko    }
141a64c8c79af1a15911c55306d83a797fa50969f77niko    size_t curr = mData->dataPosition();
142a64c8c79af1a15911c55306d83a797fa50969f77niko    // Loop over the keys to check if it has been used already.
143a64c8c79af1a15911c55306d83a797fa50969f77niko    mData->setDataPosition(mBegin);
144a64c8c79af1a15911c55306d83a797fa50969f77niko
145a64c8c79af1a15911c55306d83a797fa50969f77niko    bool error = false;
146a64c8c79af1a15911c55306d83a797fa50969f77niko    size_t left = curr - mBegin;
147a64c8c79af1a15911c55306d83a797fa50969f77niko    while (left > 0) {
148a64c8c79af1a15911c55306d83a797fa50969f77niko        size_t pos = mData->dataPosition();
149a64c8c79af1a15911c55306d83a797fa50969f77niko        size_t size = mData->readInt32();
150a64c8c79af1a15911c55306d83a797fa50969f77niko        if (size < kRecordHeaderSize || size > left) {
151a64c8c79af1a15911c55306d83a797fa50969f77niko            error = true;
152a64c8c79af1a15911c55306d83a797fa50969f77niko            break;
153a64c8c79af1a15911c55306d83a797fa50969f77niko        }
154a64c8c79af1a15911c55306d83a797fa50969f77niko        if (mData->readInt32() == key) {
15529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            ALOGE("Key exists already %d", key);
156a64c8c79af1a15911c55306d83a797fa50969f77niko            error = true;
157a64c8c79af1a15911c55306d83a797fa50969f77niko            break;
158a64c8c79af1a15911c55306d83a797fa50969f77niko        }
159a64c8c79af1a15911c55306d83a797fa50969f77niko        mData->setDataPosition(pos + size);
160a64c8c79af1a15911c55306d83a797fa50969f77niko        left -= size;
161a64c8c79af1a15911c55306d83a797fa50969f77niko    }
162a64c8c79af1a15911c55306d83a797fa50969f77niko    mData->setDataPosition(curr);
163a64c8c79af1a15911c55306d83a797fa50969f77niko    return !error;
164a64c8c79af1a15911c55306d83a797fa50969f77niko}
165a64c8c79af1a15911c55306d83a797fa50969f77niko
166a64c8c79af1a15911c55306d83a797fa50969f77niko}  // namespace android::media
167a64c8c79af1a15911c55306d83a797fa50969f77niko}  // namespace android
168