MediaCodec.cpp revision 9d73ec661e34f91f8d80a11cc5208a23997b75a0
1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "MediaCodec"
19#include <inttypes.h>
20
21#include "include/avc_utils.h"
22#include "include/SoftwareRenderer.h"
23
24#include <binder/IMemory.h>
25#include <binder/IPCThreadState.h>
26#include <binder/IServiceManager.h>
27#include <binder/MemoryDealer.h>
28#include <gui/BufferQueue.h>
29#include <gui/Surface.h>
30#include <media/ICrypto.h>
31#include <media/IOMX.h>
32#include <media/IResourceManagerService.h>
33#include <media/stagefright/foundation/ABuffer.h>
34#include <media/stagefright/foundation/ADebug.h>
35#include <media/stagefright/foundation/AMessage.h>
36#include <media/stagefright/foundation/AString.h>
37#include <media/stagefright/foundation/hexdump.h>
38#include <media/stagefright/ACodec.h>
39#include <media/stagefright/BufferProducerWrapper.h>
40#include <media/stagefright/MediaCodec.h>
41#include <media/stagefright/MediaCodecList.h>
42#include <media/stagefright/MediaDefs.h>
43#include <media/stagefright/MediaErrors.h>
44#include <media/stagefright/MediaFilter.h>
45#include <media/stagefright/MetaData.h>
46#include <media/stagefright/OMXClient.h>
47#include <media/stagefright/PersistentSurface.h>
48#include <media/stagefright/SurfaceUtils.h>
49#include <mediautils/BatteryNotifier.h>
50#include <private/android_filesystem_config.h>
51#include <utils/Log.h>
52#include <utils/Singleton.h>
53
54namespace android {
55
56static int64_t getId(sp<IResourceManagerClient> client) {
57    return (int64_t) client.get();
58}
59
60static bool isResourceError(status_t err) {
61    return (err == NO_MEMORY);
62}
63
64static const int kMaxRetry = 2;
65static const int kMaxReclaimWaitTimeInUs = 500000;  // 0.5s
66
67struct ResourceManagerClient : public BnResourceManagerClient {
68    ResourceManagerClient(MediaCodec* codec) : mMediaCodec(codec) {}
69
70    virtual bool reclaimResource() {
71        sp<MediaCodec> codec = mMediaCodec.promote();
72        if (codec == NULL) {
73            // codec is already gone.
74            return true;
75        }
76        status_t err = codec->reclaim();
77        if (err == WOULD_BLOCK) {
78            ALOGD("Wait for the client to release codec.");
79            usleep(kMaxReclaimWaitTimeInUs);
80            ALOGD("Try to reclaim again.");
81            err = codec->reclaim(true /* force */);
82        }
83        if (err != OK) {
84            ALOGW("ResourceManagerClient failed to release codec with err %d", err);
85        }
86        return (err == OK);
87    }
88
89    virtual String8 getName() {
90        String8 ret;
91        sp<MediaCodec> codec = mMediaCodec.promote();
92        if (codec == NULL) {
93            // codec is already gone.
94            return ret;
95        }
96
97        AString name;
98        if (codec->getName(&name) == OK) {
99            ret.setTo(name.c_str());
100        }
101        return ret;
102    }
103
104protected:
105    virtual ~ResourceManagerClient() {}
106
107private:
108    wp<MediaCodec> mMediaCodec;
109
110    DISALLOW_EVIL_CONSTRUCTORS(ResourceManagerClient);
111};
112
113MediaCodec::ResourceManagerServiceProxy::ResourceManagerServiceProxy(pid_t pid)
114        : mPid(pid) {
115    if (mPid == MediaCodec::kNoPid) {
116        mPid = IPCThreadState::self()->getCallingPid();
117    }
118}
119
120MediaCodec::ResourceManagerServiceProxy::~ResourceManagerServiceProxy() {
121    if (mService != NULL) {
122        IInterface::asBinder(mService)->unlinkToDeath(this);
123    }
124}
125
126void MediaCodec::ResourceManagerServiceProxy::init() {
127    sp<IServiceManager> sm = defaultServiceManager();
128    sp<IBinder> binder = sm->getService(String16("media.resource_manager"));
129    mService = interface_cast<IResourceManagerService>(binder);
130    if (mService == NULL) {
131        ALOGE("Failed to get ResourceManagerService");
132        return;
133    }
134    IInterface::asBinder(mService)->linkToDeath(this);
135}
136
137void MediaCodec::ResourceManagerServiceProxy::binderDied(const wp<IBinder>& /*who*/) {
138    ALOGW("ResourceManagerService died.");
139    Mutex::Autolock _l(mLock);
140    mService.clear();
141}
142
143void MediaCodec::ResourceManagerServiceProxy::addResource(
144        int64_t clientId,
145        const sp<IResourceManagerClient> client,
146        const Vector<MediaResource> &resources) {
147    Mutex::Autolock _l(mLock);
148    if (mService == NULL) {
149        return;
150    }
151    mService->addResource(mPid, clientId, client, resources);
152}
153
154void MediaCodec::ResourceManagerServiceProxy::removeResource(int64_t clientId) {
155    Mutex::Autolock _l(mLock);
156    if (mService == NULL) {
157        return;
158    }
159    mService->removeResource(mPid, clientId);
160}
161
162bool MediaCodec::ResourceManagerServiceProxy::reclaimResource(
163        const Vector<MediaResource> &resources) {
164    Mutex::Autolock _l(mLock);
165    if (mService == NULL) {
166        return false;
167    }
168    return mService->reclaimResource(mPid, resources);
169}
170
171// static
172sp<MediaCodec> MediaCodec::CreateByType(
173        const sp<ALooper> &looper, const AString &mime, bool encoder, status_t *err, pid_t pid) {
174    sp<MediaCodec> codec = new MediaCodec(looper, pid);
175
176    const status_t ret = codec->init(mime, true /* nameIsType */, encoder);
177    if (err != NULL) {
178        *err = ret;
179    }
180    return ret == OK ? codec : NULL; // NULL deallocates codec.
181}
182
183// static
184sp<MediaCodec> MediaCodec::CreateByComponentName(
185        const sp<ALooper> &looper, const AString &name, status_t *err, pid_t pid) {
186    sp<MediaCodec> codec = new MediaCodec(looper, pid);
187
188    const status_t ret = codec->init(name, false /* nameIsType */, false /* encoder */);
189    if (err != NULL) {
190        *err = ret;
191    }
192    return ret == OK ? codec : NULL; // NULL deallocates codec.
193}
194
195// static
196sp<PersistentSurface> MediaCodec::CreatePersistentInputSurface() {
197    OMXClient client;
198    CHECK_EQ(client.connect(), (status_t)OK);
199    sp<IOMX> omx = client.interface();
200
201    const sp<IMediaCodecList> mediaCodecList = MediaCodecList::getInstance();
202    if (mediaCodecList == NULL) {
203        ALOGE("Failed to obtain MediaCodecList!");
204        return NULL; // if called from Java should raise IOException
205    }
206
207    AString tmp;
208    sp<AMessage> globalSettings = mediaCodecList->getGlobalSettings();
209    if (globalSettings == NULL || !globalSettings->findString(
210            kMaxEncoderInputBuffers, &tmp)) {
211        ALOGE("Failed to get encoder input buffer count!");
212        return NULL;
213    }
214
215    int32_t bufferCount = strtol(tmp.c_str(), NULL, 10);
216    if (bufferCount <= 0
217            || bufferCount > BufferQueue::MAX_MAX_ACQUIRED_BUFFERS) {
218        ALOGE("Encoder input buffer count is invalid!");
219        return NULL;
220    }
221
222    sp<IGraphicBufferProducer> bufferProducer;
223    sp<IGraphicBufferConsumer> bufferConsumer;
224
225    status_t err = omx->createPersistentInputSurface(
226            &bufferProducer, &bufferConsumer);
227
228    if (err != OK) {
229        ALOGE("Failed to create persistent input surface.");
230        return NULL;
231    }
232
233    err = bufferConsumer->setMaxAcquiredBufferCount(bufferCount);
234
235    if (err != NO_ERROR) {
236        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
237                bufferCount, err);
238        return NULL;
239    }
240
241    return new PersistentSurface(bufferProducer, bufferConsumer);
242}
243
244MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid)
245    : mState(UNINITIALIZED),
246      mReleasedByResourceManager(false),
247      mLooper(looper),
248      mCodec(NULL),
249      mReplyID(0),
250      mFlags(0),
251      mStickyError(OK),
252      mSoftRenderer(NULL),
253      mResourceManagerClient(new ResourceManagerClient(this)),
254      mResourceManagerService(new ResourceManagerServiceProxy(pid)),
255      mBatteryStatNotified(false),
256      mIsVideo(false),
257      mVideoWidth(0),
258      mVideoHeight(0),
259      mRotationDegrees(0),
260      mDequeueInputTimeoutGeneration(0),
261      mDequeueInputReplyID(0),
262      mDequeueOutputTimeoutGeneration(0),
263      mDequeueOutputReplyID(0),
264      mHaveInputSurface(false),
265      mHavePendingInputBuffers(false) {
266}
267
268MediaCodec::~MediaCodec() {
269    CHECK_EQ(mState, UNINITIALIZED);
270    mResourceManagerService->removeResource(getId(mResourceManagerClient));
271}
272
273// static
274status_t MediaCodec::PostAndAwaitResponse(
275        const sp<AMessage> &msg, sp<AMessage> *response) {
276    status_t err = msg->postAndAwaitResponse(response);
277
278    if (err != OK) {
279        return err;
280    }
281
282    if (!(*response)->findInt32("err", &err)) {
283        err = OK;
284    }
285
286    return err;
287}
288
289void MediaCodec::PostReplyWithError(const sp<AReplyToken> &replyID, int32_t err) {
290    int32_t finalErr = err;
291    if (mReleasedByResourceManager) {
292        // override the err code if MediaCodec has been released by ResourceManager.
293        finalErr = DEAD_OBJECT;
294    }
295
296    sp<AMessage> response = new AMessage;
297    response->setInt32("err", finalErr);
298    response->postReply(replyID);
299}
300
301status_t MediaCodec::init(const AString &name, bool nameIsType, bool encoder) {
302    mResourceManagerService->init();
303
304    // save init parameters for reset
305    mInitName = name;
306    mInitNameIsType = nameIsType;
307    mInitIsEncoder = encoder;
308
309    // Current video decoders do not return from OMX_FillThisBuffer
310    // quickly, violating the OpenMAX specs, until that is remedied
311    // we need to invest in an extra looper to free the main event
312    // queue.
313
314    if (nameIsType || !strncasecmp(name.c_str(), "omx.", 4)) {
315        mCodec = new ACodec;
316    } else if (!nameIsType
317            && !strncasecmp(name.c_str(), "android.filter.", 15)) {
318        mCodec = new MediaFilter;
319    } else {
320        return NAME_NOT_FOUND;
321    }
322
323    bool secureCodec = false;
324    if (nameIsType && !strncasecmp(name.c_str(), "video/", 6)) {
325        mIsVideo = true;
326    } else {
327        AString tmp = name;
328        if (tmp.endsWith(".secure")) {
329            secureCodec = true;
330            tmp.erase(tmp.size() - 7, 7);
331        }
332        const sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
333        if (mcl == NULL) {
334            mCodec = NULL;  // remove the codec.
335            return NO_INIT; // if called from Java should raise IOException
336        }
337        ssize_t codecIdx = mcl->findCodecByName(tmp.c_str());
338        if (codecIdx >= 0) {
339            const sp<MediaCodecInfo> info = mcl->getCodecInfo(codecIdx);
340            Vector<AString> mimes;
341            info->getSupportedMimes(&mimes);
342            for (size_t i = 0; i < mimes.size(); i++) {
343                if (mimes[i].startsWith("video/")) {
344                    mIsVideo = true;
345                    break;
346                }
347            }
348        }
349    }
350
351    if (mIsVideo) {
352        // video codec needs dedicated looper
353        if (mCodecLooper == NULL) {
354            mCodecLooper = new ALooper;
355            mCodecLooper->setName("CodecLooper");
356            mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO);
357        }
358
359        mCodecLooper->registerHandler(mCodec);
360    } else {
361        mLooper->registerHandler(mCodec);
362    }
363
364    mLooper->registerHandler(this);
365
366    mCodec->setNotificationMessage(new AMessage(kWhatCodecNotify, this));
367
368    sp<AMessage> msg = new AMessage(kWhatInit, this);
369    msg->setString("name", name);
370    msg->setInt32("nameIsType", nameIsType);
371
372    if (nameIsType) {
373        msg->setInt32("encoder", encoder);
374    }
375
376    status_t err;
377    Vector<MediaResource> resources;
378    const char *type = secureCodec ? kResourceSecureCodec : kResourceNonSecureCodec;
379    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
380    resources.push_back(MediaResource(String8(type), String8(subtype), 1));
381    for (int i = 0; i <= kMaxRetry; ++i) {
382        if (i > 0) {
383            // Don't try to reclaim resource for the first time.
384            if (!mResourceManagerService->reclaimResource(resources)) {
385                break;
386            }
387        }
388
389        sp<AMessage> response;
390        err = PostAndAwaitResponse(msg, &response);
391        if (!isResourceError(err)) {
392            break;
393        }
394    }
395    return err;
396}
397
398status_t MediaCodec::setCallback(const sp<AMessage> &callback) {
399    sp<AMessage> msg = new AMessage(kWhatSetCallback, this);
400    msg->setMessage("callback", callback);
401
402    sp<AMessage> response;
403    return PostAndAwaitResponse(msg, &response);
404}
405
406status_t MediaCodec::setOnFrameRenderedNotification(const sp<AMessage> &notify) {
407    sp<AMessage> msg = new AMessage(kWhatSetNotification, this);
408    msg->setMessage("on-frame-rendered", notify);
409    return msg->post();
410}
411
412status_t MediaCodec::configure(
413        const sp<AMessage> &format,
414        const sp<Surface> &surface,
415        const sp<ICrypto> &crypto,
416        uint32_t flags) {
417    sp<AMessage> msg = new AMessage(kWhatConfigure, this);
418
419    if (mIsVideo) {
420        format->findInt32("width", &mVideoWidth);
421        format->findInt32("height", &mVideoHeight);
422        if (!format->findInt32("rotation-degrees", &mRotationDegrees)) {
423            mRotationDegrees = 0;
424        }
425    }
426
427    msg->setMessage("format", format);
428    msg->setInt32("flags", flags);
429    msg->setObject("surface", surface);
430
431    if (crypto != NULL) {
432        msg->setPointer("crypto", crypto.get());
433    }
434
435    // save msg for reset
436    mConfigureMsg = msg;
437
438    status_t err;
439    Vector<MediaResource> resources;
440    const char *type = (mFlags & kFlagIsSecure) ?
441            kResourceSecureCodec : kResourceNonSecureCodec;
442    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
443    resources.push_back(MediaResource(String8(type), String8(subtype), 1));
444    // Don't know the buffer size at this point, but it's fine to use 1 because
445    // the reclaimResource call doesn't consider the requester's buffer size for now.
446    resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));
447    for (int i = 0; i <= kMaxRetry; ++i) {
448        if (i > 0) {
449            // Don't try to reclaim resource for the first time.
450            if (!mResourceManagerService->reclaimResource(resources)) {
451                break;
452            }
453        }
454
455        sp<AMessage> response;
456        err = PostAndAwaitResponse(msg, &response);
457        if (err != OK && err != INVALID_OPERATION) {
458            // MediaCodec now set state to UNINITIALIZED upon any fatal error.
459            // To maintain backward-compatibility, do a reset() to put codec
460            // back into INITIALIZED state.
461            // But don't reset if the err is INVALID_OPERATION, which means
462            // the configure failure is due to wrong state.
463
464            ALOGE("configure failed with err 0x%08x, resetting...", err);
465            reset();
466        }
467        if (!isResourceError(err)) {
468            break;
469        }
470    }
471    return err;
472}
473
474status_t MediaCodec::setInputSurface(
475        const sp<PersistentSurface> &surface) {
476    sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
477    msg->setObject("input-surface", surface.get());
478
479    sp<AMessage> response;
480    return PostAndAwaitResponse(msg, &response);
481}
482
483status_t MediaCodec::setSurface(const sp<Surface> &surface) {
484    sp<AMessage> msg = new AMessage(kWhatSetSurface, this);
485    msg->setObject("surface", surface);
486
487    sp<AMessage> response;
488    return PostAndAwaitResponse(msg, &response);
489}
490
491status_t MediaCodec::createInputSurface(
492        sp<IGraphicBufferProducer>* bufferProducer) {
493    sp<AMessage> msg = new AMessage(kWhatCreateInputSurface, this);
494
495    sp<AMessage> response;
496    status_t err = PostAndAwaitResponse(msg, &response);
497    if (err == NO_ERROR) {
498        // unwrap the sp<IGraphicBufferProducer>
499        sp<RefBase> obj;
500        bool found = response->findObject("input-surface", &obj);
501        CHECK(found);
502        sp<BufferProducerWrapper> wrapper(
503                static_cast<BufferProducerWrapper*>(obj.get()));
504        *bufferProducer = wrapper->getBufferProducer();
505    } else {
506        ALOGW("createInputSurface failed, err=%d", err);
507    }
508    return err;
509}
510
511uint64_t MediaCodec::getGraphicBufferSize() {
512    if (!mIsVideo) {
513        return 0;
514    }
515
516    uint64_t size = 0;
517    size_t portNum = sizeof(mPortBuffers) / sizeof((mPortBuffers)[0]);
518    for (size_t i = 0; i < portNum; ++i) {
519        // TODO: this is just an estimation, we should get the real buffer size from ACodec.
520        size += mPortBuffers[i].size() * mVideoWidth * mVideoHeight * 3 / 2;
521    }
522    return size;
523}
524
525void MediaCodec::addResource(const String8 &type, const String8 &subtype, uint64_t value) {
526    Vector<MediaResource> resources;
527    resources.push_back(MediaResource(type, subtype, value));
528    mResourceManagerService->addResource(
529            getId(mResourceManagerClient), mResourceManagerClient, resources);
530}
531
532status_t MediaCodec::start() {
533    sp<AMessage> msg = new AMessage(kWhatStart, this);
534
535    status_t err;
536    Vector<MediaResource> resources;
537    const char *type = (mFlags & kFlagIsSecure) ?
538            kResourceSecureCodec : kResourceNonSecureCodec;
539    const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
540    resources.push_back(MediaResource(String8(type), String8(subtype), 1));
541    // Don't know the buffer size at this point, but it's fine to use 1 because
542    // the reclaimResource call doesn't consider the requester's buffer size for now.
543    resources.push_back(MediaResource(String8(kResourceGraphicMemory), 1));
544    for (int i = 0; i <= kMaxRetry; ++i) {
545        if (i > 0) {
546            // Don't try to reclaim resource for the first time.
547            if (!mResourceManagerService->reclaimResource(resources)) {
548                break;
549            }
550            // Recover codec from previous error before retry start.
551            err = reset();
552            if (err != OK) {
553                ALOGE("retrying start: failed to reset codec");
554                break;
555            }
556            sp<AMessage> response;
557            err = PostAndAwaitResponse(mConfigureMsg, &response);
558            if (err != OK) {
559                ALOGE("retrying start: failed to configure codec");
560                break;
561            }
562        }
563
564        sp<AMessage> response;
565        err = PostAndAwaitResponse(msg, &response);
566        if (!isResourceError(err)) {
567            break;
568        }
569    }
570    return err;
571}
572
573status_t MediaCodec::stop() {
574    sp<AMessage> msg = new AMessage(kWhatStop, this);
575
576    sp<AMessage> response;
577    return PostAndAwaitResponse(msg, &response);
578}
579
580bool MediaCodec::hasPendingBuffer(int portIndex) {
581    const Vector<BufferInfo> &buffers = mPortBuffers[portIndex];
582    for (size_t i = 0; i < buffers.size(); ++i) {
583        const BufferInfo &info = buffers.itemAt(i);
584        if (info.mOwnedByClient) {
585            return true;
586        }
587    }
588    return false;
589}
590
591bool MediaCodec::hasPendingBuffer() {
592    return hasPendingBuffer(kPortIndexInput) || hasPendingBuffer(kPortIndexOutput);
593}
594
595status_t MediaCodec::reclaim(bool force) {
596    ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
597    sp<AMessage> msg = new AMessage(kWhatRelease, this);
598    msg->setInt32("reclaimed", 1);
599    msg->setInt32("force", force ? 1 : 0);
600
601    sp<AMessage> response;
602    status_t ret = PostAndAwaitResponse(msg, &response);
603    if (ret == -ENOENT) {
604        ALOGD("MediaCodec looper is gone, skip reclaim");
605        ret = OK;
606    }
607    return ret;
608}
609
610status_t MediaCodec::release() {
611    sp<AMessage> msg = new AMessage(kWhatRelease, this);
612
613    sp<AMessage> response;
614    return PostAndAwaitResponse(msg, &response);
615}
616
617status_t MediaCodec::reset() {
618    /* When external-facing MediaCodec object is created,
619       it is already initialized.  Thus, reset is essentially
620       release() followed by init(), plus clearing the state */
621
622    status_t err = release();
623
624    // unregister handlers
625    if (mCodec != NULL) {
626        if (mCodecLooper != NULL) {
627            mCodecLooper->unregisterHandler(mCodec->id());
628        } else {
629            mLooper->unregisterHandler(mCodec->id());
630        }
631        mCodec = NULL;
632    }
633    mLooper->unregisterHandler(id());
634
635    mFlags = 0;    // clear all flags
636    mStickyError = OK;
637
638    // reset state not reset by setState(UNINITIALIZED)
639    mReplyID = 0;
640    mDequeueInputReplyID = 0;
641    mDequeueOutputReplyID = 0;
642    mDequeueInputTimeoutGeneration = 0;
643    mDequeueOutputTimeoutGeneration = 0;
644    mHaveInputSurface = false;
645
646    if (err == OK) {
647        err = init(mInitName, mInitNameIsType, mInitIsEncoder);
648    }
649    return err;
650}
651
652status_t MediaCodec::queueInputBuffer(
653        size_t index,
654        size_t offset,
655        size_t size,
656        int64_t presentationTimeUs,
657        uint32_t flags,
658        AString *errorDetailMsg) {
659    if (errorDetailMsg != NULL) {
660        errorDetailMsg->clear();
661    }
662
663    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
664    msg->setSize("index", index);
665    msg->setSize("offset", offset);
666    msg->setSize("size", size);
667    msg->setInt64("timeUs", presentationTimeUs);
668    msg->setInt32("flags", flags);
669    msg->setPointer("errorDetailMsg", errorDetailMsg);
670
671    sp<AMessage> response;
672    return PostAndAwaitResponse(msg, &response);
673}
674
675status_t MediaCodec::queueSecureInputBuffer(
676        size_t index,
677        size_t offset,
678        const CryptoPlugin::SubSample *subSamples,
679        size_t numSubSamples,
680        const uint8_t key[16],
681        const uint8_t iv[16],
682        CryptoPlugin::Mode mode,
683        int64_t presentationTimeUs,
684        uint32_t flags,
685        AString *errorDetailMsg) {
686    if (errorDetailMsg != NULL) {
687        errorDetailMsg->clear();
688    }
689
690    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
691    msg->setSize("index", index);
692    msg->setSize("offset", offset);
693    msg->setPointer("subSamples", (void *)subSamples);
694    msg->setSize("numSubSamples", numSubSamples);
695    msg->setPointer("key", (void *)key);
696    msg->setPointer("iv", (void *)iv);
697    msg->setInt32("mode", mode);
698    msg->setInt64("timeUs", presentationTimeUs);
699    msg->setInt32("flags", flags);
700    msg->setPointer("errorDetailMsg", errorDetailMsg);
701
702    sp<AMessage> response;
703    status_t err = PostAndAwaitResponse(msg, &response);
704
705    return err;
706}
707
708status_t MediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
709    sp<AMessage> msg = new AMessage(kWhatDequeueInputBuffer, this);
710    msg->setInt64("timeoutUs", timeoutUs);
711
712    sp<AMessage> response;
713    status_t err;
714    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
715        return err;
716    }
717
718    CHECK(response->findSize("index", index));
719
720    return OK;
721}
722
723status_t MediaCodec::dequeueOutputBuffer(
724        size_t *index,
725        size_t *offset,
726        size_t *size,
727        int64_t *presentationTimeUs,
728        uint32_t *flags,
729        int64_t timeoutUs) {
730    sp<AMessage> msg = new AMessage(kWhatDequeueOutputBuffer, this);
731    msg->setInt64("timeoutUs", timeoutUs);
732
733    sp<AMessage> response;
734    status_t err;
735    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
736        return err;
737    }
738
739    CHECK(response->findSize("index", index));
740    CHECK(response->findSize("offset", offset));
741    CHECK(response->findSize("size", size));
742    CHECK(response->findInt64("timeUs", presentationTimeUs));
743    CHECK(response->findInt32("flags", (int32_t *)flags));
744
745    return OK;
746}
747
748status_t MediaCodec::renderOutputBufferAndRelease(size_t index) {
749    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
750    msg->setSize("index", index);
751    msg->setInt32("render", true);
752
753    sp<AMessage> response;
754    return PostAndAwaitResponse(msg, &response);
755}
756
757status_t MediaCodec::renderOutputBufferAndRelease(size_t index, int64_t timestampNs) {
758    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
759    msg->setSize("index", index);
760    msg->setInt32("render", true);
761    msg->setInt64("timestampNs", timestampNs);
762
763    sp<AMessage> response;
764    return PostAndAwaitResponse(msg, &response);
765}
766
767status_t MediaCodec::releaseOutputBuffer(size_t index) {
768    sp<AMessage> msg = new AMessage(kWhatReleaseOutputBuffer, this);
769    msg->setSize("index", index);
770
771    sp<AMessage> response;
772    return PostAndAwaitResponse(msg, &response);
773}
774
775status_t MediaCodec::signalEndOfInputStream() {
776    sp<AMessage> msg = new AMessage(kWhatSignalEndOfInputStream, this);
777
778    sp<AMessage> response;
779    return PostAndAwaitResponse(msg, &response);
780}
781
782status_t MediaCodec::getOutputFormat(sp<AMessage> *format) const {
783    sp<AMessage> msg = new AMessage(kWhatGetOutputFormat, this);
784
785    sp<AMessage> response;
786    status_t err;
787    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
788        return err;
789    }
790
791    CHECK(response->findMessage("format", format));
792
793    return OK;
794}
795
796status_t MediaCodec::getInputFormat(sp<AMessage> *format) const {
797    sp<AMessage> msg = new AMessage(kWhatGetInputFormat, this);
798
799    sp<AMessage> response;
800    status_t err;
801    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
802        return err;
803    }
804
805    CHECK(response->findMessage("format", format));
806
807    return OK;
808}
809
810status_t MediaCodec::getName(AString *name) const {
811    sp<AMessage> msg = new AMessage(kWhatGetName, this);
812
813    sp<AMessage> response;
814    status_t err;
815    if ((err = PostAndAwaitResponse(msg, &response)) != OK) {
816        return err;
817    }
818
819    CHECK(response->findString("name", name));
820
821    return OK;
822}
823
824status_t MediaCodec::getWidevineLegacyBuffers(Vector<sp<ABuffer> > *buffers) const {
825    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
826    msg->setInt32("portIndex", kPortIndexInput);
827    msg->setPointer("buffers", buffers);
828    msg->setInt32("widevine", true);
829
830    sp<AMessage> response;
831    return PostAndAwaitResponse(msg, &response);
832}
833
834status_t MediaCodec::getInputBuffers(Vector<sp<ABuffer> > *buffers) const {
835    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
836    msg->setInt32("portIndex", kPortIndexInput);
837    msg->setPointer("buffers", buffers);
838
839    sp<AMessage> response;
840    return PostAndAwaitResponse(msg, &response);
841}
842
843status_t MediaCodec::getOutputBuffers(Vector<sp<ABuffer> > *buffers) const {
844    sp<AMessage> msg = new AMessage(kWhatGetBuffers, this);
845    msg->setInt32("portIndex", kPortIndexOutput);
846    msg->setPointer("buffers", buffers);
847
848    sp<AMessage> response;
849    return PostAndAwaitResponse(msg, &response);
850}
851
852status_t MediaCodec::getOutputBuffer(size_t index, sp<ABuffer> *buffer) {
853    sp<AMessage> format;
854    return getBufferAndFormat(kPortIndexOutput, index, buffer, &format);
855}
856
857status_t MediaCodec::getOutputFormat(size_t index, sp<AMessage> *format) {
858    sp<ABuffer> buffer;
859    return getBufferAndFormat(kPortIndexOutput, index, &buffer, format);
860}
861
862status_t MediaCodec::getInputBuffer(size_t index, sp<ABuffer> *buffer) {
863    sp<AMessage> format;
864    return getBufferAndFormat(kPortIndexInput, index, buffer, &format);
865}
866
867bool MediaCodec::isExecuting() const {
868    return mState == STARTED || mState == FLUSHED;
869}
870
871status_t MediaCodec::getBufferAndFormat(
872        size_t portIndex, size_t index,
873        sp<ABuffer> *buffer, sp<AMessage> *format) {
874    // use mutex instead of a context switch
875
876    if (mReleasedByResourceManager) {
877        return DEAD_OBJECT;
878    }
879
880    buffer->clear();
881    format->clear();
882    if (!isExecuting()) {
883        return INVALID_OPERATION;
884    }
885
886    // we do not want mPortBuffers to change during this section
887    // we also don't want mOwnedByClient to change during this
888    Mutex::Autolock al(mBufferLock);
889    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
890    if (index < buffers->size()) {
891        const BufferInfo &info = buffers->itemAt(index);
892        if (info.mOwnedByClient) {
893            // by the time buffers array is initialized, crypto is set
894            if (portIndex == kPortIndexInput && mCrypto != NULL) {
895                *buffer = info.mEncryptedData;
896            } else {
897                *buffer = info.mData;
898            }
899            *format = info.mFormat;
900        }
901    }
902    return OK;
903}
904
905status_t MediaCodec::flush() {
906    sp<AMessage> msg = new AMessage(kWhatFlush, this);
907
908    sp<AMessage> response;
909    return PostAndAwaitResponse(msg, &response);
910}
911
912status_t MediaCodec::requestIDRFrame() {
913    (new AMessage(kWhatRequestIDRFrame, this))->post();
914
915    return OK;
916}
917
918void MediaCodec::requestActivityNotification(const sp<AMessage> &notify) {
919    sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, this);
920    msg->setMessage("notify", notify);
921    msg->post();
922}
923
924////////////////////////////////////////////////////////////////////////////////
925
926void MediaCodec::cancelPendingDequeueOperations() {
927    if (mFlags & kFlagDequeueInputPending) {
928        PostReplyWithError(mDequeueInputReplyID, INVALID_OPERATION);
929
930        ++mDequeueInputTimeoutGeneration;
931        mDequeueInputReplyID = 0;
932        mFlags &= ~kFlagDequeueInputPending;
933    }
934
935    if (mFlags & kFlagDequeueOutputPending) {
936        PostReplyWithError(mDequeueOutputReplyID, INVALID_OPERATION);
937
938        ++mDequeueOutputTimeoutGeneration;
939        mDequeueOutputReplyID = 0;
940        mFlags &= ~kFlagDequeueOutputPending;
941    }
942}
943
944bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
945    if (!isExecuting() || (mFlags & kFlagIsAsync)
946            || (newRequest && (mFlags & kFlagDequeueInputPending))) {
947        PostReplyWithError(replyID, INVALID_OPERATION);
948        return true;
949    } else if (mFlags & kFlagStickyError) {
950        PostReplyWithError(replyID, getStickyError());
951        return true;
952    }
953
954    ssize_t index = dequeuePortBuffer(kPortIndexInput);
955
956    if (index < 0) {
957        CHECK_EQ(index, -EAGAIN);
958        return false;
959    }
960
961    sp<AMessage> response = new AMessage;
962    response->setSize("index", index);
963    response->postReply(replyID);
964
965    return true;
966}
967
968bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
969    if (!isExecuting() || (mFlags & kFlagIsAsync)
970            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
971        PostReplyWithError(replyID, INVALID_OPERATION);
972    } else if (mFlags & kFlagStickyError) {
973        PostReplyWithError(replyID, getStickyError());
974    } else if (mFlags & kFlagOutputBuffersChanged) {
975        PostReplyWithError(replyID, INFO_OUTPUT_BUFFERS_CHANGED);
976        mFlags &= ~kFlagOutputBuffersChanged;
977    } else if (mFlags & kFlagOutputFormatChanged) {
978        PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
979        mFlags &= ~kFlagOutputFormatChanged;
980    } else {
981        sp<AMessage> response = new AMessage;
982        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
983
984        if (index < 0) {
985            CHECK_EQ(index, -EAGAIN);
986            return false;
987        }
988
989        const sp<ABuffer> &buffer =
990            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
991
992        response->setSize("index", index);
993        response->setSize("offset", buffer->offset());
994        response->setSize("size", buffer->size());
995
996        int64_t timeUs;
997        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
998
999        response->setInt64("timeUs", timeUs);
1000
1001        int32_t omxFlags;
1002        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
1003
1004        uint32_t flags = 0;
1005        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
1006            flags |= BUFFER_FLAG_SYNCFRAME;
1007        }
1008        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1009            flags |= BUFFER_FLAG_CODECCONFIG;
1010        }
1011        if (omxFlags & OMX_BUFFERFLAG_EOS) {
1012            flags |= BUFFER_FLAG_EOS;
1013        }
1014
1015        response->setInt32("flags", flags);
1016        response->postReply(replyID);
1017    }
1018
1019    return true;
1020}
1021
1022void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
1023    switch (msg->what()) {
1024        case kWhatCodecNotify:
1025        {
1026            int32_t what;
1027            CHECK(msg->findInt32("what", &what));
1028
1029            switch (what) {
1030                case CodecBase::kWhatError:
1031                {
1032                    int32_t err, actionCode;
1033                    CHECK(msg->findInt32("err", &err));
1034                    CHECK(msg->findInt32("actionCode", &actionCode));
1035
1036                    ALOGE("Codec reported err %#x, actionCode %d, while in state %d",
1037                            err, actionCode, mState);
1038                    if (err == DEAD_OBJECT) {
1039                        mFlags |= kFlagSawMediaServerDie;
1040                        mFlags &= ~kFlagIsComponentAllocated;
1041                    }
1042
1043                    bool sendErrorResponse = true;
1044
1045                    switch (mState) {
1046                        case INITIALIZING:
1047                        {
1048                            setState(UNINITIALIZED);
1049                            break;
1050                        }
1051
1052                        case CONFIGURING:
1053                        {
1054                            setState(actionCode == ACTION_CODE_FATAL ?
1055                                    UNINITIALIZED : INITIALIZED);
1056                            break;
1057                        }
1058
1059                        case STARTING:
1060                        {
1061                            setState(actionCode == ACTION_CODE_FATAL ?
1062                                    UNINITIALIZED : CONFIGURED);
1063                            break;
1064                        }
1065
1066                        case STOPPING:
1067                        case RELEASING:
1068                        {
1069                            // Ignore the error, assuming we'll still get
1070                            // the shutdown complete notification.
1071
1072                            sendErrorResponse = false;
1073
1074                            if (mFlags & kFlagSawMediaServerDie) {
1075                                // MediaServer died, there definitely won't
1076                                // be a shutdown complete notification after
1077                                // all.
1078
1079                                // note that we're directly going from
1080                                // STOPPING->UNINITIALIZED, instead of the
1081                                // usual STOPPING->INITIALIZED state.
1082                                setState(UNINITIALIZED);
1083                                if (mState == RELEASING) {
1084                                    mComponentName.clear();
1085                                }
1086                                (new AMessage)->postReply(mReplyID);
1087                            }
1088                            break;
1089                        }
1090
1091                        case FLUSHING:
1092                        {
1093                            if (actionCode == ACTION_CODE_FATAL) {
1094                                setState(UNINITIALIZED);
1095                            } else {
1096                                setState(
1097                                        (mFlags & kFlagIsAsync) ? FLUSHED : STARTED);
1098                            }
1099                            break;
1100                        }
1101
1102                        case FLUSHED:
1103                        case STARTED:
1104                        {
1105                            sendErrorResponse = false;
1106
1107                            setStickyError(err);
1108                            postActivityNotificationIfPossible();
1109
1110                            cancelPendingDequeueOperations();
1111
1112                            if (mFlags & kFlagIsAsync) {
1113                                onError(err, actionCode);
1114                            }
1115                            switch (actionCode) {
1116                            case ACTION_CODE_TRANSIENT:
1117                                break;
1118                            case ACTION_CODE_RECOVERABLE:
1119                                setState(INITIALIZED);
1120                                break;
1121                            default:
1122                                setState(UNINITIALIZED);
1123                                break;
1124                            }
1125                            break;
1126                        }
1127
1128                        default:
1129                        {
1130                            sendErrorResponse = false;
1131
1132                            setStickyError(err);
1133                            postActivityNotificationIfPossible();
1134
1135                            // actionCode in an uninitialized state is always fatal.
1136                            if (mState == UNINITIALIZED) {
1137                                actionCode = ACTION_CODE_FATAL;
1138                            }
1139                            if (mFlags & kFlagIsAsync) {
1140                                onError(err, actionCode);
1141                            }
1142                            switch (actionCode) {
1143                            case ACTION_CODE_TRANSIENT:
1144                                break;
1145                            case ACTION_CODE_RECOVERABLE:
1146                                setState(INITIALIZED);
1147                                break;
1148                            default:
1149                                setState(UNINITIALIZED);
1150                                break;
1151                            }
1152                            break;
1153                        }
1154                    }
1155
1156                    if (sendErrorResponse) {
1157                        PostReplyWithError(mReplyID, err);
1158                    }
1159                    break;
1160                }
1161
1162                case CodecBase::kWhatComponentAllocated:
1163                {
1164                    CHECK_EQ(mState, INITIALIZING);
1165                    setState(INITIALIZED);
1166                    mFlags |= kFlagIsComponentAllocated;
1167
1168                    CHECK(msg->findString("componentName", &mComponentName));
1169
1170                    if (mComponentName.startsWith("OMX.google.")) {
1171                        mFlags |= kFlagUsesSoftwareRenderer;
1172                    } else {
1173                        mFlags &= ~kFlagUsesSoftwareRenderer;
1174                    }
1175
1176                    String8 resourceType;
1177                    if (mComponentName.endsWith(".secure")) {
1178                        mFlags |= kFlagIsSecure;
1179                        resourceType = String8(kResourceSecureCodec);
1180                    } else {
1181                        mFlags &= ~kFlagIsSecure;
1182                        resourceType = String8(kResourceNonSecureCodec);
1183                    }
1184
1185                    if (mIsVideo) {
1186                        // audio codec is currently ignored.
1187                        addResource(resourceType, String8(kResourceVideoCodec), 1);
1188                    }
1189
1190                    (new AMessage)->postReply(mReplyID);
1191                    break;
1192                }
1193
1194                case CodecBase::kWhatComponentConfigured:
1195                {
1196                    if (mState == UNINITIALIZED || mState == INITIALIZED) {
1197                        // In case a kWhatError message came in and replied with error,
1198                        // we log a warning and ignore.
1199                        ALOGW("configure interrupted by error, current state %d", mState);
1200                        break;
1201                    }
1202                    CHECK_EQ(mState, CONFIGURING);
1203
1204                    // reset input surface flag
1205                    mHaveInputSurface = false;
1206
1207                    CHECK(msg->findMessage("input-format", &mInputFormat));
1208                    CHECK(msg->findMessage("output-format", &mOutputFormat));
1209
1210                    int32_t usingSwRenderer;
1211                    if (mOutputFormat->findInt32("using-sw-renderer", &usingSwRenderer)
1212                            && usingSwRenderer) {
1213                        mFlags |= kFlagUsesSoftwareRenderer;
1214                    }
1215                    setState(CONFIGURED);
1216                    (new AMessage)->postReply(mReplyID);
1217                    break;
1218                }
1219
1220                case CodecBase::kWhatInputSurfaceCreated:
1221                {
1222                    // response to initiateCreateInputSurface()
1223                    status_t err = NO_ERROR;
1224                    sp<AMessage> response = new AMessage;
1225                    if (!msg->findInt32("err", &err)) {
1226                        sp<RefBase> obj;
1227                        msg->findObject("input-surface", &obj);
1228                        CHECK(obj != NULL);
1229                        response->setObject("input-surface", obj);
1230                        mHaveInputSurface = true;
1231                    } else {
1232                        response->setInt32("err", err);
1233                    }
1234                    response->postReply(mReplyID);
1235                    break;
1236                }
1237
1238                case CodecBase::kWhatInputSurfaceAccepted:
1239                {
1240                    // response to initiateSetInputSurface()
1241                    status_t err = NO_ERROR;
1242                    sp<AMessage> response = new AMessage();
1243                    if (!msg->findInt32("err", &err)) {
1244                        mHaveInputSurface = true;
1245                    } else {
1246                        response->setInt32("err", err);
1247                    }
1248                    response->postReply(mReplyID);
1249                    break;
1250                }
1251
1252                case CodecBase::kWhatSignaledInputEOS:
1253                {
1254                    // response to signalEndOfInputStream()
1255                    sp<AMessage> response = new AMessage;
1256                    status_t err;
1257                    if (msg->findInt32("err", &err)) {
1258                        response->setInt32("err", err);
1259                    }
1260                    response->postReply(mReplyID);
1261                    break;
1262                }
1263
1264
1265                case CodecBase::kWhatBuffersAllocated:
1266                {
1267                    Mutex::Autolock al(mBufferLock);
1268                    int32_t portIndex;
1269                    CHECK(msg->findInt32("portIndex", &portIndex));
1270
1271                    ALOGV("%s buffers allocated",
1272                          portIndex == kPortIndexInput ? "input" : "output");
1273
1274                    CHECK(portIndex == kPortIndexInput
1275                            || portIndex == kPortIndexOutput);
1276
1277                    mPortBuffers[portIndex].clear();
1278
1279                    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
1280
1281                    sp<RefBase> obj;
1282                    CHECK(msg->findObject("portDesc", &obj));
1283
1284                    sp<CodecBase::PortDescription> portDesc =
1285                        static_cast<CodecBase::PortDescription *>(obj.get());
1286
1287                    size_t numBuffers = portDesc->countBuffers();
1288
1289                    size_t totalSize = 0;
1290                    for (size_t i = 0; i < numBuffers; ++i) {
1291                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1292                            totalSize += portDesc->bufferAt(i)->capacity();
1293                        }
1294                    }
1295
1296                    if (totalSize) {
1297                        mDealer = new MemoryDealer(totalSize, "MediaCodec");
1298                    }
1299
1300                    for (size_t i = 0; i < numBuffers; ++i) {
1301                        BufferInfo info;
1302                        info.mBufferID = portDesc->bufferIDAt(i);
1303                        info.mOwnedByClient = false;
1304                        info.mData = portDesc->bufferAt(i);
1305
1306                        if (portIndex == kPortIndexInput && mCrypto != NULL) {
1307                            sp<IMemory> mem = mDealer->allocate(info.mData->capacity());
1308                            info.mEncryptedData =
1309                                new ABuffer(mem->pointer(), info.mData->capacity());
1310                            info.mSharedEncryptedBuffer = mem;
1311                        }
1312
1313                        buffers->push_back(info);
1314                    }
1315
1316                    if (portIndex == kPortIndexOutput) {
1317                        if (mState == STARTING) {
1318                            // We're always allocating output buffers after
1319                            // allocating input buffers, so this is a good
1320                            // indication that now all buffers are allocated.
1321                            if (mIsVideo) {
1322                                String8 subtype;
1323                                addResource(
1324                                        String8(kResourceGraphicMemory),
1325                                        subtype,
1326                                        getGraphicBufferSize());
1327                            }
1328                            setState(STARTED);
1329                            (new AMessage)->postReply(mReplyID);
1330                        } else {
1331                            mFlags |= kFlagOutputBuffersChanged;
1332                            postActivityNotificationIfPossible();
1333                        }
1334                    }
1335                    break;
1336                }
1337
1338                case CodecBase::kWhatOutputFormatChanged:
1339                {
1340                    ALOGV("codec output format changed");
1341
1342                    if (mSoftRenderer == NULL &&
1343                            mSurface != NULL &&
1344                            (mFlags & kFlagUsesSoftwareRenderer)) {
1345                        AString mime;
1346                        CHECK(msg->findString("mime", &mime));
1347
1348                        if (mime.startsWithIgnoreCase("video/")) {
1349                            mSoftRenderer = new SoftwareRenderer(mSurface, mRotationDegrees);
1350                        }
1351                    }
1352
1353                    mOutputFormat = msg;
1354
1355                    if (mFlags & kFlagIsEncoder) {
1356                        // Before we announce the format change we should
1357                        // collect codec specific data and amend the output
1358                        // format as necessary.
1359                        mFlags |= kFlagGatherCodecSpecificData;
1360                    } else if (mFlags & kFlagIsAsync) {
1361                        onOutputFormatChanged();
1362                    } else {
1363                        mFlags |= kFlagOutputFormatChanged;
1364                        postActivityNotificationIfPossible();
1365                    }
1366
1367                    // Notify mCrypto of video resolution changes
1368                    if (mCrypto != NULL) {
1369                        int32_t left, top, right, bottom, width, height;
1370                        if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
1371                            mCrypto->notifyResolution(right - left + 1, bottom - top + 1);
1372                        } else if (mOutputFormat->findInt32("width", &width)
1373                                && mOutputFormat->findInt32("height", &height)) {
1374                            mCrypto->notifyResolution(width, height);
1375                        }
1376                    }
1377
1378                    break;
1379                }
1380
1381                case CodecBase::kWhatOutputFramesRendered:
1382                {
1383                    // ignore these in all states except running, and check that we have a
1384                    // notification set
1385                    if (mState == STARTED && mOnFrameRenderedNotification != NULL) {
1386                        sp<AMessage> notify = mOnFrameRenderedNotification->dup();
1387                        notify->setMessage("data", msg);
1388                        notify->post();
1389                    }
1390                    break;
1391                }
1392
1393                case CodecBase::kWhatFillThisBuffer:
1394                {
1395                    /* size_t index = */updateBuffers(kPortIndexInput, msg);
1396
1397                    if (mState == FLUSHING
1398                            || mState == STOPPING
1399                            || mState == RELEASING) {
1400                        returnBuffersToCodecOnPort(kPortIndexInput);
1401                        break;
1402                    }
1403
1404                    if (!mCSD.empty()) {
1405                        ssize_t index = dequeuePortBuffer(kPortIndexInput);
1406                        CHECK_GE(index, 0);
1407
1408                        // If codec specific data had been specified as
1409                        // part of the format in the call to configure and
1410                        // if there's more csd left, we submit it here
1411                        // clients only get access to input buffers once
1412                        // this data has been exhausted.
1413
1414                        status_t err = queueCSDInputBuffer(index);
1415
1416                        if (err != OK) {
1417                            ALOGE("queueCSDInputBuffer failed w/ error %d",
1418                                  err);
1419
1420                            setStickyError(err);
1421                            postActivityNotificationIfPossible();
1422
1423                            cancelPendingDequeueOperations();
1424                        }
1425                        break;
1426                    }
1427
1428                    if (mFlags & kFlagIsAsync) {
1429                        if (!mHaveInputSurface) {
1430                            if (mState == FLUSHED) {
1431                                mHavePendingInputBuffers = true;
1432                            } else {
1433                                onInputBufferAvailable();
1434                            }
1435                        }
1436                    } else if (mFlags & kFlagDequeueInputPending) {
1437                        CHECK(handleDequeueInputBuffer(mDequeueInputReplyID));
1438
1439                        ++mDequeueInputTimeoutGeneration;
1440                        mFlags &= ~kFlagDequeueInputPending;
1441                        mDequeueInputReplyID = 0;
1442                    } else {
1443                        postActivityNotificationIfPossible();
1444                    }
1445                    break;
1446                }
1447
1448                case CodecBase::kWhatDrainThisBuffer:
1449                {
1450                    /* size_t index = */updateBuffers(kPortIndexOutput, msg);
1451
1452                    if (mState == FLUSHING
1453                            || mState == STOPPING
1454                            || mState == RELEASING) {
1455                        returnBuffersToCodecOnPort(kPortIndexOutput);
1456                        break;
1457                    }
1458
1459                    sp<ABuffer> buffer;
1460                    CHECK(msg->findBuffer("buffer", &buffer));
1461
1462                    int32_t omxFlags;
1463                    CHECK(msg->findInt32("flags", &omxFlags));
1464
1465                    buffer->meta()->setInt32("omxFlags", omxFlags);
1466
1467                    if (mFlags & kFlagGatherCodecSpecificData) {
1468                        // This is the very first output buffer after a
1469                        // format change was signalled, it'll either contain
1470                        // the one piece of codec specific data we can expect
1471                        // or there won't be codec specific data.
1472                        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1473                            status_t err =
1474                                amendOutputFormatWithCodecSpecificData(buffer);
1475
1476                            if (err != OK) {
1477                                ALOGE("Codec spit out malformed codec "
1478                                      "specific data!");
1479                            }
1480                        }
1481
1482                        mFlags &= ~kFlagGatherCodecSpecificData;
1483                        if (mFlags & kFlagIsAsync) {
1484                            onOutputFormatChanged();
1485                        } else {
1486                            mFlags |= kFlagOutputFormatChanged;
1487                        }
1488                    }
1489
1490                    if (mFlags & kFlagIsAsync) {
1491                        onOutputBufferAvailable();
1492                    } else if (mFlags & kFlagDequeueOutputPending) {
1493                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));
1494
1495                        ++mDequeueOutputTimeoutGeneration;
1496                        mFlags &= ~kFlagDequeueOutputPending;
1497                        mDequeueOutputReplyID = 0;
1498                    } else {
1499                        postActivityNotificationIfPossible();
1500                    }
1501
1502                    break;
1503                }
1504
1505                case CodecBase::kWhatEOS:
1506                {
1507                    // We already notify the client of this by using the
1508                    // corresponding flag in "onOutputBufferReady".
1509                    break;
1510                }
1511
1512                case CodecBase::kWhatShutdownCompleted:
1513                {
1514                    if (mState == STOPPING) {
1515                        setState(INITIALIZED);
1516                    } else {
1517                        CHECK_EQ(mState, RELEASING);
1518                        setState(UNINITIALIZED);
1519                        mComponentName.clear();
1520                    }
1521                    mFlags &= ~kFlagIsComponentAllocated;
1522
1523                    mResourceManagerService->removeResource(getId(mResourceManagerClient));
1524
1525                    (new AMessage)->postReply(mReplyID);
1526                    break;
1527                }
1528
1529                case CodecBase::kWhatFlushCompleted:
1530                {
1531                    if (mState != FLUSHING) {
1532                        ALOGW("received FlushCompleted message in state %d",
1533                                mState);
1534                        break;
1535                    }
1536
1537                    if (mFlags & kFlagIsAsync) {
1538                        setState(FLUSHED);
1539                    } else {
1540                        setState(STARTED);
1541                        mCodec->signalResume();
1542                    }
1543
1544                    (new AMessage)->postReply(mReplyID);
1545                    break;
1546                }
1547
1548                default:
1549                    TRESPASS();
1550            }
1551            break;
1552        }
1553
1554        case kWhatInit:
1555        {
1556            sp<AReplyToken> replyID;
1557            CHECK(msg->senderAwaitsResponse(&replyID));
1558
1559            if (mState != UNINITIALIZED) {
1560                PostReplyWithError(replyID, INVALID_OPERATION);
1561                break;
1562            }
1563
1564            mReplyID = replyID;
1565            setState(INITIALIZING);
1566
1567            AString name;
1568            CHECK(msg->findString("name", &name));
1569
1570            int32_t nameIsType;
1571            int32_t encoder = false;
1572            CHECK(msg->findInt32("nameIsType", &nameIsType));
1573            if (nameIsType) {
1574                CHECK(msg->findInt32("encoder", &encoder));
1575            }
1576
1577            sp<AMessage> format = new AMessage;
1578
1579            if (nameIsType) {
1580                format->setString("mime", name.c_str());
1581                format->setInt32("encoder", encoder);
1582            } else {
1583                format->setString("componentName", name.c_str());
1584            }
1585
1586            mCodec->initiateAllocateComponent(format);
1587            break;
1588        }
1589
1590        case kWhatSetNotification:
1591        {
1592            sp<AMessage> notify;
1593            if (msg->findMessage("on-frame-rendered", &notify)) {
1594                mOnFrameRenderedNotification = notify;
1595            }
1596            break;
1597        }
1598
1599        case kWhatSetCallback:
1600        {
1601            sp<AReplyToken> replyID;
1602            CHECK(msg->senderAwaitsResponse(&replyID));
1603
1604            if (mState == UNINITIALIZED
1605                    || mState == INITIALIZING
1606                    || isExecuting()) {
1607                // callback can't be set after codec is executing,
1608                // or before it's initialized (as the callback
1609                // will be cleared when it goes to INITIALIZED)
1610                PostReplyWithError(replyID, INVALID_OPERATION);
1611                break;
1612            }
1613
1614            sp<AMessage> callback;
1615            CHECK(msg->findMessage("callback", &callback));
1616
1617            mCallback = callback;
1618
1619            if (mCallback != NULL) {
1620                ALOGI("MediaCodec will operate in async mode");
1621                mFlags |= kFlagIsAsync;
1622            } else {
1623                mFlags &= ~kFlagIsAsync;
1624            }
1625
1626            sp<AMessage> response = new AMessage;
1627            response->postReply(replyID);
1628            break;
1629        }
1630
1631        case kWhatConfigure:
1632        {
1633            sp<AReplyToken> replyID;
1634            CHECK(msg->senderAwaitsResponse(&replyID));
1635
1636            if (mState != INITIALIZED) {
1637                PostReplyWithError(replyID, INVALID_OPERATION);
1638                break;
1639            }
1640
1641            sp<RefBase> obj;
1642            CHECK(msg->findObject("surface", &obj));
1643
1644            sp<AMessage> format;
1645            CHECK(msg->findMessage("format", &format));
1646
1647            int32_t push;
1648            if (msg->findInt32("push-blank-buffers-on-shutdown", &push) && push != 0) {
1649                mFlags |= kFlagPushBlankBuffersOnShutdown;
1650            }
1651
1652            if (obj != NULL) {
1653                format->setObject("native-window", obj);
1654                status_t err = handleSetSurface(static_cast<Surface *>(obj.get()));
1655                if (err != OK) {
1656                    PostReplyWithError(replyID, err);
1657                    break;
1658                }
1659            } else {
1660                handleSetSurface(NULL);
1661            }
1662
1663            mReplyID = replyID;
1664            setState(CONFIGURING);
1665
1666            void *crypto;
1667            if (!msg->findPointer("crypto", &crypto)) {
1668                crypto = NULL;
1669            }
1670
1671            mCrypto = static_cast<ICrypto *>(crypto);
1672
1673            uint32_t flags;
1674            CHECK(msg->findInt32("flags", (int32_t *)&flags));
1675
1676            if (flags & CONFIGURE_FLAG_ENCODE) {
1677                format->setInt32("encoder", true);
1678                mFlags |= kFlagIsEncoder;
1679            }
1680
1681            extractCSD(format);
1682
1683            mCodec->initiateConfigureComponent(format);
1684            break;
1685        }
1686
1687        case kWhatSetSurface:
1688        {
1689            sp<AReplyToken> replyID;
1690            CHECK(msg->senderAwaitsResponse(&replyID));
1691
1692            status_t err = OK;
1693            sp<Surface> surface;
1694
1695            switch (mState) {
1696                case CONFIGURED:
1697                case STARTED:
1698                case FLUSHED:
1699                {
1700                    sp<RefBase> obj;
1701                    (void)msg->findObject("surface", &obj);
1702                    sp<Surface> surface = static_cast<Surface *>(obj.get());
1703                    if (mSurface == NULL) {
1704                        // do not support setting surface if it was not set
1705                        err = INVALID_OPERATION;
1706                    } else if (obj == NULL) {
1707                        // do not support unsetting surface
1708                        err = BAD_VALUE;
1709                    } else {
1710                        err = connectToSurface(surface);
1711                        if (err == BAD_VALUE) {
1712                            // assuming reconnecting to same surface
1713                            // TODO: check if it is the same surface
1714                            err = OK;
1715                        } else {
1716                            if (err == OK) {
1717                                if (mFlags & kFlagUsesSoftwareRenderer) {
1718                                    if (mSoftRenderer != NULL
1719                                            && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1720                                        pushBlankBuffersToNativeWindow(mSurface.get());
1721                                    }
1722                                    mSoftRenderer = new SoftwareRenderer(surface);
1723                                    // TODO: check if this was successful
1724                                } else {
1725                                    err = mCodec->setSurface(surface);
1726                                }
1727                            }
1728                            if (err == OK) {
1729                                (void)disconnectFromSurface();
1730                                mSurface = surface;
1731                            }
1732                        }
1733                    }
1734                    break;
1735                }
1736
1737                default:
1738                    err = INVALID_OPERATION;
1739                    break;
1740            }
1741
1742            PostReplyWithError(replyID, err);
1743            break;
1744        }
1745
1746        case kWhatCreateInputSurface:
1747        case kWhatSetInputSurface:
1748        {
1749            sp<AReplyToken> replyID;
1750            CHECK(msg->senderAwaitsResponse(&replyID));
1751
1752            // Must be configured, but can't have been started yet.
1753            if (mState != CONFIGURED) {
1754                PostReplyWithError(replyID, INVALID_OPERATION);
1755                break;
1756            }
1757
1758            mReplyID = replyID;
1759            if (msg->what() == kWhatCreateInputSurface) {
1760                mCodec->initiateCreateInputSurface();
1761            } else {
1762                sp<RefBase> obj;
1763                CHECK(msg->findObject("input-surface", &obj));
1764
1765                mCodec->initiateSetInputSurface(
1766                        static_cast<PersistentSurface *>(obj.get()));
1767            }
1768            break;
1769        }
1770        case kWhatStart:
1771        {
1772            sp<AReplyToken> replyID;
1773            CHECK(msg->senderAwaitsResponse(&replyID));
1774
1775            if (mState == FLUSHED) {
1776                setState(STARTED);
1777                if (mHavePendingInputBuffers) {
1778                    onInputBufferAvailable();
1779                    mHavePendingInputBuffers = false;
1780                }
1781                mCodec->signalResume();
1782                PostReplyWithError(replyID, OK);
1783                break;
1784            } else if (mState != CONFIGURED) {
1785                PostReplyWithError(replyID, INVALID_OPERATION);
1786                break;
1787            }
1788
1789            mReplyID = replyID;
1790            setState(STARTING);
1791
1792            mCodec->initiateStart();
1793            break;
1794        }
1795
1796        case kWhatStop:
1797        case kWhatRelease:
1798        {
1799            State targetState =
1800                (msg->what() == kWhatStop) ? INITIALIZED : UNINITIALIZED;
1801
1802            sp<AReplyToken> replyID;
1803            CHECK(msg->senderAwaitsResponse(&replyID));
1804
1805            // already stopped/released
1806            if (mState == UNINITIALIZED && mReleasedByResourceManager) {
1807                sp<AMessage> response = new AMessage;
1808                response->setInt32("err", OK);
1809                response->postReply(replyID);
1810                break;
1811            }
1812
1813            int32_t reclaimed = 0;
1814            msg->findInt32("reclaimed", &reclaimed);
1815            if (reclaimed) {
1816                mReleasedByResourceManager = true;
1817
1818                int32_t force = 0;
1819                msg->findInt32("force", &force);
1820                if (!force && hasPendingBuffer()) {
1821                    ALOGW("Can't reclaim codec right now due to pending buffers.");
1822
1823                    // return WOULD_BLOCK to ask resource manager to retry later.
1824                    sp<AMessage> response = new AMessage;
1825                    response->setInt32("err", WOULD_BLOCK);
1826                    response->postReply(replyID);
1827
1828                    // notify the async client
1829                    if (mFlags & kFlagIsAsync) {
1830                        onError(DEAD_OBJECT, ACTION_CODE_FATAL);
1831                    }
1832                    break;
1833                }
1834            }
1835
1836            if (!((mFlags & kFlagIsComponentAllocated) && targetState == UNINITIALIZED) // See 1
1837                    && mState != INITIALIZED
1838                    && mState != CONFIGURED && !isExecuting()) {
1839                // 1) Permit release to shut down the component if allocated.
1840                //
1841                // 2) We may be in "UNINITIALIZED" state already and
1842                // also shutdown the encoder/decoder without the
1843                // client being aware of this if media server died while
1844                // we were being stopped. The client would assume that
1845                // after stop() returned, it would be safe to call release()
1846                // and it should be in this case, no harm to allow a release()
1847                // if we're already uninitialized.
1848                sp<AMessage> response = new AMessage;
1849                // TODO: we shouldn't throw an exception for stop/release. Change this to wait until
1850                // the previous stop/release completes and then reply with OK.
1851                status_t err = mState == targetState ? OK : INVALID_OPERATION;
1852                response->setInt32("err", err);
1853                if (err == OK && targetState == UNINITIALIZED) {
1854                    mComponentName.clear();
1855                }
1856                response->postReply(replyID);
1857                break;
1858            }
1859
1860            if (mFlags & kFlagSawMediaServerDie) {
1861                // It's dead, Jim. Don't expect initiateShutdown to yield
1862                // any useful results now...
1863                setState(UNINITIALIZED);
1864                if (targetState == UNINITIALIZED) {
1865                    mComponentName.clear();
1866                }
1867                (new AMessage)->postReply(replyID);
1868                break;
1869            }
1870
1871            mReplyID = replyID;
1872            setState(msg->what() == kWhatStop ? STOPPING : RELEASING);
1873
1874            mCodec->initiateShutdown(
1875                    msg->what() == kWhatStop /* keepComponentAllocated */);
1876
1877            returnBuffersToCodec();
1878
1879            if (mSoftRenderer != NULL && (mFlags & kFlagPushBlankBuffersOnShutdown)) {
1880                pushBlankBuffersToNativeWindow(mSurface.get());
1881            }
1882            break;
1883        }
1884
1885        case kWhatDequeueInputBuffer:
1886        {
1887            sp<AReplyToken> replyID;
1888            CHECK(msg->senderAwaitsResponse(&replyID));
1889
1890            if (mFlags & kFlagIsAsync) {
1891                ALOGE("dequeueOutputBuffer can't be used in async mode");
1892                PostReplyWithError(replyID, INVALID_OPERATION);
1893                break;
1894            }
1895
1896            if (mHaveInputSurface) {
1897                ALOGE("dequeueInputBuffer can't be used with input surface");
1898                PostReplyWithError(replyID, INVALID_OPERATION);
1899                break;
1900            }
1901
1902            if (handleDequeueInputBuffer(replyID, true /* new request */)) {
1903                break;
1904            }
1905
1906            int64_t timeoutUs;
1907            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1908
1909            if (timeoutUs == 0ll) {
1910                PostReplyWithError(replyID, -EAGAIN);
1911                break;
1912            }
1913
1914            mFlags |= kFlagDequeueInputPending;
1915            mDequeueInputReplyID = replyID;
1916
1917            if (timeoutUs > 0ll) {
1918                sp<AMessage> timeoutMsg =
1919                    new AMessage(kWhatDequeueInputTimedOut, this);
1920                timeoutMsg->setInt32(
1921                        "generation", ++mDequeueInputTimeoutGeneration);
1922                timeoutMsg->post(timeoutUs);
1923            }
1924            break;
1925        }
1926
1927        case kWhatDequeueInputTimedOut:
1928        {
1929            int32_t generation;
1930            CHECK(msg->findInt32("generation", &generation));
1931
1932            if (generation != mDequeueInputTimeoutGeneration) {
1933                // Obsolete
1934                break;
1935            }
1936
1937            CHECK(mFlags & kFlagDequeueInputPending);
1938
1939            PostReplyWithError(mDequeueInputReplyID, -EAGAIN);
1940
1941            mFlags &= ~kFlagDequeueInputPending;
1942            mDequeueInputReplyID = 0;
1943            break;
1944        }
1945
1946        case kWhatQueueInputBuffer:
1947        {
1948            sp<AReplyToken> replyID;
1949            CHECK(msg->senderAwaitsResponse(&replyID));
1950
1951            if (!isExecuting()) {
1952                PostReplyWithError(replyID, INVALID_OPERATION);
1953                break;
1954            } else if (mFlags & kFlagStickyError) {
1955                PostReplyWithError(replyID, getStickyError());
1956                break;
1957            }
1958
1959            status_t err = onQueueInputBuffer(msg);
1960
1961            PostReplyWithError(replyID, err);
1962            break;
1963        }
1964
1965        case kWhatDequeueOutputBuffer:
1966        {
1967            sp<AReplyToken> replyID;
1968            CHECK(msg->senderAwaitsResponse(&replyID));
1969
1970            if (mFlags & kFlagIsAsync) {
1971                ALOGE("dequeueOutputBuffer can't be used in async mode");
1972                PostReplyWithError(replyID, INVALID_OPERATION);
1973                break;
1974            }
1975
1976            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
1977                break;
1978            }
1979
1980            int64_t timeoutUs;
1981            CHECK(msg->findInt64("timeoutUs", &timeoutUs));
1982
1983            if (timeoutUs == 0ll) {
1984                PostReplyWithError(replyID, -EAGAIN);
1985                break;
1986            }
1987
1988            mFlags |= kFlagDequeueOutputPending;
1989            mDequeueOutputReplyID = replyID;
1990
1991            if (timeoutUs > 0ll) {
1992                sp<AMessage> timeoutMsg =
1993                    new AMessage(kWhatDequeueOutputTimedOut, this);
1994                timeoutMsg->setInt32(
1995                        "generation", ++mDequeueOutputTimeoutGeneration);
1996                timeoutMsg->post(timeoutUs);
1997            }
1998            break;
1999        }
2000
2001        case kWhatDequeueOutputTimedOut:
2002        {
2003            int32_t generation;
2004            CHECK(msg->findInt32("generation", &generation));
2005
2006            if (generation != mDequeueOutputTimeoutGeneration) {
2007                // Obsolete
2008                break;
2009            }
2010
2011            CHECK(mFlags & kFlagDequeueOutputPending);
2012
2013            PostReplyWithError(mDequeueOutputReplyID, -EAGAIN);
2014
2015            mFlags &= ~kFlagDequeueOutputPending;
2016            mDequeueOutputReplyID = 0;
2017            break;
2018        }
2019
2020        case kWhatReleaseOutputBuffer:
2021        {
2022            sp<AReplyToken> replyID;
2023            CHECK(msg->senderAwaitsResponse(&replyID));
2024
2025            if (!isExecuting()) {
2026                PostReplyWithError(replyID, INVALID_OPERATION);
2027                break;
2028            } else if (mFlags & kFlagStickyError) {
2029                PostReplyWithError(replyID, getStickyError());
2030                break;
2031            }
2032
2033            status_t err = onReleaseOutputBuffer(msg);
2034
2035            PostReplyWithError(replyID, err);
2036            break;
2037        }
2038
2039        case kWhatSignalEndOfInputStream:
2040        {
2041            sp<AReplyToken> replyID;
2042            CHECK(msg->senderAwaitsResponse(&replyID));
2043
2044            if (!isExecuting()) {
2045                PostReplyWithError(replyID, INVALID_OPERATION);
2046                break;
2047            } else if (mFlags & kFlagStickyError) {
2048                PostReplyWithError(replyID, getStickyError());
2049                break;
2050            }
2051
2052            mReplyID = replyID;
2053            mCodec->signalEndOfInputStream();
2054            break;
2055        }
2056
2057        case kWhatGetBuffers:
2058        {
2059            sp<AReplyToken> replyID;
2060            CHECK(msg->senderAwaitsResponse(&replyID));
2061            // Unfortunately widevine legacy source requires knowing all of the
2062            // codec input buffers, so we have to provide them even in async mode.
2063            int32_t widevine = 0;
2064            msg->findInt32("widevine", &widevine);
2065
2066            if (!isExecuting() || ((mFlags & kFlagIsAsync) && !widevine)) {
2067                PostReplyWithError(replyID, INVALID_OPERATION);
2068                break;
2069            } else if (mFlags & kFlagStickyError) {
2070                PostReplyWithError(replyID, getStickyError());
2071                break;
2072            }
2073
2074            int32_t portIndex;
2075            CHECK(msg->findInt32("portIndex", &portIndex));
2076
2077            Vector<sp<ABuffer> > *dstBuffers;
2078            CHECK(msg->findPointer("buffers", (void **)&dstBuffers));
2079
2080            dstBuffers->clear();
2081            const Vector<BufferInfo> &srcBuffers = mPortBuffers[portIndex];
2082
2083            for (size_t i = 0; i < srcBuffers.size(); ++i) {
2084                const BufferInfo &info = srcBuffers.itemAt(i);
2085
2086                dstBuffers->push_back(
2087                        (portIndex == kPortIndexInput && mCrypto != NULL)
2088                                ? info.mEncryptedData : info.mData);
2089            }
2090
2091            (new AMessage)->postReply(replyID);
2092            break;
2093        }
2094
2095        case kWhatFlush:
2096        {
2097            sp<AReplyToken> replyID;
2098            CHECK(msg->senderAwaitsResponse(&replyID));
2099
2100            if (!isExecuting()) {
2101                PostReplyWithError(replyID, INVALID_OPERATION);
2102                break;
2103            } else if (mFlags & kFlagStickyError) {
2104                PostReplyWithError(replyID, getStickyError());
2105                break;
2106            }
2107
2108            mReplyID = replyID;
2109            // TODO: skip flushing if already FLUSHED
2110            setState(FLUSHING);
2111
2112            mCodec->signalFlush();
2113            returnBuffersToCodec();
2114            break;
2115        }
2116
2117        case kWhatGetInputFormat:
2118        case kWhatGetOutputFormat:
2119        {
2120            sp<AMessage> format =
2121                (msg->what() == kWhatGetOutputFormat ? mOutputFormat : mInputFormat);
2122
2123            sp<AReplyToken> replyID;
2124            CHECK(msg->senderAwaitsResponse(&replyID));
2125
2126            if ((mState != CONFIGURED && mState != STARTING &&
2127                 mState != STARTED && mState != FLUSHING &&
2128                 mState != FLUSHED)
2129                    || format == NULL) {
2130                PostReplyWithError(replyID, INVALID_OPERATION);
2131                break;
2132            } else if (mFlags & kFlagStickyError) {
2133                PostReplyWithError(replyID, getStickyError());
2134                break;
2135            }
2136
2137            sp<AMessage> response = new AMessage;
2138            response->setMessage("format", format);
2139            response->postReply(replyID);
2140            break;
2141        }
2142
2143        case kWhatRequestIDRFrame:
2144        {
2145            mCodec->signalRequestIDRFrame();
2146            break;
2147        }
2148
2149        case kWhatRequestActivityNotification:
2150        {
2151            CHECK(mActivityNotify == NULL);
2152            CHECK(msg->findMessage("notify", &mActivityNotify));
2153
2154            postActivityNotificationIfPossible();
2155            break;
2156        }
2157
2158        case kWhatGetName:
2159        {
2160            sp<AReplyToken> replyID;
2161            CHECK(msg->senderAwaitsResponse(&replyID));
2162
2163            if (mComponentName.empty()) {
2164                PostReplyWithError(replyID, INVALID_OPERATION);
2165                break;
2166            }
2167
2168            sp<AMessage> response = new AMessage;
2169            response->setString("name", mComponentName.c_str());
2170            response->postReply(replyID);
2171            break;
2172        }
2173
2174        case kWhatSetParameters:
2175        {
2176            sp<AReplyToken> replyID;
2177            CHECK(msg->senderAwaitsResponse(&replyID));
2178
2179            sp<AMessage> params;
2180            CHECK(msg->findMessage("params", &params));
2181
2182            status_t err = onSetParameters(params);
2183
2184            PostReplyWithError(replyID, err);
2185            break;
2186        }
2187
2188        default:
2189            TRESPASS();
2190    }
2191}
2192
2193void MediaCodec::extractCSD(const sp<AMessage> &format) {
2194    mCSD.clear();
2195
2196    size_t i = 0;
2197    for (;;) {
2198        sp<ABuffer> csd;
2199        if (!format->findBuffer(AStringPrintf("csd-%u", i).c_str(), &csd)) {
2200            break;
2201        }
2202
2203        mCSD.push_back(csd);
2204        ++i;
2205    }
2206
2207    ALOGV("Found %zu pieces of codec specific data.", mCSD.size());
2208}
2209
2210status_t MediaCodec::queueCSDInputBuffer(size_t bufferIndex) {
2211    CHECK(!mCSD.empty());
2212
2213    const BufferInfo *info =
2214        &mPortBuffers[kPortIndexInput].itemAt(bufferIndex);
2215
2216    sp<ABuffer> csd = *mCSD.begin();
2217    mCSD.erase(mCSD.begin());
2218
2219    const sp<ABuffer> &codecInputData =
2220        (mCrypto != NULL) ? info->mEncryptedData : info->mData;
2221
2222    if (csd->size() > codecInputData->capacity()) {
2223        return -EINVAL;
2224    }
2225
2226    memcpy(codecInputData->data(), csd->data(), csd->size());
2227
2228    AString errorDetailMsg;
2229
2230    sp<AMessage> msg = new AMessage(kWhatQueueInputBuffer, this);
2231    msg->setSize("index", bufferIndex);
2232    msg->setSize("offset", 0);
2233    msg->setSize("size", csd->size());
2234    msg->setInt64("timeUs", 0ll);
2235    msg->setInt32("flags", BUFFER_FLAG_CODECCONFIG);
2236    msg->setPointer("errorDetailMsg", &errorDetailMsg);
2237
2238    return onQueueInputBuffer(msg);
2239}
2240
2241void MediaCodec::setState(State newState) {
2242    if (newState == INITIALIZED || newState == UNINITIALIZED) {
2243        delete mSoftRenderer;
2244        mSoftRenderer = NULL;
2245
2246        mCrypto.clear();
2247        handleSetSurface(NULL);
2248
2249        mInputFormat.clear();
2250        mOutputFormat.clear();
2251        mFlags &= ~kFlagOutputFormatChanged;
2252        mFlags &= ~kFlagOutputBuffersChanged;
2253        mFlags &= ~kFlagStickyError;
2254        mFlags &= ~kFlagIsEncoder;
2255        mFlags &= ~kFlagGatherCodecSpecificData;
2256        mFlags &= ~kFlagIsAsync;
2257        mStickyError = OK;
2258
2259        mActivityNotify.clear();
2260        mCallback.clear();
2261    }
2262
2263    if (newState == UNINITIALIZED) {
2264        // return any straggling buffers, e.g. if we got here on an error
2265        returnBuffersToCodec();
2266
2267        // The component is gone, mediaserver's probably back up already
2268        // but should definitely be back up should we try to instantiate
2269        // another component.. and the cycle continues.
2270        mFlags &= ~kFlagSawMediaServerDie;
2271    }
2272
2273    mState = newState;
2274
2275    cancelPendingDequeueOperations();
2276
2277    updateBatteryStat();
2278}
2279
2280void MediaCodec::returnBuffersToCodec() {
2281    returnBuffersToCodecOnPort(kPortIndexInput);
2282    returnBuffersToCodecOnPort(kPortIndexOutput);
2283}
2284
2285void MediaCodec::returnBuffersToCodecOnPort(int32_t portIndex) {
2286    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2287    Mutex::Autolock al(mBufferLock);
2288
2289    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2290
2291    for (size_t i = 0; i < buffers->size(); ++i) {
2292        BufferInfo *info = &buffers->editItemAt(i);
2293
2294        if (info->mNotify != NULL) {
2295            sp<AMessage> msg = info->mNotify;
2296            info->mNotify = NULL;
2297            info->mOwnedByClient = false;
2298
2299            if (portIndex == kPortIndexInput) {
2300                /* no error, just returning buffers */
2301                msg->setInt32("err", OK);
2302            }
2303            msg->post();
2304        }
2305    }
2306
2307    mAvailPortBuffers[portIndex].clear();
2308}
2309
2310size_t MediaCodec::updateBuffers(
2311        int32_t portIndex, const sp<AMessage> &msg) {
2312    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2313
2314    uint32_t bufferID;
2315    CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
2316
2317    Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
2318
2319    for (size_t i = 0; i < buffers->size(); ++i) {
2320        BufferInfo *info = &buffers->editItemAt(i);
2321
2322        if (info->mBufferID == bufferID) {
2323            CHECK(info->mNotify == NULL);
2324            CHECK(msg->findMessage("reply", &info->mNotify));
2325
2326            info->mFormat =
2327                (portIndex == kPortIndexInput) ? mInputFormat : mOutputFormat;
2328            mAvailPortBuffers[portIndex].push_back(i);
2329
2330            return i;
2331        }
2332    }
2333
2334    TRESPASS();
2335
2336    return 0;
2337}
2338
2339status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
2340    size_t index;
2341    size_t offset;
2342    size_t size;
2343    int64_t timeUs;
2344    uint32_t flags;
2345    CHECK(msg->findSize("index", &index));
2346    CHECK(msg->findSize("offset", &offset));
2347    CHECK(msg->findInt64("timeUs", &timeUs));
2348    CHECK(msg->findInt32("flags", (int32_t *)&flags));
2349
2350    const CryptoPlugin::SubSample *subSamples;
2351    size_t numSubSamples;
2352    const uint8_t *key;
2353    const uint8_t *iv;
2354    CryptoPlugin::Mode mode = CryptoPlugin::kMode_Unencrypted;
2355
2356    // We allow the simpler queueInputBuffer API to be used even in
2357    // secure mode, by fabricating a single unencrypted subSample.
2358    CryptoPlugin::SubSample ss;
2359
2360    if (msg->findSize("size", &size)) {
2361        if (mCrypto != NULL) {
2362            ss.mNumBytesOfClearData = size;
2363            ss.mNumBytesOfEncryptedData = 0;
2364
2365            subSamples = &ss;
2366            numSubSamples = 1;
2367            key = NULL;
2368            iv = NULL;
2369        }
2370    } else {
2371        if (mCrypto == NULL) {
2372            return -EINVAL;
2373        }
2374
2375        CHECK(msg->findPointer("subSamples", (void **)&subSamples));
2376        CHECK(msg->findSize("numSubSamples", &numSubSamples));
2377        CHECK(msg->findPointer("key", (void **)&key));
2378        CHECK(msg->findPointer("iv", (void **)&iv));
2379
2380        int32_t tmp;
2381        CHECK(msg->findInt32("mode", &tmp));
2382
2383        mode = (CryptoPlugin::Mode)tmp;
2384
2385        size = 0;
2386        for (size_t i = 0; i < numSubSamples; ++i) {
2387            size += subSamples[i].mNumBytesOfClearData;
2388            size += subSamples[i].mNumBytesOfEncryptedData;
2389        }
2390    }
2391
2392    if (index >= mPortBuffers[kPortIndexInput].size()) {
2393        return -ERANGE;
2394    }
2395
2396    BufferInfo *info = &mPortBuffers[kPortIndexInput].editItemAt(index);
2397
2398    if (info->mNotify == NULL || !info->mOwnedByClient) {
2399        return -EACCES;
2400    }
2401
2402    if (offset + size > info->mData->capacity()) {
2403        return -EINVAL;
2404    }
2405
2406    sp<AMessage> reply = info->mNotify;
2407    info->mData->setRange(offset, size);
2408    info->mData->meta()->setInt64("timeUs", timeUs);
2409
2410    if (flags & BUFFER_FLAG_EOS) {
2411        info->mData->meta()->setInt32("eos", true);
2412    }
2413
2414    if (flags & BUFFER_FLAG_CODECCONFIG) {
2415        info->mData->meta()->setInt32("csd", true);
2416    }
2417
2418    if (mCrypto != NULL) {
2419        if (size > info->mEncryptedData->capacity()) {
2420            return -ERANGE;
2421        }
2422
2423        AString *errorDetailMsg;
2424        CHECK(msg->findPointer("errorDetailMsg", (void **)&errorDetailMsg));
2425
2426        ssize_t result = mCrypto->decrypt(
2427                (mFlags & kFlagIsSecure) != 0,
2428                key,
2429                iv,
2430                mode,
2431                info->mSharedEncryptedBuffer,
2432                offset,
2433                subSamples,
2434                numSubSamples,
2435                info->mData->base(),
2436                errorDetailMsg);
2437
2438        if (result < 0) {
2439            return result;
2440        }
2441
2442        info->mData->setRange(0, result);
2443    }
2444
2445    // synchronization boundary for getBufferAndFormat
2446    {
2447        Mutex::Autolock al(mBufferLock);
2448        info->mOwnedByClient = false;
2449    }
2450    reply->setBuffer("buffer", info->mData);
2451    reply->post();
2452
2453    info->mNotify = NULL;
2454
2455    return OK;
2456}
2457
2458//static
2459size_t MediaCodec::CreateFramesRenderedMessage(
2460        std::list<FrameRenderTracker::Info> done, sp<AMessage> &msg) {
2461    size_t index = 0;
2462
2463    for (std::list<FrameRenderTracker::Info>::const_iterator it = done.cbegin();
2464            it != done.cend(); ++it) {
2465        if (it->getRenderTimeNs() < 0) {
2466            continue; // dropped frame from tracking
2467        }
2468        msg->setInt64(AStringPrintf("%zu-media-time-us", index).c_str(), it->getMediaTimeUs());
2469        msg->setInt64(AStringPrintf("%zu-system-nano", index).c_str(), it->getRenderTimeNs());
2470        ++index;
2471    }
2472    return index;
2473}
2474
2475status_t MediaCodec::onReleaseOutputBuffer(const sp<AMessage> &msg) {
2476    size_t index;
2477    CHECK(msg->findSize("index", &index));
2478
2479    int32_t render;
2480    if (!msg->findInt32("render", &render)) {
2481        render = 0;
2482    }
2483
2484    if (!isExecuting()) {
2485        return -EINVAL;
2486    }
2487
2488    if (index >= mPortBuffers[kPortIndexOutput].size()) {
2489        return -ERANGE;
2490    }
2491
2492    BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
2493
2494    if (info->mNotify == NULL || !info->mOwnedByClient) {
2495        return -EACCES;
2496    }
2497
2498    // synchronization boundary for getBufferAndFormat
2499    {
2500        Mutex::Autolock al(mBufferLock);
2501        info->mOwnedByClient = false;
2502    }
2503
2504    if (render && info->mData != NULL && info->mData->size() != 0) {
2505        info->mNotify->setInt32("render", true);
2506
2507        int64_t mediaTimeUs = -1;
2508        info->mData->meta()->findInt64("timeUs", &mediaTimeUs);
2509
2510        int64_t renderTimeNs = 0;
2511        if (!msg->findInt64("timestampNs", &renderTimeNs)) {
2512            // use media timestamp if client did not request a specific render timestamp
2513            ALOGV("using buffer PTS of %lld", (long long)mediaTimeUs);
2514            renderTimeNs = mediaTimeUs * 1000;
2515        }
2516        info->mNotify->setInt64("timestampNs", renderTimeNs);
2517
2518        if (mSoftRenderer != NULL) {
2519            std::list<FrameRenderTracker::Info> doneFrames = mSoftRenderer->render(
2520                    info->mData->data(), info->mData->size(),
2521                    mediaTimeUs, renderTimeNs, NULL, info->mFormat);
2522
2523            // if we are running, notify rendered frames
2524            if (!doneFrames.empty() && mState == STARTED && mOnFrameRenderedNotification != NULL) {
2525                sp<AMessage> notify = mOnFrameRenderedNotification->dup();
2526                sp<AMessage> data = new AMessage;
2527                if (CreateFramesRenderedMessage(doneFrames, data)) {
2528                    notify->setMessage("data", data);
2529                    notify->post();
2530                }
2531            }
2532        }
2533    }
2534
2535    info->mNotify->post();
2536    info->mNotify = NULL;
2537
2538    return OK;
2539}
2540
2541ssize_t MediaCodec::dequeuePortBuffer(int32_t portIndex) {
2542    CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
2543
2544    List<size_t> *availBuffers = &mAvailPortBuffers[portIndex];
2545
2546    if (availBuffers->empty()) {
2547        return -EAGAIN;
2548    }
2549
2550    size_t index = *availBuffers->begin();
2551    availBuffers->erase(availBuffers->begin());
2552
2553    BufferInfo *info = &mPortBuffers[portIndex].editItemAt(index);
2554    CHECK(!info->mOwnedByClient);
2555    {
2556        Mutex::Autolock al(mBufferLock);
2557        info->mOwnedByClient = true;
2558
2559        // set image-data
2560        if (info->mFormat != NULL) {
2561            sp<ABuffer> imageData;
2562            if (info->mFormat->findBuffer("image-data", &imageData)) {
2563                info->mData->meta()->setBuffer("image-data", imageData);
2564            }
2565            int32_t left, top, right, bottom;
2566            if (info->mFormat->findRect("crop", &left, &top, &right, &bottom)) {
2567                info->mData->meta()->setRect("crop-rect", left, top, right, bottom);
2568            }
2569        }
2570    }
2571
2572    return index;
2573}
2574
2575status_t MediaCodec::connectToSurface(const sp<Surface> &surface) {
2576    status_t err = OK;
2577    if (surface != NULL) {
2578        err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2579        if (err == BAD_VALUE) {
2580            ALOGI("native window already connected. Assuming no change of surface");
2581            return err;
2582        } else if (err == OK) {
2583            // Require a fresh set of buffers after each connect by using a unique generation
2584            // number. Rely on the fact that max supported process id by Linux is 2^22.
2585            // PID is never 0 so we don't have to worry that we use the default generation of 0.
2586            // TODO: come up with a unique scheme if other producers also set the generation number.
2587            static uint32_t mSurfaceGeneration = 0;
2588            uint32_t generation = (getpid() << 10) | (++mSurfaceGeneration & ((1 << 10) - 1));
2589            surface->setGenerationNumber(generation);
2590            ALOGI("[%s] setting surface generation to %u", mComponentName.c_str(), generation);
2591
2592            // HACK: clear any free buffers. Remove when connect will automatically do this.
2593            // This is needed as the consumer may be holding onto stale frames that it can reattach
2594            // to this surface after disconnect/connect, and those free frames would inherit the new
2595            // generation number. Disconnecting after setting a unique generation prevents this.
2596            native_window_api_disconnect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2597            err = native_window_api_connect(surface.get(), NATIVE_WINDOW_API_MEDIA);
2598        }
2599
2600        if (err != OK) {
2601            ALOGE("native_window_api_connect returned an error: %s (%d)", strerror(-err), err);
2602        }
2603    }
2604    return err;
2605}
2606
2607status_t MediaCodec::disconnectFromSurface() {
2608    status_t err = OK;
2609    if (mSurface != NULL) {
2610        // Resetting generation is not technically needed, but there is no need to keep it either
2611        mSurface->setGenerationNumber(0);
2612        err = native_window_api_disconnect(mSurface.get(), NATIVE_WINDOW_API_MEDIA);
2613        if (err != OK) {
2614            ALOGW("native_window_api_disconnect returned an error: %s (%d)", strerror(-err), err);
2615        }
2616        // assume disconnected even on error
2617        mSurface.clear();
2618    }
2619    return err;
2620}
2621
2622status_t MediaCodec::handleSetSurface(const sp<Surface> &surface) {
2623    status_t err = OK;
2624    if (mSurface != NULL) {
2625        (void)disconnectFromSurface();
2626    }
2627    if (surface != NULL) {
2628        err = connectToSurface(surface);
2629        if (err == OK) {
2630            mSurface = surface;
2631        }
2632    }
2633    return err;
2634}
2635
2636void MediaCodec::onInputBufferAvailable() {
2637    int32_t index;
2638    while ((index = dequeuePortBuffer(kPortIndexInput)) >= 0) {
2639        sp<AMessage> msg = mCallback->dup();
2640        msg->setInt32("callbackID", CB_INPUT_AVAILABLE);
2641        msg->setInt32("index", index);
2642        msg->post();
2643    }
2644}
2645
2646void MediaCodec::onOutputBufferAvailable() {
2647    int32_t index;
2648    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
2649        const sp<ABuffer> &buffer =
2650            mPortBuffers[kPortIndexOutput].itemAt(index).mData;
2651        sp<AMessage> msg = mCallback->dup();
2652        msg->setInt32("callbackID", CB_OUTPUT_AVAILABLE);
2653        msg->setInt32("index", index);
2654        msg->setSize("offset", buffer->offset());
2655        msg->setSize("size", buffer->size());
2656
2657        int64_t timeUs;
2658        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
2659
2660        msg->setInt64("timeUs", timeUs);
2661
2662        int32_t omxFlags;
2663        CHECK(buffer->meta()->findInt32("omxFlags", &omxFlags));
2664
2665        uint32_t flags = 0;
2666        if (omxFlags & OMX_BUFFERFLAG_SYNCFRAME) {
2667            flags |= BUFFER_FLAG_SYNCFRAME;
2668        }
2669        if (omxFlags & OMX_BUFFERFLAG_CODECCONFIG) {
2670            flags |= BUFFER_FLAG_CODECCONFIG;
2671        }
2672        if (omxFlags & OMX_BUFFERFLAG_EOS) {
2673            flags |= BUFFER_FLAG_EOS;
2674        }
2675
2676        msg->setInt32("flags", flags);
2677
2678        msg->post();
2679    }
2680}
2681
2682void MediaCodec::onError(status_t err, int32_t actionCode, const char *detail) {
2683    if (mCallback != NULL) {
2684        sp<AMessage> msg = mCallback->dup();
2685        msg->setInt32("callbackID", CB_ERROR);
2686        msg->setInt32("err", err);
2687        msg->setInt32("actionCode", actionCode);
2688
2689        if (detail != NULL) {
2690            msg->setString("detail", detail);
2691        }
2692
2693        msg->post();
2694    }
2695}
2696
2697void MediaCodec::onOutputFormatChanged() {
2698    if (mCallback != NULL) {
2699        sp<AMessage> msg = mCallback->dup();
2700        msg->setInt32("callbackID", CB_OUTPUT_FORMAT_CHANGED);
2701        msg->setMessage("format", mOutputFormat);
2702        msg->post();
2703    }
2704}
2705
2706
2707void MediaCodec::postActivityNotificationIfPossible() {
2708    if (mActivityNotify == NULL) {
2709        return;
2710    }
2711
2712    bool isErrorOrOutputChanged =
2713            (mFlags & (kFlagStickyError
2714                    | kFlagOutputBuffersChanged
2715                    | kFlagOutputFormatChanged));
2716
2717    if (isErrorOrOutputChanged
2718            || !mAvailPortBuffers[kPortIndexInput].empty()
2719            || !mAvailPortBuffers[kPortIndexOutput].empty()) {
2720        mActivityNotify->setInt32("input-buffers",
2721                mAvailPortBuffers[kPortIndexInput].size());
2722
2723        if (isErrorOrOutputChanged) {
2724            // we want consumer to dequeue as many times as it can
2725            mActivityNotify->setInt32("output-buffers", INT32_MAX);
2726        } else {
2727            mActivityNotify->setInt32("output-buffers",
2728                    mAvailPortBuffers[kPortIndexOutput].size());
2729        }
2730        mActivityNotify->post();
2731        mActivityNotify.clear();
2732    }
2733}
2734
2735status_t MediaCodec::setParameters(const sp<AMessage> &params) {
2736    sp<AMessage> msg = new AMessage(kWhatSetParameters, this);
2737    msg->setMessage("params", params);
2738
2739    sp<AMessage> response;
2740    return PostAndAwaitResponse(msg, &response);
2741}
2742
2743status_t MediaCodec::onSetParameters(const sp<AMessage> &params) {
2744    mCodec->signalSetParameters(params);
2745
2746    return OK;
2747}
2748
2749status_t MediaCodec::amendOutputFormatWithCodecSpecificData(
2750        const sp<ABuffer> &buffer) {
2751    AString mime;
2752    CHECK(mOutputFormat->findString("mime", &mime));
2753
2754    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
2755        // Codec specific data should be SPS and PPS in a single buffer,
2756        // each prefixed by a startcode (0x00 0x00 0x00 0x01).
2757        // We separate the two and put them into the output format
2758        // under the keys "csd-0" and "csd-1".
2759
2760        unsigned csdIndex = 0;
2761
2762        const uint8_t *data = buffer->data();
2763        size_t size = buffer->size();
2764
2765        const uint8_t *nalStart;
2766        size_t nalSize;
2767        while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
2768            sp<ABuffer> csd = new ABuffer(nalSize + 4);
2769            memcpy(csd->data(), "\x00\x00\x00\x01", 4);
2770            memcpy(csd->data() + 4, nalStart, nalSize);
2771
2772            mOutputFormat->setBuffer(
2773                    AStringPrintf("csd-%u", csdIndex).c_str(), csd);
2774
2775            ++csdIndex;
2776        }
2777
2778        if (csdIndex != 2) {
2779            return ERROR_MALFORMED;
2780        }
2781    } else {
2782        // For everything else we just stash the codec specific data into
2783        // the output format as a single piece of csd under "csd-0".
2784        mOutputFormat->setBuffer("csd-0", buffer);
2785    }
2786
2787    return OK;
2788}
2789
2790void MediaCodec::updateBatteryStat() {
2791    if (mState == CONFIGURED && !mBatteryStatNotified) {
2792        BatteryNotifier& notifier(BatteryNotifier::getInstance());
2793
2794        if (mIsVideo) {
2795            notifier.noteStartVideo();
2796        } else {
2797            notifier.noteStartAudio();
2798        }
2799
2800        mBatteryStatNotified = true;
2801    } else if (mState == UNINITIALIZED && mBatteryStatNotified) {
2802        BatteryNotifier& notifier(BatteryNotifier::getInstance());
2803
2804        if (mIsVideo) {
2805            notifier.noteStopVideo();
2806        } else {
2807            notifier.noteStopAudio();
2808        }
2809
2810        mBatteryStatNotified = false;
2811    }
2812}
2813
2814}  // namespace android
2815