cameraservice: Copy camera characteristics from session characteristics

The getSessionCharacteristics call is meant to replace the output of
getCameraCharacteristics. The current implementation however passed
the output of HAL directly to the application, which could be missing
quite a few keys.

This CL uses the camera device's characteristics as the base
and copies over any updated values from the HAL instead. This will
ensure the output of getSessionCharacteristics matches the constraints
of getCameraCharacteristics.

Similarly, this CL also filters out any sensitive keys if
getSessionCharactersitics is called from a process that does not have
camera permission granted.

Bug: 303645857
Test: atest android.hardware.camera2.cts.CameraDeviceSetupTest passes
Test: atest android.hardware.camera2.cts.StaticMetadataTest passes
Change-Id: I589c80fc6152ae3cb14c72963953feb94a7f745a
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
index 14e5fad..48d78e1 100644
--- a/services/camera/libcameraservice/aidl/AidlUtils.cpp
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -18,6 +18,7 @@
 
 #include <aidl/AidlUtils.h>
 #include <aidl/ExtensionMetadataTags.h>
+#include <aidl/SessionCharacteristicsTags.h>
 #include <aidl/VndkVersionMetadataTags.h>
 #include <aidlcommonsupport/NativeHandle.h>
 #include <camera/StringUtils.h>
@@ -334,6 +335,49 @@
     return OK;
 }
 
+status_t copySessionCharacteristics(const CameraMetadata& from, CameraMetadata* to,
+                                    int queryVersion) {
+    // Ensure the vendor ID are the same before attempting
+    // anything else. If vendor IDs differ we cannot safely copy the characteristics.
+    if (from.getVendorId() != to->getVendorId()) {
+        ALOGE("%s: Incompatible CameraMetadata objects. Vendor IDs differ. From: %lu; To: %lu",
+              __FUNCTION__, from.getVendorId(), to->getVendorId());
+        return BAD_VALUE;
+    }
+
+    // Allow public tags according to the queryVersion
+    std::unordered_set<uint32_t> validPublicTags;
+    auto last = api_level_to_session_characteristic_keys.upper_bound(queryVersion);
+    for (auto it = api_level_to_session_characteristic_keys.begin(); it != last; it++) {
+        validPublicTags.insert(it->second.cbegin(), it->second.cend());
+    }
+
+    const camera_metadata_t* src = from.getAndLock();
+    camera_metadata_ro_entry_t entry{};
+    for (size_t i = 0; i < get_camera_metadata_entry_count(src); i++) {
+        int ret = get_camera_metadata_ro_entry(src, i, &entry);
+        if (ret != OK) {
+            ALOGE("%s: Could not fetch entry at index %lu. Error: %d", __FUNCTION__, i, ret);
+            from.unlock(src);
+            return BAD_VALUE;
+        }
+
+        if (entry.tag < (uint32_t)VENDOR_SECTION_START &&
+                validPublicTags.find(entry.tag) == validPublicTags.end()) {
+            ALOGI("%s: Session Characteristics contains tag %s but not supported by query version "
+                  "(%d)",
+                  __FUNCTION__, get_camera_metadata_tag_name(entry.tag), queryVersion);
+            continue;
+        }
+
+        // The entry is either a vendor tag, or a valid session characteristic key.
+        // Copy over the value
+        to->update(entry);
+    }
+    from.unlock(src);
+    return OK;
+}
+
 bool areExtensionKeysSupported(const CameraMetadata& metadata) {
     auto requestKeys = metadata.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
     if (requestKeys.count == 0) {