Merge "Camera NDK: New lifecycle for ACameraMetadata_fromCameraMetadata"
diff --git a/camera/ndk/NdkCameraMetadata.cpp b/camera/ndk/NdkCameraMetadata.cpp
index 1fec3e1..7d3a53e 100644
--- a/camera/ndk/NdkCameraMetadata.cpp
+++ b/camera/ndk/NdkCameraMetadata.cpp
@@ -81,15 +81,16 @@
 }
 
 // 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) {
+// cameraMetadata.getNativeMetadataPtr() and returns it as a std::shared_ptr<CameraMetadata>*.
+std::shared_ptr<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);
+    return reinterpret_cast<std::shared_ptr<CameraMetadata>* >(ret);
 }
 
 }  // namespace
@@ -179,10 +180,9 @@
         return nullptr;
     }
 
-    CameraMetadata* src = CameraMetadata_getNativeMetadataPtr(env,
-                                                              cameraMetadata);
-    ACameraMetadata* output = new ACameraMetadata(src, type);
+    auto sharedData = CameraMetadata_getNativeMetadataPtr(env, cameraMetadata);
+    ACameraMetadata* output = new ACameraMetadata(*sharedData, type);
     output->incStrong(/*id=*/(void*) ACameraMetadata_fromCameraMetadata);
     return output;
 }
-#endif  /* __ANDROID_VNDK__ */
\ No newline at end of file
+#endif  /* __ANDROID_VNDK__ */
diff --git a/camera/ndk/impl/ACameraMetadata.cpp b/camera/ndk/impl/ACameraMetadata.cpp
index 18c5d3c..1bbb9c2 100644
--- a/camera/ndk/impl/ACameraMetadata.cpp
+++ b/camera/ndk/impl/ACameraMetadata.cpp
@@ -28,33 +28,24 @@
  * ACameraMetadata Implementation
  */
 ACameraMetadata::ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type) :
-        mData(new CameraMetadata(buffer)),
-        mOwnsData(true),
+        mData(std::make_shared<CameraMetadata>(buffer)),
         mType(type) {
     init();
 }
 
-ACameraMetadata::ACameraMetadata(CameraMetadata* cameraMetadata, ACAMERA_METADATA_TYPE type) :
+ACameraMetadata::ACameraMetadata(const std::shared_ptr<CameraMetadata>& cameraMetadata,
+        ACAMERA_METADATA_TYPE type) :
         mData(cameraMetadata),
-        mOwnsData(false),
         mType(type) {
     init();
 }
 
 ACameraMetadata::ACameraMetadata(const ACameraMetadata& other) :
-        mOwnsData(other.mOwnsData),
+        mData(std::make_shared<CameraMetadata>(*(other.mData))),
         mType(other.mType) {
-    if (other.mOwnsData) {
-        mData = new CameraMetadata(*(other.mData));
-    } else {
-        mData = other.mData;
-    }
 }
 
 ACameraMetadata::~ACameraMetadata() {
-    if (mOwnsData) {
-        delete mData;
-    }
 }
 
 void
@@ -373,7 +364,7 @@
 
     Mutex::Autolock _l(mLock);
 
-    camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData)->find(tag);
+    camera_metadata_ro_entry rawEntry = static_cast<const CameraMetadata*>(mData.get())->find(tag);
     if (rawEntry.count == 0) {
         ALOGE("%s: cannot find metadata tag %d", __FUNCTION__, tag);
         return ACAMERA_ERROR_METADATA_NOT_FOUND;
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index a57b2ff..084a60b 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -18,6 +18,7 @@
 
 #include <unordered_set>
 #include <vector>
+#include <memory>
 
 #include <sys/types.h>
 #include <utils/Mutex.h>
@@ -50,14 +51,13 @@
     // Constructs a ACameraMetadata that takes ownership of `buffer`.
     ACameraMetadata(camera_metadata_t* buffer, ACAMERA_METADATA_TYPE type);
 
-    // Constructs a ACameraMetadata that is a view of `cameraMetadata`.
-    // `cameraMetadata` will not be deleted by ~ACameraMetadata().
-    ACameraMetadata(CameraMetadata* cameraMetadata, ACAMERA_METADATA_TYPE type);
+    // Constructs a ACameraMetadata that shares its data with something else, like a Java object
+    ACameraMetadata(const std::shared_ptr<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.
+    // Always makes a deep copy.
     ACameraMetadata(const ACameraMetadata& other);
 
     ~ACameraMetadata();
@@ -125,9 +125,7 @@
     // Guard access of public APIs: get/update/getTags.
     mutable Mutex mLock;
 
-    CameraMetadata* mData;
-    // If true, has ownership of mData. Otherwise, mData is a view of an external instance.
-    bool mOwnsData;
+    std::shared_ptr<CameraMetadata> mData;
 
     mutable Vector<uint32_t> mTags; // Updated by `getTags()`, cleared by `update()`.
     const ACAMERA_METADATA_TYPE mType;
diff --git a/camera/ndk/include/camera/NdkCameraMetadata.h b/camera/ndk/include/camera/NdkCameraMetadata.h
index ee75610..072bb02 100644
--- a/camera/ndk/include/camera/NdkCameraMetadata.h
+++ b/camera/ndk/include/camera/NdkCameraMetadata.h
@@ -274,10 +274,9 @@
  * <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()}.
+ * <p>The ACameraMetadata maintains a reference count to the underlying data, so
+ * it can be used independently of the Java object, and it remains valid even if
+ * the Java metadata is garbage collected.
  *
  * @param env the JNI environment.
  * @param cameraMetadata the source {@link android.hardware.camera2.CameraMetadata} from which the
@@ -297,4 +296,4 @@
 
 #endif /* _NDK_CAMERA_METADATA_H */
 
-/** @} */
\ No newline at end of file
+/** @} */