aidl: camera: Implement support for torch strength levels

Change-Id: Iedd0e3acbc2dc3458366c3dec31dc3203eccf026
diff --git a/aidl/camera/common/Android.bp b/aidl/camera/common/Android.bp
index 3a7c254..9df08fc 100644
--- a/aidl/camera/common/Android.bp
+++ b/aidl/camera/common/Android.bp
@@ -12,6 +12,7 @@
         "VendorTagDescriptor.cpp",
         "HandleImporter.cpp",
         "Exif.cpp",
+        "SamsungCameraModule.cpp",
         "SimpleThread.cpp",
     ],
     cflags: [
@@ -29,7 +30,7 @@
     ],
     include_dirs: ["system/media/private/camera/include"],
     header_libs: ["libhardware_headers.camera3_samsung"],
-    export_include_dirs: ["include"],
+    export_include_dirs: ["include", "include_samsung"],
     export_shared_lib_headers: ["libui"],
 }
 
diff --git a/aidl/camera/common/SamsungCameraModule.cpp b/aidl/camera/common/SamsungCameraModule.cpp
new file mode 100644
index 0000000..73f52fb
--- /dev/null
+++ b/aidl/camera/common/SamsungCameraModule.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2024 The LineageOS Project
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#define LOG_TAG "CamComm1.0-SamsungCamModule"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+
+#include <SamsungCameraModule.h>
+#include <cutils/trace.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace helper {
+
+SamsungCameraModule::SamsungCameraModule(camera_module_t* module)
+    : CameraModule(module), mModule(module) {}
+
+SamsungCameraModule::~SamsungCameraModule() {}
+
+bool SamsungCameraModule::isSetTorchModeStrengthSupported() {
+    return isSetTorchModeSupported() && mModule->set_torch_mode_strength != NULL;
+}
+
+int SamsungCameraModule::setTorchModeStrength(const char* camera_id, bool enable, int strength) {
+    int res = INVALID_OPERATION;
+    if (mModule->set_torch_mode_strength != NULL) {
+        ATRACE_BEGIN("camera_module->set_torch_mode_strength");
+        res = mModule->set_torch_mode_strength(camera_id, enable, strength);
+        ATRACE_END();
+    }
+    return res;
+}
+
+}  // namespace helper
+}  // namespace common
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/aidl/camera/common/include_samsung/SamsungCameraModule.h b/aidl/camera/common/include_samsung/SamsungCameraModule.h
new file mode 100644
index 0000000..2ada92f
--- /dev/null
+++ b/aidl/camera/common/include_samsung/SamsungCameraModule.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The LineageOS Project
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#pragma once
+
+#include <CameraModule.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace helper {
+
+class SamsungCameraModule : public CameraModule {
+  public:
+    explicit SamsungCameraModule(camera_module_t* module);
+    virtual ~SamsungCameraModule();
+
+    bool isSetTorchModeStrengthSupported();
+    int setTorchModeStrength(const char* camera_id, bool enable, int strength);
+
+  private:
+    camera_module_t* mModule;
+};
+
+}  // namespace helper
+}  // namespace common
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/aidl/camera/device/CameraDevice.cpp b/aidl/camera/device/CameraDevice.cpp
index 96d7eed..65cba8d 100644
--- a/aidl/camera/device/CameraDevice.cpp
+++ b/aidl/camera/device/CameraDevice.cpp
@@ -20,7 +20,7 @@
 std::string CameraDevice::kDeviceVersion = "1.1";
 
 CameraDevice::CameraDevice(
-        sp<CameraModule> module, const std::string& cameraId,
+        sp<SamsungCameraModule> module, const std::string& cameraId,
         const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames)
     : mModule(module),
       mCameraId(cameraId),
@@ -65,8 +65,18 @@
         // Module 2.1+ codepath.
         struct camera_info info;
         int ret = mModule->getCameraInfo(mCameraIdInt, &info);
