1d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber/*
2d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * Copyright (C) 2009 The Android Open Source Project
3d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *
4d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * you may not use this file except in compliance with the License.
6d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * You may obtain a copy of the License at
7d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *
8d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber *
10d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * Unless required by applicable law or agreed to in writing, software
11d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * See the License for the specific language governing permissions and
14d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber * limitations under the License.
15d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber */
16d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
17d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include "AMRNBEncoder.h"
18d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
19d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include "gsmamr_enc.h"
20d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
21d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include <media/stagefright/MediaBufferGroup.h>
22d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include <media/stagefright/MediaDebug.h>
23d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include <media/stagefright/MediaDefs.h>
24d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include <media/stagefright/MediaErrors.h>
25d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber#include <media/stagefright/MetaData.h>
26d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
27d49b526dd2009270cb15f7fe4e70b74673950608Andreas Hubernamespace android {
28d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
29d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberstatic const int32_t kNumSamplesPerFrame = 160;
30d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberstatic const int32_t kSampleRate = 8000;
31d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
32d49b526dd2009270cb15f7fe4e70b74673950608Andreas HuberAMRNBEncoder::AMRNBEncoder(const sp<MediaSource> &source)
33d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    : mSource(source),
34d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mStarted(false),
35d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mBufferGroup(NULL),
36d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mEncState(NULL),
37d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mSidState(NULL),
38d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mAnchorTimeUs(0),
39d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mNumFramesOutput(0),
40d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mInputBuffer(NULL),
41d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mMode(MR475),
42d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber      mNumInputSamples(0) {
43d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
44d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
45d49b526dd2009270cb15f7fe4e70b74673950608Andreas HuberAMRNBEncoder::~AMRNBEncoder() {
46d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (mStarted) {
47d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        stop();
48d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
49d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
50d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
51d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberstatic Mode PickModeFromBitrate(int32_t bps) {
52d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (bps <= 4750) {
53d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR475;
54d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else if (bps <= 5150) {
55d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR515;
56d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else if (bps <= 5900) {
57d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR59;
58d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else if (bps <= 6700) {
59d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR67;
60d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else if (bps <= 7400) {
61d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR74;
62d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else if (bps <= 7950) {
63d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR795;
64d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else if (bps <= 10200) {
65d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR102;
66d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else {
67d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        return MR122;
68d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
69d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
70d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
71d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberstatus_t AMRNBEncoder::start(MetaData *params) {
72d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK(!mStarted);
73d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
74d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mBufferGroup = new MediaBufferGroup;
75d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mBufferGroup->add_buffer(new MediaBuffer(32));
76d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
77d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK_EQ(AMREncodeInit(
78d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                &mEncState, &mSidState, false /* dtx_enable */),
79d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber             0);
80d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
81d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mSource->start();
82d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
83d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mAnchorTimeUs = 0;
84d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mNumFramesOutput = 0;
85d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mStarted = true;
86d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mNumInputSamples = 0;
87d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
88d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    int32_t bitrate;
89d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (params && params->findInt32(kKeyBitRate, &bitrate)) {
90d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        mMode = PickModeFromBitrate(bitrate);
91d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    } else {
92d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        mMode = MR475;
93d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
94d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
95d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    return OK;
96d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
97d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
98d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberstatus_t AMRNBEncoder::stop() {
99d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK(mStarted);
100d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
101d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (mInputBuffer) {
102d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        mInputBuffer->release();
103d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        mInputBuffer = NULL;
104d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
105d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
106d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    delete mBufferGroup;
107d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mBufferGroup = NULL;
108d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
109d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mSource->stop();
110d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
111d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    AMREncodeExit(&mEncState, &mSidState);
112d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mEncState = mSidState = NULL;
113d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
114d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mStarted = false;
115d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
116d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    return OK;
117d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
118d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
119d49b526dd2009270cb15f7fe4e70b74673950608Andreas Hubersp<MetaData> AMRNBEncoder::getFormat() {
120d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    sp<MetaData> srcFormat = mSource->getFormat();
121d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
122d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    int32_t numChannels;
123d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    int32_t sampleRate;
124d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
125d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK(srcFormat->findInt32(kKeyChannelCount, &numChannels));
126d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK_EQ(numChannels, 1);
127d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
128d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
129d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK_EQ(sampleRate, kSampleRate);
130d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
131d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    sp<MetaData> meta = new MetaData;
132d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
133d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    meta->setInt32(kKeyChannelCount, numChannels);
134d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    meta->setInt32(kKeySampleRate, sampleRate);
135d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
136d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    int64_t durationUs;
137d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
138d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        meta->setInt64(kKeyDuration, durationUs);
139d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
140d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
1417167472d843335f05fd7c9db2d44277677976097Andreas Huber    meta->setCString(kKeyDecoderComponent, "AMRNBEncoder");
1427167472d843335f05fd7c9db2d44277677976097Andreas Huber
143d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    return meta;
144d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
145d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
146d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huberstatus_t AMRNBEncoder::read(
147d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        MediaBuffer **out, const ReadOptions *options) {
148d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    status_t err;
149d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
150d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    *out = NULL;
151d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
152d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    int64_t seekTimeUs;
153d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK(options == NULL || !options->getSeekTo(&seekTimeUs));
154d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
155d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    while (mNumInputSamples < kNumSamplesPerFrame) {
156d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        if (mInputBuffer == NULL) {
157d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            err = mSource->read(&mInputBuffer, options);
158d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
159d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            if (err != OK) {
160d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                if (mNumInputSamples == 0) {
161d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                    return ERROR_END_OF_STREAM;
162d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                }
163d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                memset(&mInputFrame[mNumInputSamples],
164d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                       0,
165d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                       sizeof(int16_t)
166d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                            * (kNumSamplesPerFrame - mNumInputSamples));
167d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                mNumInputSamples = kNumSamplesPerFrame;
168d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                break;
169d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            }
170d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
171d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            size_t align = mInputBuffer->range_length() % sizeof(int16_t);
172d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            CHECK_EQ(align, 0);
173d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
174d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            int64_t timeUs;
175d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
176d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                mAnchorTimeUs = timeUs;
177d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                mNumFramesOutput = 0;
178d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            }
179d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
180d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
181d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        size_t copy =
182d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
183d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
184d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        if (copy > mInputBuffer->range_length()) {
185d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            copy = mInputBuffer->range_length();
186d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
187d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
188d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        memcpy(&mInputFrame[mNumInputSamples],
189d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber               (const uint8_t *)mInputBuffer->data()
190d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                    + mInputBuffer->range_offset(),
191d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber               copy);
192d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
193d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        mNumInputSamples += copy / sizeof(int16_t);
194d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
195d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        mInputBuffer->set_range(
196d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                mInputBuffer->range_offset() + copy,
197d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber                mInputBuffer->range_length() - copy);
198d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
199d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        if (mInputBuffer->range_length() == 0) {
200d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            mInputBuffer->release();
201d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            mInputBuffer = NULL;
202d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber        }
203d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    }
204d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
205d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    MediaBuffer *buffer;
206d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
207d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
208d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    uint8_t *outPtr = (uint8_t *)buffer->data();
209d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
210d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    Frame_Type_3GPP frameType;
211d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    int res = AMREncode(
212d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            mEncState, mSidState, (Mode)mMode,
213d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            mInputFrame, outPtr, &frameType, AMR_TX_WMF);
214d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
215d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK(res >= 0);
216d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    CHECK((size_t)res < buffer->size());
217d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
218d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // Convert header byte from WMF to IETF format.
219d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    outPtr[0] = ((outPtr[0] << 3) | 4) & 0x7c;
220d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
221d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    buffer->set_range(0, res);
222d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
223d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    // Each frame of 160 samples is 20ms long.
224d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    buffer->meta_data()->setInt64(
225d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber            kKeyTime, mAnchorTimeUs + mNumFramesOutput * 20000);
226d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
227d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    ++mNumFramesOutput;
228d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
229d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    *out = buffer;
230d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
231d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    mNumInputSamples = 0;
232d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
233d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber    return OK;
234d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}
235d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber
236d49b526dd2009270cb15f7fe4e70b74673950608Andreas Huber}  // namespace android
237