Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2c5b3c2f authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add ACameraMetadata_fromCameraMetadata."

parents 8bd56112 9f713e83
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -57,6 +57,9 @@ cc_library_shared {
        "libmediandk",
        "libnativewindow",
    ],
    header_libs: [
        "jni_headers",
    ],
    cflags: [
        "-fvisibility=hidden",
        "-DEXPORT=__attribute__ ((visibility (\"default\")))",
@@ -121,7 +124,6 @@ cc_library_shared {
        "android.frameworks.cameraservice.common@2.0",
        "android.frameworks.cameraservice.service@2.0",
    ],

    static_libs: [
        "android.hardware.camera.common@1.0-helper",
        "libarect",
+94 −1
Original line number Diff line number Diff line
@@ -26,6 +26,68 @@

using namespace android;

#ifndef __ANDROID_VNDK__
namespace {

constexpr const char* android_hardware_camera2_CameraMetadata_jniClassName =
    "android/hardware/camera2/CameraMetadata";
constexpr const char* android_hardware_camera2_CameraCharacteristics_jniClassName =
    "android/hardware/camera2/CameraCharacteristics";
constexpr const char* android_hardware_camera2_CaptureResult_jniClassName =
    "android/hardware/camera2/CaptureResult";

jclass android_hardware_camera2_CameraCharacteristics_clazz = nullptr;
jclass android_hardware_camera2_CaptureResult_clazz = nullptr;
jmethodID android_hardware_camera2_CameraMetadata_getNativeMetadataPtr = nullptr;

// Called at most once to initializes global variables used by JNI.
bool InitJni(JNIEnv* env) {
    // From C++11 onward, static initializers are guaranteed to be executed at most once,
    // even if called from multiple threads.
    static bool ok = [env]() -> bool {
        const jclass cameraMetadataClazz = env->FindClass(
            android_hardware_camera2_CameraMetadata_jniClassName);
        if (cameraMetadataClazz == nullptr) {
            return false;
        }
        android_hardware_camera2_CameraMetadata_getNativeMetadataPtr =
            env->GetMethodID(cameraMetadataClazz, "getNativeMetadataPtr", "()J");
        if (android_hardware_camera2_CameraMetadata_getNativeMetadataPtr == nullptr) {
            return false;
        }

        android_hardware_camera2_CameraCharacteristics_clazz = env->FindClass(
            android_hardware_camera2_CameraCharacteristics_jniClassName);
        if (android_hardware_camera2_CameraCharacteristics_clazz == nullptr) {
            return false;
        }

        android_hardware_camera2_CaptureResult_clazz = env->FindClass(
            android_hardware_camera2_CaptureResult_jniClassName);
        if (android_hardware_camera2_CaptureResult_clazz == nullptr) {
            return false;
        }

        return true;
    }();
    return ok;
}

// Given cameraMetadata, an instance of android.hardware.camera2.CameraMetadata, invokes
// cameraMetadata.getNativeMetadataPtr() and returns it as a CameraMetadata*.
CameraMetadata* CameraMetadata_getNativeMetadataPtr(JNIEnv* env, jobject cameraMetadata) {
    if (cameraMetadata == nullptr) {
        ALOGE("%s: Invalid Java CameraMetadata object.", __FUNCTION__);
        return nullptr;
    }
    jlong ret = env->CallLongMethod(cameraMetadata,
                                    android_hardware_camera2_CameraMetadata_getNativeMetadataPtr);
    return reinterpret_cast<CameraMetadata *>(ret);
}

}  // namespace
#endif  /* __ANDROID_VNDK__ */

EXPORT
camera_status_t ACameraMetadata_getConstEntry(
        const ACameraMetadata* acm, uint32_t tag, ACameraMetadata_const_entry* entry) {
@@ -58,7 +120,7 @@ ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src) {
        return nullptr;
    }
    ACameraMetadata* copy = new ACameraMetadata(*src);
    copy->incStrong((void*) ACameraMetadata_copy);
    copy->incStrong(/*id=*/(void*) ACameraMetadata_copy);
    return copy;
}

@@ -86,3 +148,34 @@ bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,

    return staticMetadata->isLogicalMultiCamera(numPhysicalCameras, physicalCameraIds);
}

