Merge "MPEG4Extractor: fix CTS test failure"
diff --git a/media/bufferpool/2.0/AccessorImpl.cpp b/media/bufferpool/2.0/AccessorImpl.cpp
index 84fcca2..0165314 100644
--- a/media/bufferpool/2.0/AccessorImpl.cpp
+++ b/media/bufferpool/2.0/AccessorImpl.cpp
@@ -308,7 +308,11 @@
         ConnectionId conId,
         uint32_t msgId) {
     auto it = mAcks.find(conId);
-    if (it == mAcks.end() || isMessageLater(msgId, it->second)) {
+    if (it == mAcks.end()) {
+        ALOGW("ACK from inconsistent connection! %lld", (long long)conId);
+        return;
+    }
+    if (isMessageLater(msgId, it->second)) {
         mAcks[conId] = msgId;
     }
 }
@@ -327,7 +331,6 @@
                 }
             }
             channel.postInvalidation(msgId, it->mFrom, it->mTo);
-            sInvalidator->addAccessor(mId, it->mImpl);
             it = mPendings.erase(it);
             continue;
         }
@@ -342,24 +345,24 @@
         size_t left,
         BufferInvalidationChannel &channel,
         const std::shared_ptr<Accessor::Impl> &impl) {
-    if (left == 0) {
         uint32_t msgId = 0;
-        if (needsAck) {
+    if (needsAck) {
+        msgId = ++mInvalidationId;
+        if (msgId == 0) {
+            // wrap happens
             msgId = ++mInvalidationId;
-            if (msgId == 0) {
-                // wrap happens
-                msgId = ++mInvalidationId;
-            }
         }
-        ALOGV("bufferpool invalidation requested and queued");
+    }
+    ALOGV("bufferpool invalidation requested and queued");
+    if (left == 0) {
         channel.postInvalidation(msgId, from, to);
-        sInvalidator->addAccessor(mId, impl);
     } else {
         // TODO: sending hint message?
         ALOGV("bufferpool invalidation requested and pending");
         Pending pending(needsAck, from, to, left, impl);
         mPendings.push_back(pending);
     }
+    sInvalidator->addAccessor(mId, impl);
 }
 
 void Accessor::Impl::BufferPool::Invalidation::onHandleAck() {
@@ -373,6 +376,9 @@
                           (long long)it->first, it->second, mInvalidationId);
                     Return<void> transResult = observer->onMessage(it->first, mInvalidationId);
                     (void) transResult;
+                    // N.B: ignore possibility of onMessage oneway call being
+                    // lost.
+                    it->second = mInvalidationId;
                 } else {
                     ALOGV("bufferpool observer died %lld", (long long)it->first);
                     deads.insert(it->first);
@@ -385,8 +391,10 @@
             }
         }
     }
-    // All invalidation Ids are synced.
-    sInvalidator->delAccessor(mId);
+    if (mPendings.size() == 0) {
+        // All invalidation Ids are synced and no more pending invalidations.
+        sInvalidator->delAccessor(mId);
+    }
 }
 
 bool Accessor::Impl::BufferPool::handleOwnBuffer(
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index dd29474..4aee9d5 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -608,6 +608,7 @@
         { "temporal-layer-count", kKeyTemporalLayerCount },
         { "thumbnail-width", kKeyThumbnailWidth },
         { "thumbnail-height", kKeyThumbnailHeight },
+        { "frame-count", kKeyFrameCount },
     }
 };
 
diff --git a/media/ndk/NdkMediaDataSource.cpp b/media/ndk/NdkMediaDataSource.cpp
index 3c10024..1abee93 100644
--- a/media/ndk/NdkMediaDataSource.cpp
+++ b/media/ndk/NdkMediaDataSource.cpp
@@ -59,6 +59,7 @@
     AMediaDataSource_setGetSize(mDataSource, dataSource->getSize);
     AMediaDataSource_setClose(mDataSource, dataSource->close);
     AMediaDataSource_setUserdata(mDataSource, dataSource->userdata);
+    AMediaDataSource_setGetAvailableSize(mDataSource, dataSource->getAvailableSize);
     mDataSource->mImpl = dataSource->mImpl;
     mDataSource->mFlags = dataSource->mFlags;
 }
diff --git a/media/ndk/NdkMediaDataSourceCallbacks.cpp b/media/ndk/NdkMediaDataSourceCallbacks.cpp
index f40387f..86a57da 100644
--- a/media/ndk/NdkMediaDataSourceCallbacks.cpp
+++ b/media/ndk/NdkMediaDataSourceCallbacks.cpp
@@ -43,8 +43,8 @@
 ssize_t DataSource_getAvailableSize(void *userdata, off64_t offset) {
     off64_t size = -1;
     DataSource *source = static_cast<DataSource *>(userdata);
-    status_t err = source->getAvailableSize(offset, &size);
-    return  err == OK ? size : -1;
+    source->getAvailableSize(offset, &size);
+    return  size;
 }
 
 }  // namespace android
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 4dacd02..2f50e3a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -1579,6 +1579,23 @@
 
 Status CameraService::notifySystemEvent(int32_t eventId,
         const std::vector<int32_t>& args) {
+    const int pid = CameraThreadState::getCallingPid();
+    const int selfPid = getpid();
+
+    // Permission checks
+    if (pid != selfPid) {
+        // Ensure we're being called by system_server, or similar process with
+        // permissions to notify the camera service about system events
+        if (!checkCallingPermission(
+                String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
+            const int uid = CameraThreadState::getCallingUid();
+            ALOGE("Permission Denial: cannot send updates to camera service about system"
+                    " events from pid=%d, uid=%d", pid, uid);
+            return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
+                            "No permission to send updates to camera service about system events from pid=%d, uid=%d", pid, uid);
+        }
+    }
+
     ATRACE_CALL();
 
     switch(eventId) {
@@ -1993,9 +2010,6 @@
 status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
         uint32_t flags) {
 
-    const int pid = CameraThreadState::getCallingPid();
-    const int selfPid = getpid();
-
     // Permission checks
     switch (code) {
         case SHELL_COMMAND_TRANSACTION: {
@@ -2022,20 +2036,6 @@
             }
             return NO_ERROR;
         }
-        case BnCameraService::NOTIFYSYSTEMEVENT: {
-            if (pid != selfPid) {
-                // Ensure we're being called by system_server, or similar process with
-                // permissions to notify the camera service about system events
-                if (!checkCallingPermission(
-                        String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
-                    const int uid = CameraThreadState::getCallingUid();
-                    ALOGE("Permission Denial: cannot send updates to camera service about system"
-                            " events from pid=%d, uid=%d", pid, uid);
-                    return PERMISSION_DENIED;
-                }
-            }
-            break;
-        }
     }
 
     return BnCameraService::onTransact(code, data, reply, flags);