CameraNDK: implement abortCaptures API

Bug: 27102995
Change-Id: Idaf1db02e0bcc60bb9cdb2797b4479ea0389f5f9
diff --git a/camera/ndk/impl/ACameraCaptureSession.cpp b/camera/ndk/impl/ACameraCaptureSession.cpp
index b741e46..b9c159d 100644
--- a/camera/ndk/impl/ACameraCaptureSession.cpp
+++ b/camera/ndk/impl/ACameraCaptureSession.cpp
@@ -90,6 +90,24 @@
 }
 
 camera_status_t
+ACameraCaptureSession::abortCaptures() {
+    sp<CameraDevice> dev = getDeviceSp();
+    if (dev == nullptr) {
+        ALOGE("Error: Device associated with session %p has been closed!", this);
+        return ACAMERA_ERROR_SESSION_CLOSED;
+    }
+
+    camera_status_t ret;
+    dev->lockDeviceForSessionOps();
+    {
+        Mutex::Autolock _l(mSessionLock);
+        ret = dev->flushLocked(this);
+    }
+    dev->unlockDevice();
+    return ret;
+}
+
+camera_status_t
 ACameraCaptureSession::setRepeatingRequest(
         /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
         int numRequests, ACaptureRequest** requests,
diff --git a/camera/ndk/impl/ACameraCaptureSession.h b/camera/ndk/impl/ACameraCaptureSession.h
index f20b324..58428e6 100644
--- a/camera/ndk/impl/ACameraCaptureSession.h
+++ b/camera/ndk/impl/ACameraCaptureSession.h
@@ -77,6 +77,8 @@
 
     camera_status_t stopRepeating();
 
+    camera_status_t abortCaptures();
+
     camera_status_t setRepeatingRequest(
             /*optional*/ACameraCaptureSession_captureCallbacks* cbs,
             int numRequests, ACaptureRequest** requests,
@@ -104,7 +106,6 @@
     const wp<CameraDevice> mDevice;
     bool  mIsClosed = false;
     bool  mClosedByApp = false;
-    bool  mIdle = true;
     Mutex mSessionLock;
 };
 
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 6bca692..8f1115a 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -170,6 +170,7 @@
     // set new session as current session
     newSession->incStrong((void *) ACameraDevice_createCaptureSession);
     mCurrentSession = newSession;
+    mFlushing = false;
     *session = newSession;
     return ACAMERA_OK;
 }
@@ -389,6 +390,58 @@
 }
 
 camera_status_t
+CameraDevice::flushLocked(ACameraCaptureSession* session) {
+    camera_status_t ret = checkCameraClosedOrErrorLocked();
+    if (ret != ACAMERA_OK) {
+        ALOGE("Camera %s abort captures failed! ret %d", getId(), ret);
+        return ret;
+    }
+
+    // This should never happen because creating a new session will close
+    // previous one and thus reject any API call from previous session.
+    // But still good to check here in case something unexpected happen.
+    if (session != mCurrentSession) {
+        ALOGE("Camera %s session %p is not current active session!", getId(), session);
+        return ACAMERA_ERROR_INVALID_OPERATION;
+    }
+
+    if (mFlushing) {
+        ALOGW("Camera %s is already aborting captures", getId());
+        return ACAMERA_OK;
+    }
+
+    mFlushing = true;
+    // Send onActive callback to guarantee there is always active->ready transition
+    sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+    msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+    msg->setObject(kSessionSpKey, session);
+    msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onActive);
+    msg->post();
+
+    // If device is already idling, send callback and exit early
+    if (mIdle) {
+        sp<AMessage> msg = new AMessage(kWhatSessionStateCb, mHandler);
+        msg->setPointer(kContextKey, session->mUserSessionCallback.context);
+        msg->setObject(kSessionSpKey, session);
+        msg->setPointer(kCallbackFpKey, (void*) session->mUserSessionCallback.onReady);
+        msg->post();
+        mFlushing = false;
+        return ACAMERA_OK;
+    }
+
+    int64_t lastFrameNumber;
+    binder::Status remoteRet = mRemote->flush(&lastFrameNumber);
+    if (!remoteRet.isOk()) {
+        ALOGE("Abort captures fails in remote: %s", remoteRet.toString8().string());
+        return ACAMERA_ERROR_UNKNOWN;
+    }
+    if (mRepeatingSequenceId != REQUEST_ID_NONE) {
+        checkRepeatingSequenceCompleteLocked(mRepeatingSequenceId, lastFrameNumber);
+    }
+    return ACAMERA_OK;
+}
+
+camera_status_t
 CameraDevice::waitUntilIdleLocked() {
     camera_status_t ret = checkCameraClosedOrErrorLocked();
     if (ret != ACAMERA_OK) {
@@ -1109,6 +1162,7 @@
         msg->post();
     }
     dev->mIdle = true;
+    dev->mFlushing = false;
     return ret;
 }
 
diff --git a/camera/ndk/impl/ACameraDevice.h b/camera/ndk/impl/ACameraDevice.h
index 46243b9..fd51a81 100644
--- a/camera/ndk/impl/ACameraDevice.h
+++ b/camera/ndk/impl/ACameraDevice.h
@@ -96,6 +96,8 @@
 
     camera_status_t stopRepeatingLocked();
 
+    camera_status_t flushLocked(ACameraCaptureSession*);
+
     camera_status_t waitUntilIdleLocked();
 
 
@@ -152,13 +154,13 @@
     std::atomic_bool mClosing;
     inline bool isClosed() { return mClosing; }
 
-    bool mInError;
-    camera_status_t mError;
+    bool mInError = false;
+    camera_status_t mError = ACAMERA_OK;
     void onCaptureErrorLocked(
             int32_t errorCode,
             const CaptureResultExtras& resultExtras);
 
-    bool mIdle;
+    bool mIdle = true;
     // This will avoid a busy session being deleted before it's back to idle state
     sp<ACameraCaptureSession> mBusySession;
 
@@ -203,6 +205,7 @@
      ***********************************/
     // The current active session
     ACameraCaptureSession* mCurrentSession = nullptr;
+    bool mFlushing = false;
 
     int mNextSessionId = 0;
     // TODO: might need another looper/handler to handle callbacks from service