#ifndef __ANDROID_VNDK__
EXPORT
ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata) {
    ATRACE_CALL();

    const bool ok = InitJni(env);
    LOG_ALWAYS_FATAL_IF(!ok, "Failed to find CameraMetadata Java classes.");

    if (cameraMetadata == nullptr) {
        return nullptr;
    }

    ACameraMetadata::ACAMERA_METADATA_TYPE type;
    if (env->IsInstanceOf(cameraMetadata,
        android_hardware_camera2_CameraCharacteristics_clazz)) {
        type = ACameraMetadata::ACM_CHARACTERISTICS;
    } else if (env->IsInstanceOf(cameraMetadata,
        android_hardware_camera2_CaptureResult_clazz)) {
        type = ACameraMetadata::ACM_RESULT;
    } else {
        return nullptr;
    }

    CameraMetadata* src = CameraMetadata_getNativeMetadataPtr(env,
                                                              cameraMetadata);
    ACameraMetadata* output = new ACameraMetadata(src, type);
    output->incStrong(/*id=*/(void*) ACameraMetadata_fromCameraMetadata);
    return output;
}
#endif  /* __ANDROID_VNDK__ */
 No newline at end of file
+48 −18
Original line number Diff line number Diff line
@@ -28,7 +28,37 @@ using namespace android;
 * ACameraMetadata Implementation
 */
ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type) :
        mData(buffer), mType(type) {
        mData(new CameraMetadata(buffer)),
        mOwnsData(true),
        mType(type) {
    init();
}

ACameraMetadata::ACameraMetadata(CameraMetadata* cameraMetadata, ACAMERA_METADATA_TYPE type) :
        mData(cameraMetadata),
        mOwnsData(false),
        mType(type) {
    init();
}

ACameraMetadata::ACameraMetadata(const ACameraMetadata& other) :
        mOwnsData(other.mOwnsData),
        mType(other.mType) {
    if (other.mOwnsData) {
        mData = new CameraMetadata(*(other.mData));
    } else {
        mData = other.mData;
    }
}

ACameraMetadata::~ACameraMetadata() {
    if (mOwnsData) {
        delete mData;
    }
}

void
ACameraMetadata::init() {
    if (mType == ACM_CHARACTERISTICS) {
        filterUnsupportedFeatures();
        filterStreamConfigurations();
@@ -61,7 +91,7 @@ ACameraMetadata::isNdkSupportedCapability(int32_t capability) {
void
ACameraMetadata::filterUnsupportedFeatures() {
    // Hide unsupported capabilities (reprocessing)
    camera_metadata_entry entry = mData.find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
    camera_metadata_entry entry = mData->find(ANDROID_REQUEST_AVAILABLE_CAPABILITIES);
    if (entry.count == 0 || entry.type != TYPE_BYTE) {
        ALOGE("%s: malformed available capability key! count %zu, type %d",
                __FUNCTION__, entry.count, entry.type);
@@ -80,7 +110,7 @@ ACameraMetadata::filterUnsupportedFeatures() {
            }
        }
    }
    mData.update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
    mData->update(ANDROID_REQUEST_AVAILABLE_CAPABILITIES, capabilities);
}

void
@@ -118,7 +148,7 @@ ACameraMetadata::filterDurations(uint32_t tag) {
    const int STREAM_WIDTH_OFFSET = 1;
    const int STREAM_HEIGHT_OFFSET = 2;
    const int STREAM_DURATION_OFFSET = 3;
    camera_metadata_entry entry = mData.find(tag);
    camera_metadata_entry entry = mData->find(tag);
    if (entry.count == 0 || entry.count % 4 || entry.type != TYPE_INT64) {
        ALOGE("%s: malformed duration key %d! count %zu, type %d",
                __FUNCTION__, tag, entry.count, entry.type);
@@ -194,7 +224,7 @@ ACameraMetadata::filterDurations(uint32_t tag) {
        }
    }

    mData.update(tag, filteredDurations);
    mData->update(tag, filteredDurations);
}

void
@@ -204,7 +234,7 @@ ACameraMetadata::filterStreamConfigurations() {
    const int STREAM_WIDTH_OFFSET = 1;
    const int STREAM_HEIGHT_OFFSET = 2;
    const int STREAM_IS_INPUT_OFFSET = 3;
    camera_metadata_entry entry = mData.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
    camera_metadata_entry entry = mData->find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
    if (entry.count > 0 && (entry.count % 4 || entry.type != TYPE_INT32)) {
        ALOGE("%s: malformed available stream configuration key! count %zu, type %d",
                __FUNCTION__, entry.count, entry.type);
@@ -234,10 +264,10 @@ ACameraMetadata::filterStreamConfigurations() {
    }

    if (filteredStreamConfigs.size() > 0) {
        mData.update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
        mData->update(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, filteredStreamConfigs);
    }

    entry = mData.find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
    entry = mData->find(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS);
    if (entry.count > 0 && (entry.count % 4 || entry.type != TYPE_INT32)) {
        ALOGE("%s: malformed available depth stream configuration key! count %zu, type %d",
                __FUNCTION__, entry.count, entry.type);
@@ -270,11 +300,11 @@ ACameraMetadata::filterStreamConfigurations() {
    }

    if (filteredDepthStreamConfigs.size() > 0) {
        mData.update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
        mData->update(ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
                filteredDepthStreamConfigs);
    }

    entry = mData.find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
    entry = mData->find(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS);
    Vector<int32_t> filteredHeicStreamConfigs;
    filteredHeicStreamConfigs.setCapacity(entry.count);

@@ -297,9 +327,9 @@ ACameraMetadata::filterStreamConfigurations() {
        filteredHeicStreamConfigs.push_back(height);
        filteredHeicStreamConfigs.push_back(isInput);
    }
    mData.update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);
    mData->update(ANDROID_HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS, filteredHeicStreamConfigs);

    entry = mData.find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
    entry = mData->find(ANDROID_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS);
    Vector<int32_t> filteredDynamicDepthStreamConfigs;
    filteredDynamicDepthStreamConfigs.setCapacity(entry.count);

@@ -322,7 +352,7 @@ ACameraMetadata::filterStreamConfigurations() {
        filteredDynamicDepthStreamConfigs.push_back(height);
        filteredDynamicDepthStreamConfigs.push_back(isInput);
    }
    mData.update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
    mData->update(ACAMERA_DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS,
            filteredDynamicDepthStreamConfigs);
}

@@ -343,7 +373,7 @@ ACameraMetadata::getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry)

    Mutex::Autolock _l(mLock);

    camera_metadata_ro_entry rawEntry = mData.find(tag);
    camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData)->find(tag);
    if (rawEntry.count == 0) {
        ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
        return ACAMERA_ERROR_METADATA_NOT_FOUND;
@@ -390,9 +420,9 @@ ACameraMetadata::getTags(/*out*/int32_t* numTags,
                         /*out*/const uint32_t** tags) const {
    Mutex::Autolock _l(mLock);
    if (mTags.size() == 0) {
        size_t entry_count = mData.entryCount();
        size_t entry_count = mData->entryCount();
        mTags.setCapacity(entry_count);
        const camera_metadata_t* rawMetadata = mData.getAndLock();
        const camera_metadata_t* rawMetadata = mData->getAndLock();
        for (size_t i = 0; i < entry_count; i++) {
            camera_metadata_ro_entry_t entry;
            int ret = get_camera_metadata_ro_entry(rawMetadata, i, &entry);
@@ -405,7 +435,7 @@ ACameraMetadata::getTags(/*out*/int32_t* numTags,
                mTags.push_back(entry.tag);
            }
        }
        mData.unlock(rawMetadata);
        mData->unlock(rawMetadata);
    }

    *numTags = mTags.size();
@@ -415,7 +445,7 @@ ACameraMetadata::getTags(/*out*/int32_t* numTags,

const CameraMetadata&
ACameraMetadata::getInternalData() const {
    return mData;
    return (*mData);
}

bool
+29 −13
Original line number Diff line number Diff line
@@ -36,8 +36,8 @@ using CameraMetadata = android::hardware::camera::common::V1_0::helper::CameraMe
using namespace android;

/**
 * ACameraMetadata opaque struct definition
 * Leave outside of android namespace because it's NDK struct
 * ACameraMetadata is an opaque struct definition.
 * It is intentionally left outside of the android namespace because it's NDK struct.
 */
struct ACameraMetadata : public RefBase {
  public:
@@ -47,11 +47,20 @@ struct ACameraMetadata : public RefBase {
        ACM_RESULT,          // Read only
    } ACAMERA_METADATA_TYPE;

    // Takes ownership of pass-in buffer
    // Constructs a ACameraMetadata that takes ownership of `buffer`.
    ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type);
    // Clone
    ACameraMetadata(const ACameraMetadata& other) :
            mData(other.mData), mType(other.mType) {};

    // Constructs a ACameraMetadata that is a view of `cameraMetadata`.
    // `cameraMetadata` will not be deleted by ~ACameraMetadata().
    ACameraMetadata(CameraMetadata* cameraMetadata, ACAMERA_METADATA_TYPE type);

    // Copy constructor.
    //
    // If `other` owns its CameraMetadata, then makes a deep copy.
    // Otherwise, the new instance is also a view of the same data.
    ACameraMetadata(const ACameraMetadata& other);

    ~ACameraMetadata();

    camera_status_t getConstEntry(uint32_t tag, ACameraMetadata_const_entry* entry) const;

@@ -70,6 +79,9 @@ struct ACameraMetadata : public RefBase {

  private:

    // Common code called by constructors.
    void init();

    // This function does not check whether the capability passed to it is valid.
    // The caller must make sure that it is.
    bool isNdkSupportedCapability(const int32_t capability);
@@ -95,11 +107,11 @@ struct ACameraMetadata : public RefBase {

        status_t ret = OK;
        if (count == 0 && data == nullptr) {
            ret = mData.erase(tag);
            ret = mData->erase(tag);
        } else {
            // Here we have to use reinterpret_cast because the NDK data type is
            // exact copy of internal data type but they do not inherit from each other
            ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
            ret = mData->update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
        }

        if (ret == OK) {
@@ -110,10 +122,14 @@ struct ACameraMetadata : public RefBase {
        }
    }

    // guard access of public APIs: get/update/getTags
    // Guard access of public APIs: get/update/getTags.
    mutable Mutex mLock;
    CameraMetadata   mData;
    mutable Vector<uint32_t> mTags; // updated in getTags, cleared by update

    CameraMetadata* mData;
    // If true, has ownership of mData. Otherwise, mData is a view of an external instance.
    bool mOwnsData;

    mutable Vector<uint32_t> mTags; // Updated by `getTags()`, cleared by `update()`.
    const ACAMERA_METADATA_TYPE mType;

    static std::unordered_set<uint32_t> sSystemTags;
+39 −1
Original line number Diff line number Diff line
@@ -39,6 +39,12 @@
#include <stdint.h>
#include <sys/cdefs.h>

#ifndef __ANDROID_VNDK__
#if __ANDROID_API__ >= 30
#include "jni.h"
#endif  /* __ANDROID_API__ >= 30 */
#endif  /* __ANDROID_VNDK__ */

#include "NdkCameraError.h"
#include "NdkCameraMetadataTags.h"

@@ -255,6 +261,38 @@ bool ACameraMetadata_isLogicalMultiCamera(const ACameraMetadata* staticMetadata,

#endif /* __ANDROID_API__ >= 29 */

#ifndef __ANDROID_VNDK__
#if __ANDROID_API__ >= 30

/**
 * Return a {@link ACameraMetadata} that references the same data as
 * {@link cameraMetadata}, which is an instance of
 * {@link android.hardware.camera2.CameraMetadata} (e.g., a
 * {@link android.hardware.camera2.CameraCharacteristics} or
 * {@link android.hardware.camera2.CaptureResult}).
 *
 * <p>The returned ACameraMetadata must be freed by the application by {@link ACameraMetadata_free}
 * after application is done using it.</p>
 *
 * <p>This function does not affect the lifetime of {@link cameraMetadata}. Attempting to use the
 * returned ACameraMetadata object after {@link cameraMetadata} has been garbage collected is
 * unsafe. To manage the lifetime beyond the current JNI function call, use
 * {@code env->NewGlobalRef()} and {@code env->DeleteGlobalRef()}.
 *
 * @param env the JNI environment.
 * @param cameraMetadata the source {@link android.hardware.camera2.CameraMetadata} from which the
 *                       returned {@link ACameraMetadata} is a view.
 *
 * @return a valid ACameraMetadata pointer or NULL if {@link cameraMetadata} is null or not a valid
 *         instance of {@link android.hardware.camera2.CameraMetadata}.
 *
 */
ACameraMetadata* ACameraMetadata_fromCameraMetadata(JNIEnv* env, jobject cameraMetadata)
        __INTRODUCED_IN(30);

#endif /* __ANDROID_API__ >= 30 */
#endif  /* __ANDROID_VNDK__ */

__END_DECLS

#endif /* _NDK_CAMERA_METADATA_H */
Loading