Camera: add offline session API skeleton

Test: N/A, no implementation yet
Bug: 135142453
Change-Id: I497e42433d4d49466fe37467d4ff66e8583c55df
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 27bebde..28421ba 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -1901,6 +1901,80 @@
     return binder::Status::ok();
 }
 
+binder::Status CameraDeviceClient::switchToOffline(
+        const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+        const std::vector<view::Surface>& offlineOutputs,
+        /*out*/
+        sp<hardware::camera2::ICameraOfflineSession>* session) {
+    ATRACE_CALL();
+
+    binder::Status res;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    if (offlineOutputs.empty()) {
+        String8 msg = String8::format("Offline outputs must not be empty");
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    if (session == nullptr) {
+        String8 msg = String8::format("Invalid offline session");
+        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+    }
+
+    std::vector<int32_t> offlineStreamIds(offlineOutputs.size());
+    for (auto& surface : offlineOutputs) {
+        sp<IBinder> binder = IInterface::asBinder(surface.graphicBufferProducer);
+        ssize_t index = mStreamMap.indexOfKey(binder);
+        if (index == NAME_NOT_FOUND) {
+            String8 msg = String8::format("Offline output is invalid");
+            ALOGE("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
+        // TODO: Also check whether the offline output is supported by Hal for offline mode.
+
+        sp<Surface> s = new Surface(surface.graphicBufferProducer);
+        bool isCompositeStream = camera3::DepthCompositeStream::isDepthCompositeStream(s);
+        isCompositeStream |= camera3::HeicCompositeStream::isHeicCompositeStream(s);
+        if (isCompositeStream) {
+            // TODO: Add composite specific handling
+        } else {
+            offlineStreamIds.push_back(mStreamMap.valueAt(index).streamId());
+        }
+    }
+
+    sp<CameraOfflineSessionBase> offlineSession;
+    auto ret = mDevice->switchToOffline(offlineStreamIds, &offlineSession);
+    if (ret != OK) {
+        return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Camera %s: Error switching to offline mode: %s (%d)",
+                mCameraIdStr.string(), strerror(ret), ret);
+    }
+
+    sp<CameraOfflineSessionClient> offlineClient = new CameraOfflineSessionClient(sCameraService,
+            offlineSession, cameraCb, mClientPackageName, mCameraIdStr, mClientPid, mClientUid,
+            mServicePid);
+    ret = offlineClient->initialize();
+    if (ret == OK) {
+        // TODO: We need to update mStreamMap, mConfiguredOutputs
+    } else {
+        return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Camera %s: Failed to initilize offline session: %s (%d)",
+                mCameraIdStr.string(), strerror(ret), ret);
+    }
+
+    *session = offlineClient;
+
+    return binder::Status::ok();
+}
+
 status_t CameraDeviceClient::dump(int fd, const Vector<String16>& args) {
     return BasicClient::dump(fd, args);
 }
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 7efc5ab..0a8f377 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -23,6 +23,7 @@
 #include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
 
+#include "CameraOfflineSessionClient.h"
 #include "CameraService.h"
 #include "common/FrameProcessorBase.h"
 #include "common/Camera2ClientBase.h"
@@ -157,6 +158,12 @@
 
     virtual binder::Status getGlobalAudioRestriction(/*out*/int32_t* outMode) override;
 
+    virtual binder::Status switchToOffline(
+            const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+            const std::vector<view::Surface>& offlineOutputs,
+            /*out*/
+            sp<hardware::camera2::ICameraOfflineSession>* session) override;
+
     /**
      * Interface used by CameraService
      */
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
new file mode 100644
index 0000000..cb83e29
--- /dev/null
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
+#define ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H
+
+#include <android/hardware/camera2/BnCameraOfflineSession.h>
+#include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include "CameraService.h"
+
+namespace android {
+
+using android::hardware::camera2::ICameraDeviceCallbacks;
+
+class CameraOfflineSessionClient :
+        public CameraService::OfflineClient,
+        public hardware::camera2::BnCameraOfflineSession
+        // public camera2::FrameProcessorBase::FilteredListener?
+{
+public:
+    CameraOfflineSessionClient(
+            const sp<CameraService>& cameraService,
+            sp<CameraOfflineSessionBase> session,
+            const sp<ICameraDeviceCallbacks>& remoteCallback,
+            const String16& clientPackageName,
+            const String8& cameraIdStr,
+            int clientPid, uid_t clientUid, int servicePid) :
+                    CameraService::OfflineClient(cameraService, clientPackageName,
+                            cameraIdStr, clientPid, clientUid, servicePid),
+                            mRemoteCallback(remoteCallback), mOfflineSession(session) {}
+
+    ~CameraOfflineSessionClient() {}
+
+    virtual binder::Status disconnect() override { return binder::Status::ok(); }
+
+    virtual status_t dump(int /*fd*/, const Vector<String16>& /*args*/) override {
+        return OK;
+    }
+
+    // Block the client form using the camera
+    virtual void block() override {};
+
+    // Return the package name for this client
+    virtual String16 getPackageName() const override { String16 ret; return ret; };
+
+    // Notify client about a fatal error
+    // TODO: maybe let impl notify within block?
+    virtual void notifyError(int32_t /*errorCode*/,
+            const CaptureResultExtras& /*resultExtras*/) override {}
+
+    // Get the UID of the application client using this
+    virtual uid_t getClientUid() const override { return 0; }
+
+    // Get the PID of the application client using this
+    virtual int getClientPid() const override { return 0; }
+
+    status_t initialize() {
+        // TODO: Talk to camera service to add the offline session client book keeping
+        return OK;
+    }
+private:
+    sp<CameraOfflineSessionBase> mSession;
+
+    sp<hardware::camera2::ICameraDeviceCallbacks> mRemoteCallback;
+    // This class is responsible to convert HAL callbacks to AIDL callbacks
+
+    sp<CameraOfflineSessionBase> mOfflineSession;
+};
+
+} // namespace android
+
+#endif // ANDROID_SERVERS_CAMERA_PHOTOGRAPHY_CAMERAOFFLINESESSIONCLIENT_H