Camera: Add initial offline client listener logic

Various camera notification callbacks need to be
propagated back to client.

Test: Camera CTS
Bug: 135142453

Change-Id: I11a1bc634e4c6f9540d1f7f9c20e4151fdcc5ec6
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index e7e72b2..ba17eb6 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1979,7 +1979,14 @@
             mClientFeatureId, mCameraIdStr, mCameraFacing, mClientPid, mClientUid, mServicePid);
     ret = sCameraService->addOfflineClient(mCameraIdStr, offlineClient);
     if (ret == OK) {
-        // TODO: We need to update mStreamMap, mConfiguredOutputs, mCompositeStreams
+        // A successful offline session switch must reset the current camera client
+        // and release any resources occupied by previously configured streams.
+        mStreamMap.clear();
+        mConfiguredOutputs.clear();
+        mDeferredStreams.clear();
+        mStreamInfoMap.clear();
+        mCompositeStreamMap.clear();
+        mInputStream = {false, 0, 0, 0, 0};
     } else {
         switch(ret) {
             case BAD_VALUE:
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index f713419..af7b9e1 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 //#define LOG_NDEBUG 0
 
 #include "CameraOfflineSessionClient.h"
+#include "utils/CameraThreadState.h"
 #include <utils/Trace.h>
 
 namespace android {
@@ -26,22 +27,71 @@
 using binder::Status;
 
 status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
+    ATRACE_CALL();
+
+    // Verify ops permissions
+    auto res = startCameraOps();
+    if (res != OK) {
+        return res;
+    }
+
+    if (mOfflineSession.get() == nullptr) {
+        ALOGE("%s: Camera %s: No valid offline session",
+                __FUNCTION__, mCameraIdStr.string());
+        return NO_INIT;
+    }
+
+    wp<NotificationListener> weakThis(this);
+    res = mOfflineSession->initialize(weakThis);
+    if (res != OK) {
+        ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
+                __FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
+        return res;
+    }
+
     return OK;
 }
 
-status_t CameraOfflineSessionClient::dump(int /*fd*/, const Vector<String16>& /*args*/) {
-    return OK;
+status_t CameraOfflineSessionClient::dump(int fd, const Vector<String16>& args) {
+    return BasicClient::dump(fd, args);
 }
 
-status_t CameraOfflineSessionClient::dumpClient(int /*fd*/, const Vector<String16>& /*args*/) {
+status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& /*args*/) {
+    String8 result;
+
+    result = "  Offline session dump:\n";
+    write(fd, result.string(), result.size());
+
+    if (mOfflineSession.get() == nullptr) {
+        result = "  *** Offline session is detached\n";
+        write(fd, result.string(), result.size());
+        return NO_ERROR;
+    }
+
+    auto res = mOfflineSession->dump(fd);
+    if (res != OK) {
+        result = String8::format("   Error dumping offline session: %s (%d)",
+                strerror(-res), res);
+        write(fd, result.string(), result.size());
+    }
+
     return OK;
 }
 
 binder::Status CameraOfflineSessionClient::disconnect() {
+    Mutex::Autolock icl(mBinderSerializationLock);
+
     binder::Status res = Status::ok();
     if (mDisconnected) {
         return res;
     }
+    // Allow both client and the media server to disconnect at all times
+    int callingPid = CameraThreadState::getCallingPid();
+    if (callingPid != mClientPid &&
+            callingPid != mServicePid) {
+        return res;
+    }
+
     mDisconnected = true;
 
     sCameraService->removeByClient(this);
@@ -59,6 +109,15 @@
     // client shouldn't be able to call into us anymore
     mClientPid = 0;
 
+    if (mOfflineSession.get() != nullptr) {
+        auto ret = mOfflineSession->disconnect();
+        if (ret != OK) {
+            ALOGE("%s: Failed disconnecting from offline session %s (%d)", __FUNCTION__,
+                    strerror(-ret), ret);
+        }
+        mOfflineSession = nullptr;
+    }
+
     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
         auto ret = mCompositeStreamMap.valueAt(i)->deleteInternalStreams();
         if (ret != OK) {
@@ -74,8 +133,6 @@
 void CameraOfflineSessionClient::notifyError(int32_t errorCode,
         const CaptureResultExtras& resultExtras) {
     // Thread safe. Don't bother locking.
-    sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
-    //
     // Composites can have multiple internal streams. Error notifications coming from such internal
     // streams may need to remain within camera service.
     bool skipClientNotification = false;
@@ -83,8 +140,8 @@
         skipClientNotification |= mCompositeStreamMap.valueAt(i)->onError(errorCode, resultExtras);
     }
 
-    if ((remoteCb != 0) && (!skipClientNotification)) {
-        remoteCb->onDeviceError(errorCode, resultExtras);
+    if ((mRemoteCallback.get() != nullptr) && (!skipClientNotification)) {
+        mRemoteCallback->onDeviceError(errorCode, resultExtras);
     }
 }
 
@@ -156,10 +213,8 @@
     ATRACE_CALL();
     ALOGV("%s", __FUNCTION__);
 
-    // Thread-safe. No lock necessary.
-    sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = mRemoteCallback;
-    if (remoteCb != NULL) {
-        remoteCb->onResultReceived(result.mMetadata, result.mResultExtras,
+    if (mRemoteCallback.get() != NULL) {
+        mRemoteCallback->onResultReceived(result.mMetadata, result.mResultExtras,
                 result.mPhysicalMetadatas);
     }
 
@@ -170,10 +225,9 @@
 
 void CameraOfflineSessionClient::notifyShutter(const CaptureResultExtras& resultExtras,
         nsecs_t timestamp) {
-    // Thread safe. Don't bother locking.
-    sp<hardware::camera2::ICameraDeviceCallbacks> remoteCb = getRemoteCallback();
-    if (remoteCb != 0) {
-        remoteCb->onCaptureStarted(resultExtras, timestamp);
+
+    if (mRemoteCallback.get() != nullptr) {
+        mRemoteCallback->onCaptureStarted(resultExtras, timestamp);
     }
 
     for (size_t i = 0; i < mCompositeStreamMap.size(); i++) {
@@ -181,5 +235,53 @@
     }
 }
 
+void CameraOfflineSessionClient::notifyIdle() {
+    if (mRemoteCallback.get() != nullptr) {
+        mRemoteCallback->onDeviceIdle();
+    }
+}
+
+void CameraOfflineSessionClient::notifyAutoFocus(uint8_t newState, int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Autofocus state now %d, last trigger %d",
+          __FUNCTION__, newState, triggerId);
+}
+
+void CameraOfflineSessionClient::notifyAutoExposure(uint8_t newState, int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Autoexposure state now %d, last trigger %d",
+            __FUNCTION__, newState, triggerId);
+}
+
+void CameraOfflineSessionClient::notifyAutoWhitebalance(uint8_t newState, int triggerId) {
+    (void)newState;
+    (void)triggerId;
+
+    ALOGV("%s: Auto-whitebalance state now %d, last trigger %d", __FUNCTION__, newState,
+            triggerId);
+}
+
+void CameraOfflineSessionClient::notifyPrepared(int /*streamId*/) {
+    ALOGE("%s: Unexpected stream prepare notification in offline mode!", __FUNCTION__);
+    notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+                CaptureResultExtras());
+}
+
+void CameraOfflineSessionClient::notifyRequestQueueEmpty() {
+    if (mRemoteCallback.get() != nullptr) {
+        mRemoteCallback->onRequestQueueEmpty();
+    }
+}
+
+void CameraOfflineSessionClient::notifyRepeatingRequestError(long /*lastFrameNumber*/) {
+    ALOGE("%s: Unexpected repeating request error in offline mode!", __FUNCTION__);
+    notifyError(hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DEVICE,
+                CaptureResultExtras());
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index e92a05c..b0f000d 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -19,6 +19,8 @@
 
 #include <android/hardware/camera2/BnCameraOfflineSession.h>
 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include "common/FrameProcessorBase.h"
+#include "common/CameraDeviceBase.h"
 #include "CameraService.h"
 #include "CompositeStream.h"
 
@@ -35,8 +37,9 @@
 // is created through ICameraDeviceUser::switchToOffline call.
 class CameraOfflineSessionClient :
         public CameraService::BasicClient,
-        public hardware::camera2::BnCameraOfflineSession
-        // public camera2::FrameProcessorBase::FilteredListener?
+        public hardware::camera2::BnCameraOfflineSession,
+        public camera2::FrameProcessorBase::FilteredListener,
+        public NotificationListener
 {
 public:
     CameraOfflineSessionClient(
@@ -58,42 +61,45 @@
 
     virtual ~CameraOfflineSessionClient() {}
 
-    virtual sp<IBinder> asBinderWrapper() override {
+    sp<IBinder> asBinderWrapper() override {
         return IInterface::asBinder(this);
     }
 
-    virtual binder::Status disconnect() override;
+    binder::Status disconnect() override;
 
-    virtual status_t dump(int /*fd*/, const Vector<String16>& /*args*/) override;
+    status_t dump(int /*fd*/, const Vector<String16>& /*args*/) override;
 
-    virtual status_t dumpClient(int /*fd*/, const Vector<String16>& /*args*/) override;
+    status_t dumpClient(int /*fd*/, const Vector<String16>& /*args*/) override;
 
-    virtual void notifyError(int32_t /*errorCode*/,
-            const CaptureResultExtras& /*resultExtras*/) override;
-
-    virtual status_t initialize(sp<CameraProviderManager> /*manager*/,
+    status_t initialize(sp<CameraProviderManager> /*manager*/,
             const String8& /*monitorTags*/) override;
 
     // permissions management
-    virtual status_t startCameraOps() override;
-    virtual status_t finishCameraOps() override;
+    status_t startCameraOps() override;
+    status_t finishCameraOps() override;
 
-    // TODO: Those will be introduced when we implement FilteredListener and the device
-    // callbacks respectively. Just adding for now.
-    void onResultAvailable(const CaptureResult& result);
-    void notifyShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp);
+    // FilteredResultListener API
+    void onResultAvailable(const CaptureResult& result) override;
+
+    // NotificationListener API
+    void notifyError(int32_t errorCode, const CaptureResultExtras& resultExtras) override;
+    void notifyShutter(const CaptureResultExtras& resultExtras, nsecs_t timestamp) override;
+    void notifyIdle() override;
+    void notifyAutoFocus(uint8_t newState, int triggerId) override;
+    void notifyAutoExposure(uint8_t newState, int triggerId) override;
+    void notifyAutoWhitebalance(uint8_t newState, int triggerId) override;
+    void notifyPrepared(int streamId) override;
+    void notifyRequestQueueEmpty() override;
+    void notifyRepeatingRequestError(long lastFrameNumber) override;
 
 private:
-
-    const sp<hardware::camera2::ICameraDeviceCallbacks>& getRemoteCallback() {
-        return mRemoteCallback;
-    }
+    mutable Mutex mBinderSerializationLock;
 
     sp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
 
     sp<CameraOfflineSessionBase> mOfflineSession;
 
-    // Offline composite streams
+    // Offline composite stream map, output surface -> composite stream
     KeyedVector<sp<IBinder>, sp<CompositeStream>> mCompositeStreamMap;
 };