Camera NDK library: first draft

Bug: 23012001

Change-Id: I06d834421289d4dead1c87301a6ee94487ccf023
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
new file mode 100644
index 0000000..b68685d
--- /dev/null
+++ b/camera/ndk/impl/ACameraManager.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2015 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 _ACAMERA_MANAGER_H
+#define _ACAMERA_MANAGER_H
+
+#include "NdkCameraManager.h"
+
+#include <camera/CameraMetadata.h>
+#include <camera/ICameraService.h>
+#include <camera/ICameraServiceListener.h>
+#include <binder/IServiceManager.h>
+#include <utils/StrongPointer.h>
+#include <utils/Mutex.h>
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AHandler.h>
+#include <media/stagefright/foundation/AMessage.h>
+
+#include <set>
+#include <map>
+
+using namespace android;
+
+namespace android {
+
+/**
+ * Per-process singleton instance of CameraManger. Shared by all ACameraManager
+ * instances. Created when first ACameraManager is created and destroyed when
+ * all ACameraManager instances are deleted.
+ *
+ * TODO: maybe CameraManagerGlobal is better sutied in libcameraclient?
+ */
+class CameraManagerGlobal final : public RefBase {
+  public:
+    static CameraManagerGlobal& getInstance();
+    sp<ICameraService> getCameraService();
+
+    void registerAvailabilityCallback(
+            const ACameraManager_AvailabilityCallbacks *callback);
+    void unregisterAvailabilityCallback(
+            const ACameraManager_AvailabilityCallbacks *callback);
+
+  private:
+    sp<ICameraService> mCameraService;
+    const int          kCameraServicePollDelay = 500000; // 0.5s
+    const char*        kCameraServiceName      = "media.camera";
+    Mutex              mLock;
+
+    class DeathNotifier : public IBinder::DeathRecipient {
+      public:
+        DeathNotifier(CameraManagerGlobal* cm) : mCameraManager(cm) {}
+      protected:
+        // IBinder::DeathRecipient implementation
+        virtual void binderDied(const wp<IBinder>& who);
+      private:
+        const wp<CameraManagerGlobal> mCameraManager;
+    };
+    sp<DeathNotifier> mDeathNotifier;
+
+    class CameraServiceListener final : public BnCameraServiceListener {
+      public:
+        CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
+        virtual void onStatusChanged(Status status, int32_t cameraId);
+
+        // Torch API not implemented yet
+        virtual void onTorchStatusChanged(TorchStatus, const String16&) {};
+      private:
+        const wp<CameraManagerGlobal> mCameraManager;
+    };
+    sp<CameraServiceListener> mCameraServiceListener;
+
+    // Wrapper of ACameraManager_AvailabilityCallbacks so we can store it in std::set
+    struct Callback {
+        Callback(const ACameraManager_AvailabilityCallbacks *callback) :
+            mAvailable(callback->onCameraAvailable),
+            mUnavailable(callback->onCameraUnavailable),
+            mContext(callback->context) {}
+
+        bool operator == (const Callback& other) const {
+            return (mAvailable == other.mAvailable &&
+                    mUnavailable == other.mUnavailable &&
+                    mContext == other.mContext);
+        }
+        bool operator != (const Callback& other) const {
+            return !(*this == other);
+        }
+        bool operator < (const Callback& other) const {
+            if (*this == other) return false;
+            if (mContext != other.mContext) return mContext < other.mContext;
+            if (mAvailable != other.mAvailable) return mAvailable < other.mAvailable;
+            return mUnavailable < other.mUnavailable;
+        }
+        bool operator > (const Callback& other) const {
+            return (*this != other && !(*this < other));
+        }
+        ACameraManager_AvailabilityCallback mAvailable;
+        ACameraManager_AvailabilityCallback mUnavailable;
+        void*                               mContext;
+    };
+    std::set<Callback> mCallbacks;
+
+    // definition of handler and message
+    enum {
+        kWhatSendSingleCallback
+    };
+    static const char* kCameraIdKey;
+    static const char* kCallbackFpKey;
+    static const char* kContextKey;
+    class CallbackHandler : public AHandler {
+      public:
+        CallbackHandler() {}
+        void onMessageReceived(const sp<AMessage> &msg) override;
+      private:
+        inline void sendSingleCallback(
+                int32_t cameraId, void* context,
+                ACameraManager_AvailabilityCallback cb) const;
+    };
+    sp<CallbackHandler> mHandler;
+    sp<ALooper>         mCbLooper; // Looper thread where callbacks actually happen on
+
+    typedef ICameraServiceListener::Status Status;
+    void onStatusChanged(Status status, int32_t cameraId);
+    void onStatusChangedLocked(Status status, int32_t cameraId);
+    // Utils for status
+    static bool validStatus(Status status);
+    static bool isStatusAvailable(Status status);
+
+    // Map camera_id -> status
+    std::map<int32_t, Status> mDeviceStatusMap;
+
+    // For the singleton instance
+    static Mutex sLock;
+    static CameraManagerGlobal* sInstance;
+    CameraManagerGlobal() {};
+    ~CameraManagerGlobal();
+};
+
+} // namespace android;
+
+/**
+ * ACameraManager opaque struct definition
+ * Leave outside of android namespace because it's NDK struct
+ */
+struct ACameraManager {
+    ACameraManager() :
+            mCachedCameraIdList({kCameraIdListNotInit, nullptr}),
+            mGlobalManager(&(CameraManagerGlobal::getInstance())) {}
+    ~ACameraManager();
+    camera_status_t getCameraIdList(ACameraIdList** cameraIdList);
+    static void     deleteCameraIdList(ACameraIdList* cameraIdList);
+
+    camera_status_t getCameraCharacteristics(
+            const char *cameraId, ACameraMetadata **characteristics);
+    camera_status_t openCamera(const char* cameraId,
+                               ACameraDevice_StateCallbacks* callback,
+                               /*out*/ACameraDevice** device);
+
+  private:
+    camera_status_t getOrCreateCameraIdListLocked(ACameraIdList** cameraIdList);
+
+    enum {
+        kCameraIdListNotInit = -1
+    };
+    Mutex         mLock;
+    std::set<int> mCameraIds;          // Init by getOrCreateCameraIdListLocked
+    ACameraIdList mCachedCameraIdList; // Init by getOrCreateCameraIdListLocked
+    sp<CameraManagerGlobal> mGlobalManager;
+};
+
+#endif //_ACAMERA_MANAGER_H