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