-        if (ret == OK) {
-            convertToAidl(info.static_camera_characteristics, _aidl_return);
+        if (ret == OK && info.static_camera_characteristics != NULL) {
+            common::helper::CameraMetadata metadata = (camera_metadata_t*)info.static_camera_characteristics;
+            camera_metadata_entry_t entry = metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
+            if (entry.count > 0 && *entry.data.u8 != 0 && mModule->isSetTorchModeStrengthSupported()) {
+                // Samsung always has 5 supported torch strength levels
+                int32_t defaultTorchStrength = 1;
+                int32_t torchStrengthLevels = 5;
+                metadata.update(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &defaultTorchStrength, 1);
+                metadata.update(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, &torchStrengthLevels, 1);
+            }
+
+            convertToAidl(metadata.release(), _aidl_return);
         } else {
             ALOGE("%s: get camera info failed!", __FUNCTION__);
             status = Status::INTERNAL_ERROR;
@@ -347,16 +357,36 @@
     Status status = initStatus();
     if (status == Status::OK) {
         status = getAidlStatus(mModule->setTorchMode(mCameraId.c_str(), in_on));
+        if (status == Status::OK) {
+            mTorchStrengthLevel = 1;
+        }
     }
     return fromStatus(status);
 }
 
-ndk::ScopedAStatus CameraDevice::turnOnTorchWithStrengthLevel(int32_t) {
-    return fromStatus(Status::OPERATION_NOT_SUPPORTED);
+ndk::ScopedAStatus CameraDevice::turnOnTorchWithStrengthLevel(int32_t in_torchStrength) {
+    if (!mModule->isSetTorchModeStrengthSupported()) {
+        return fromStatus(Status::OPERATION_NOT_SUPPORTED);
+    }
+
+    Status status = initStatus();
+    if (status == Status::OK) {
+        status = getAidlStatus(
+                mModule->setTorchModeStrength(mCameraId.c_str(), true, in_torchStrength));
+        if (status == Status::OK) {
+            mTorchStrengthLevel = in_torchStrength;
+        }
+    }
+    return fromStatus(status);
 }
 
-ndk::ScopedAStatus CameraDevice::getTorchStrengthLevel(int32_t*) {
-    return fromStatus(Status::OPERATION_NOT_SUPPORTED);
+ndk::ScopedAStatus CameraDevice::getTorchStrengthLevel(int32_t* _aidl_return) {
+    if (!mModule->isSetTorchModeSupported()) {
+        return fromStatus(Status::OPERATION_NOT_SUPPORTED);
+    }
+
+    *_aidl_return = mTorchStrengthLevel;
+    return fromStatus(Status::OK);
 }
 
 std::shared_ptr<CameraDeviceSession> CameraDevice::createSession(
diff --git a/aidl/camera/device/CameraDevice.h b/aidl/camera/device/CameraDevice.h
index a41c496..61f4e8c 100644
--- a/aidl/camera/device/CameraDevice.h
+++ b/aidl/camera/device/CameraDevice.h
@@ -8,7 +8,7 @@
 
 #include "CameraDeviceSession.h"
 
-#include <CameraModule.h>
+#include <SamsungCameraModule.h>
 #include <aidl/android/hardware/camera/common/Status.h>
 #include <aidl/android/hardware/camera/device/BnCameraDevice.h>
 
@@ -26,7 +26,7 @@
 using ::aidl::android::hardware::camera::device::ICameraDeviceSession;
 using ::aidl::android::hardware::camera::device::ICameraInjectionSession;
 using ::aidl::android::hardware::camera::device::StreamConfiguration;
-using ::android::hardware::camera::common::helper::CameraModule;
+using ::android::hardware::camera::common::helper::SamsungCameraModule;
 
 class CameraDevice : public BnCameraDevice {
   public:
@@ -35,7 +35,7 @@
     // be multiple CameraDevice trying to access the same physical camera.  Also, provider will have
     // to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
     // camera is detached.
-    CameraDevice(sp<CameraModule> module, const std::string& cameraId,
+    CameraDevice(sp<SamsungCameraModule> module, const std::string& cameraId,
                  const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
     virtual ~CameraDevice();
 
@@ -70,7 +70,7 @@
             camera3_device_t*, const camera_metadata_t* deviceInfo,
             const std::shared_ptr<ICameraDeviceCallback>&);
 
-    const sp<CameraModule> mModule;
+    const sp<SamsungCameraModule> mModule;
     const std::string mCameraId;
     // const after ctor
     int mCameraIdInt;
@@ -79,6 +79,7 @@
     // Set by provider (when external camera is connected/disconnected)
     bool mDisconnected;
     std::weak_ptr<CameraDeviceSession> mSession{};
+    int32_t mTorchStrengthLevel = 1;
 
     const SortedVector<std::pair<std::string, std::string>>& mCameraDeviceNames;
 
diff --git a/aidl/camera/device/CameraDeviceSession.cpp b/aidl/camera/device/CameraDeviceSession.cpp
index df79f28..157b6fa 100644
--- a/aidl/camera/device/CameraDeviceSession.cpp
+++ b/aidl/camera/device/CameraDeviceSession.cpp
@@ -9,7 +9,7 @@
 
 #include "CameraDeviceSession.h"
 
-#include <CameraModule.h>
+#include <SamsungCameraModule.h>
 #include <aidl/android/hardware/camera/device/ErrorMsg.h>
 #include <aidl/android/hardware/camera/device/ShutterMsg.h>
 #include <aidlcommonsupport/NativeHandle.h>
@@ -28,7 +28,7 @@
 using ::aidl::android::hardware::camera::device::ShutterMsg;
 using ::aidl::android::hardware::camera::device::StreamType;
 using ::aidl::android::hardware::graphics::common::BufferUsage;
-using ::android::hardware::camera::common::helper::CameraModule;
+using ::android::hardware::camera::common::helper::SamsungCameraModule;
 
 // Size of request metadata fast message queue. Change to 0 to always use hwbinder buffer.
 static constexpr int32_t CAMERA_REQUEST_METADATA_QUEUE_SIZE = 1 << 20 /* 1MB */;
@@ -78,7 +78,7 @@
         mDerivePostRawSensKey = true;
     }
 
-    (void)CameraModule::isLogicalMultiCamera(mDeviceInfo, &mPhysicalCameraIds);
+    (void)SamsungCameraModule::isLogicalMultiCamera(mDeviceInfo, &mPhysicalCameraIds);
 
     mInitFail = initialize();
 }
diff --git a/aidl/camera/libhardware_headers/include/hardware/camera_common.h b/aidl/camera/libhardware_headers/include/hardware/camera_common.h
index dc0ad25..882773d 100644
--- a/aidl/camera/libhardware_headers/include/hardware/camera_common.h
+++ b/aidl/camera/libhardware_headers/include/hardware/camera_common.h
@@ -1241,6 +1241,14 @@
      */
     void (*notify_device_state_change)(uint64_t deviceState);
 
+    /**
+     * set_torch_mode_strength:
+     *
+     * Same as set_torch_mode but with support for specifying the strength level.
+     *
+     */
+    int (*set_torch_mode_strength)(const char* camera_id, bool enabled, int32_t strength);
+
     /* reserved for future use */
     void* reserved[2];
 } camera_module_t;
diff --git a/aidl/camera/provider/CameraProvider.cpp b/aidl/camera/provider/CameraProvider.cpp
index 329c34b..f81e253 100644
--- a/aidl/camera/provider/CameraProvider.cpp
+++ b/aidl/camera/provider/CameraProvider.cpp
@@ -189,7 +189,7 @@
         return true;
     }
 
-    mModule = new CameraModule(rawModule);
+    mModule = new SamsungCameraModule(rawModule);
     err = mModule->init();
     if (err != OK) {
         ALOGE("Could not initialize camera HAL module: %d (%s)", err, strerror(-err));
diff --git a/aidl/camera/provider/CameraProvider.h b/aidl/camera/provider/CameraProvider.h
index 411b331..9fe9004 100644
--- a/aidl/camera/provider/CameraProvider.h
+++ b/aidl/camera/provider/CameraProvider.h
@@ -6,7 +6,7 @@
 
 #pragma once
 
-#include <CameraModule.h>
+#include <SamsungCameraModule.h>
 #include <VendorTagDescriptor.h>
 #include <aidl/android/hardware/camera/device/ICameraDevice.h>
 #include <aidl/android/hardware/camera/provider/BnCameraProvider.h>
@@ -26,7 +26,7 @@
 using ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination;
 using ::aidl::android::hardware::camera::provider::ConcurrentCameraIdCombination;
 using ::aidl::android::hardware::camera::provider::ICameraProviderCallback;
-using ::android::hardware::camera::common::helper::CameraModule;
+using ::android::hardware::camera::common::helper::SamsungCameraModule;
 
 class CameraProvider : public BnCameraProvider, protected camera_module_callbacks_t {
   public:
@@ -54,7 +54,7 @@
     Mutex mCbLock;
     std::shared_ptr<ICameraProviderCallback> mCallbacks = nullptr;
 
-    sp<CameraModule> mModule;
+    sp<SamsungCameraModule> mModule;
 
     int mNumberOfLegacyCameras;
     std::map<std::string, camera_device_status_t> mCameraStatusMap;  // camera id -> status