Merge "P requires 4.14.42" into pi-dev
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 91255d0..6af774e 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -41,6 +41,7 @@
         "VehicleAreaDoor",
         "VehicleAreaMirror",
         "VehicleAreaSeat",
+        "VehicleAreaWheel",
         "VehicleAreaWindow",
         "VehicleDisplay",
         "VehicleGear",
@@ -68,7 +69,6 @@
         "VmsOfferingMessageIntegerValuesIndex",
         "VmsPublisherInformationIntegerValuesIndex",
         "VmsSubscriptionsStateIntegerValuesIndex",
-        "Wheel",
     ],
     gen_java: true,
 }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index c1f80f4..4ae94c0 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -40,7 +40,8 @@
 constexpr int VEHICLE_MAP_SERVICE = (int)VehicleProperty::VEHICLE_MAP_SERVICE;
 constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK;
 constexpr int ALL_WHEELS =
-    (int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR);
+    (int)(VehicleAreaWheel::LEFT_FRONT | VehicleAreaWheel::RIGHT_FRONT |
+          VehicleAreaWheel::LEFT_REAR | VehicleAreaWheel::RIGHT_REAR);
 constexpr int HVAC_LEFT = (int)(VehicleAreaSeat::ROW_1_LEFT | VehicleAreaSeat::ROW_2_LEFT |
                                 VehicleAreaSeat::ROW_2_CENTER);
 constexpr int HVAC_RIGHT = (int)(VehicleAreaSeat::ROW_1_RIGHT | VehicleAreaSeat::ROW_2_RIGHT);
@@ -484,8 +485,7 @@
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
                 .access = VehiclePropertyAccess::WRITE,
-                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                .configArray = {3}},
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
      .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::BOOT_COMPLETE), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 23f9b77..a031ee9 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -91,7 +91,7 @@
     SEAT        = 0x05000000,
     /** DOOR maps to enum VehicleAreaDoor */
     DOOR        = 0x06000000,
-    /** WHEEL maps to enum Wheel */
+    /** WHEEL maps to enum VehicleAreaWheel */
     WHEEL       = 0x07000000,
 
     MASK        = 0x0f000000,
@@ -1090,8 +1090,8 @@
      * It is assumed that AP's power state is controller by separate power
      * controller.
      *
-     * For configuration information, VehiclePropConfig.configFlags can
-     * have bit flag combining values in VehicleApPowerStateConfigFlag.
+     * For configuration information, VehiclePropConfig.configArray can have bit flag combining
+     * values in VehicleApPowerStateConfigFlag.
      *
      *   int32Values[0] : VehicleApPowerStateReq enum value
      *   int32Values[1] : additional parameter relevant for each state,
@@ -2582,14 +2582,6 @@
      */
     vec<VehicleAreaConfig> areaConfigs;
 
-    /**
-     * Configuration flags for this property.
-     *
-     * For example, it may store the number of presets that are stored by the
-     * radio module.
-     */
-    int32_t configFlags;
-
     /** Contains additional configuration parameters */
     vec<int32_t> configArray;
 
@@ -2754,7 +2746,7 @@
     INTERNAL_ERROR = 5,
 };
 
-enum Wheel : int32_t {
+enum VehicleAreaWheel : int32_t {
     UNKNOWN = 0x0,
 
     LEFT_FRONT = 0x1,
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index 571b80c..62b0037 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -137,29 +137,30 @@
 }
 
 Return<void> TunerCallbackMock::onCurrentProgramInfoChanged(const ProgramInfo& info) {
-    auto logically = utils::getType(info.logicallyTunedTo);
-    if (logically != IdentifierType::INVALID) {
-        EXPECT_TRUE(logically == IdentifierType::AMFM_FREQUENCY ||
-                    logically == IdentifierType::RDS_PI ||
-                    logically == IdentifierType::HD_STATION_ID_EXT ||
-                    logically == IdentifierType::DAB_SID_EXT ||
-                    logically == IdentifierType::DRMO_SERVICE_ID ||
-                    logically == IdentifierType::SXM_SERVICE_ID ||
-                    (logically >= IdentifierType::VENDOR_START &&
-                     logically <= IdentifierType::VENDOR_END) ||
-                    logically > IdentifierType::SXM_CHANNEL);
+    for (auto&& id : info.selector) {
+        EXPECT_NE(IdentifierType::INVALID, utils::getType(id));
     }
 
+    auto logically = utils::getType(info.logicallyTunedTo);
+    /* This field is required for currently tuned program and should be INVALID
+     * for entries from the program list.
+     */
+    EXPECT_TRUE(
+        logically == IdentifierType::AMFM_FREQUENCY || logically == IdentifierType::RDS_PI ||
+        logically == IdentifierType::HD_STATION_ID_EXT ||
+        logically == IdentifierType::DAB_SID_EXT || logically == IdentifierType::DRMO_SERVICE_ID ||
+        logically == IdentifierType::SXM_SERVICE_ID ||
+        (logically >= IdentifierType::VENDOR_START && logically <= IdentifierType::VENDOR_END) ||
+        logically > IdentifierType::SXM_CHANNEL);
+
     auto physically = utils::getType(info.physicallyTunedTo);
-    if (physically != IdentifierType::INVALID) {
-        EXPECT_TRUE(physically == IdentifierType::AMFM_FREQUENCY ||
-                    physically == IdentifierType::DAB_ENSEMBLE ||
-                    physically == IdentifierType::DRMO_FREQUENCY ||
-                    physically == IdentifierType::SXM_CHANNEL ||
-                    (physically >= IdentifierType::VENDOR_START &&
-                     physically <= IdentifierType::VENDOR_END) ||
-                    physically > IdentifierType::SXM_CHANNEL);
-    }
+    // ditto (see "logically" above)
+    EXPECT_TRUE(
+        physically == IdentifierType::AMFM_FREQUENCY ||
+        physically == IdentifierType::DAB_ENSEMBLE ||
+        physically == IdentifierType::DRMO_FREQUENCY || physically == IdentifierType::SXM_CHANNEL ||
+        (physically >= IdentifierType::VENDOR_START && physically <= IdentifierType::VENDOR_END) ||
+        physically > IdentifierType::SXM_CHANNEL);
 
     if (logically == IdentifierType::AMFM_FREQUENCY) {
         auto ps = utils::getMetadataString(info, MetadataKey::RDS_PS);
diff --git a/broadcastradio/common/tests/IdentifierIterator_test.cpp b/broadcastradio/common/tests/IdentifierIterator_test.cpp
index 5bf222b..75e0d49 100644
--- a/broadcastradio/common/tests/IdentifierIterator_test.cpp
+++ b/broadcastradio/common/tests/IdentifierIterator_test.cpp
@@ -33,8 +33,8 @@
     };
     // clang-format on
 
-    auto it = utils::begin(sel);
-    auto end = utils::end(sel);
+    auto it = V2_0::begin(sel);
+    auto end = V2_0::end(sel);
 
     ASSERT_NE(end, it);
     EXPECT_EQ(sel.primaryId, *it);
@@ -46,8 +46,8 @@
 TEST(IdentifierIteratorTest, empty) {
     V2_0::ProgramSelector sel{};
 
-    auto it = utils::begin(sel);
-    auto end = utils::end(sel);
+    auto it = V2_0::begin(sel);
+    auto end = V2_0::end(sel);
 
     ASSERT_NE(end, it++);  // primary id is always present
     ASSERT_EQ(end, it);
@@ -57,8 +57,8 @@
     V2_0::ProgramSelector sel1{};
     V2_0::ProgramSelector sel2{};
 
-    auto it1 = utils::begin(sel1);
-    auto it2 = utils::begin(sel2);
+    auto it1 = V2_0::begin(sel1);
+    auto it2 = V2_0::begin(sel2);
 
     EXPECT_NE(it1, it2);
 }
@@ -66,8 +66,8 @@
 TEST(IdentifierIteratorTest, increments) {
     V2_0::ProgramSelector sel{{}, {{}, {}}};
 
-    auto it = utils::begin(sel);
-    auto end = utils::end(sel);
+    auto it = V2_0::begin(sel);
+    auto end = V2_0::end(sel);
     auto pre = it;
     auto post = it;
 
@@ -102,8 +102,8 @@
     auto isRdsPi = std::bind(typeEquals, _1, IdentifierType::RDS_PI);
     auto isFreq = std::bind(typeEquals, _1, IdentifierType::AMFM_FREQUENCY);
 
-    auto end = utils::end(sel);
-    auto it = std::find_if(utils::begin(sel), end, isRdsPi);
+    auto end = V2_0::end(sel);
+    auto it = std::find_if(V2_0::begin(sel), end, isRdsPi);
     ASSERT_NE(end, it);
     EXPECT_EQ(rds_pi1, it->value);
 
@@ -111,7 +111,7 @@
     ASSERT_NE(end, it);
     EXPECT_EQ(rds_pi2, it->value);
 
-    it = std::find_if(utils::begin(sel), end, isFreq);
+    it = std::find_if(V2_0::begin(sel), end, isFreq);
     ASSERT_NE(end, it);
     EXPECT_EQ(freq1, it->value);
 
@@ -120,4 +120,17 @@
     EXPECT_EQ(freq2, it->value);
 }
 
+TEST(IdentifierIteratorTest, rangeLoop) {
+    V2_0::ProgramSelector sel{{}, {{}, {}, {}}};
+
+    unsigned count = 0;
+    for (auto&& id : sel) {
+        ASSERT_EQ(0u, id.type);
+        count++;
+    }
+
+    const auto expectedCount = 1 + sel.secondaryIds.size();
+    ASSERT_EQ(expectedCount, count);
+}
+
 }  // anonymous namespace
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
index 6fe9554..3e20b35 100644
--- a/broadcastradio/common/utils2x/Utils.cpp
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -81,14 +81,6 @@
     return mPos == rhs.mPos;
 }
 
-IdentifierIterator begin(const V2_0::ProgramSelector& sel) {
-    return IdentifierIterator(sel);
-}
-
-IdentifierIterator end(const V2_0::ProgramSelector& sel) {
-    return IdentifierIterator(sel) + 1 /* primary id */ + sel.secondaryIds.size();
-}
-
 FrequencyBand getBand(uint64_t freq) {
     // keep in sync with
     // frameworks/base/services/core/java/com/android/server/broadcastradio/hal2/Utils.java
@@ -411,6 +403,18 @@
 }
 
 }  // namespace utils
+
+namespace V2_0 {
+
+utils::IdentifierIterator begin(const ProgramSelector& sel) {
+    return utils::IdentifierIterator(sel);
+}
+
+utils::IdentifierIterator end(const ProgramSelector& sel) {
+    return utils::IdentifierIterator(sel) + 1 /* primary id */ + sel.secondaryIds.size();
+}
+
+}  // namespace V2_0
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
index 5e51941..c4aecb2 100644
--- a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
+++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
@@ -69,9 +69,6 @@
     size_t mPos = 0;
 };
 
-IdentifierIterator begin(const V2_0::ProgramSelector& sel);
-IdentifierIterator end(const V2_0::ProgramSelector& sel);
-
 /**
  * Guesses band from the frequency value.
  *
@@ -153,6 +150,13 @@
 V2_0::ProgramIdentifier make_hdradio_station_name(const std::string& name);
 
 }  // namespace utils
+
+namespace V2_0 {
+
+utils::IdentifierIterator begin(const ProgramSelector& sel);
+utils::IdentifierIterator end(const ProgramSelector& sel);
+
+}  // namespace V2_0
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 9217a82..dc4e0f0 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -306,7 +306,7 @@
             return ret;
         }
         CameraMetadata m;
-        m = rawInfo.static_camera_characteristics;
+        m.append(rawInfo.static_camera_characteristics);
         deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
         cameraInfo = rawInfo;
         cameraInfo.static_camera_characteristics = m.release();
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 1cef882..f33da13 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -35,6 +35,13 @@
 // Size of result metadata fast message queue. Change to 0 to always use hwbinder buffer.
 static constexpr size_t CAMERA_RESULT_METADATA_QUEUE_SIZE  = 1 << 20 /* 1MB */;
 
+// Metadata sent by HAL will be replaced by a compact copy
+// if their (total size >= compact size + METADATA_SHRINK_ABS_THRESHOLD &&
+//           total_size >= compact size * METADATA_SHRINK_REL_THRESHOLD)
+// Heuristically picked by size of one page
+static constexpr int METADATA_SHRINK_ABS_THRESHOLD = 4096;
+static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2;
+
 HandleImporter CameraDeviceSession::sHandleImporter;
 const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
 
@@ -780,13 +787,11 @@
                 mOverridenRequest.update(
                         ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
                         defaultBoost, 1);
-                const camera_metadata_t *metaBuffer =
-                        mOverridenRequest.getAndLock();
-                convertToHidl(metaBuffer, outMetadata);
-                mOverridenRequest.unlock(metaBuffer);
-            } else {
-                convertToHidl(rawRequest, outMetadata);
             }
+            const camera_metadata_t *metaBuffer =
+                    mOverridenRequest.getAndLock();
+            convertToHidl(metaBuffer, outMetadata);
+            mOverridenRequest.unlock(metaBuffer);
         }
     }
     return status;
@@ -1362,6 +1367,62 @@
     return OK;
 }
 
+// Static helper method to copy/shrink capture result metadata sent by HAL
+void CameraDeviceSession::sShrinkCaptureResult(
+        camera3_capture_result* dst, const camera3_capture_result* src,
+        std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata>* mds,
+        std::vector<const camera_metadata_t*>* physCamMdArray,
+        bool handlePhysCam) {
+    *dst = *src;
+    if (sShouldShrink(src->result)) {
+        mds->emplace_back(sCreateCompactCopy(src->result));
+        dst->result = mds->back().getAndLock();
+    }
+
+    if (handlePhysCam) {
+        // First determine if we need to create new camera_metadata_t* array
+        bool needShrink = false;
+        for (uint32_t i = 0; i < src->num_physcam_metadata; i++) {
+            if (sShouldShrink(src->physcam_metadata[i])) {
+                needShrink = true;
+            }
+        }
+
+        if (!needShrink) return;
+
+        physCamMdArray->reserve(src->num_physcam_metadata);
+        dst->physcam_metadata = physCamMdArray->data();
+        for (uint32_t i = 0; i < src->num_physcam_metadata; i++) {
+            if (sShouldShrink(src->physcam_metadata[i])) {
+                mds->emplace_back(sCreateCompactCopy(src->physcam_metadata[i]));
+                dst->physcam_metadata[i] = mds->back().getAndLock();
+            } else {
+                dst->physcam_metadata[i] = src->physcam_metadata[i];
+            }
+        }
+    }
+}
+
+bool CameraDeviceSession::sShouldShrink(const camera_metadata_t* md) {
+    size_t compactSize = get_camera_metadata_compact_size(md);
+    size_t totalSize = get_camera_metadata_size(md);
+    if (totalSize >= compactSize + METADATA_SHRINK_ABS_THRESHOLD &&
+            totalSize >= compactSize * METADATA_SHRINK_REL_THRESHOLD) {
+        ALOGV("Camera metadata should be shrunk from %zu to %zu", totalSize, compactSize);
+        return true;
+    }
+    return false;
+}
+
+camera_metadata_t* CameraDeviceSession::sCreateCompactCopy(const camera_metadata_t* src) {
+    size_t compactSize = get_camera_metadata_compact_size(src);
+    void* buffer = calloc(1, compactSize);
+    if (buffer == nullptr) {
+        ALOGE("%s: Allocating %zu bytes failed", __FUNCTION__, compactSize);
+    }
+    return copy_camera_metadata(buffer, compactSize, src);
+}
+
 /**
  * Static callback forwarding methods from HAL to instance
  */
@@ -1372,7 +1433,13 @@
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
 
     CaptureResult result = {};
-    status_t ret = d->constructCaptureResult(result, hal_result);
+    camera3_capture_result shadowResult;
+    bool handlePhysCam = (d->mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
+    std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata> compactMds;
+    std::vector<const camera_metadata_t*> physCamMdArray;
+    sShrinkCaptureResult(&shadowResult, hal_result, &compactMds, &physCamMdArray, handlePhysCam);
+
+    status_t ret = d->constructCaptureResult(result, &shadowResult);
     if (ret == OK) {
         d->mResultBatcher.processCaptureResult(result);
     }
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 269cc06..af90e5a 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -141,7 +141,7 @@
     };
 
     camera3_device_t* mDevice;
-    uint32_t mDeviceVersion;
+    const uint32_t mDeviceVersion;
     bool mIsAELockAvailable;
     bool mDerivePostRawSensKey;
     uint32_t mNumPartialResults;
@@ -329,6 +329,17 @@
 
     status_t constructCaptureResult(CaptureResult& result,
                                 const camera3_capture_result *hal_result);
+
+    // Static helper method to copy/shrink capture result metadata sent by HAL
+    // Temporarily allocated metadata copy will be hold in mds
+    static void sShrinkCaptureResult(
+            camera3_capture_result* dst, const camera3_capture_result* src,
+            std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata>* mds,
+            std::vector<const camera_metadata_t*>* physCamMdArray,
+            bool handlePhysCam);
+    static bool sShouldShrink(const camera_metadata_t* md);
+    static camera_metadata_t* sCreateCompactCopy(const camera_metadata_t* src);
+
 private:
 
     struct TrampolineSessionInterface_3_2 : public ICameraDeviceSession {
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index 9722c75..6a18161 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -479,31 +479,40 @@
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
 
     CaptureResult result = {};
-    status_t ret = d->constructCaptureResult(result.v3_2, hal_result);
+    camera3_capture_result shadowResult;
+    bool handlePhysCam = (d->mDeviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
+    std::vector<::android::hardware::camera::common::V1_0::helper::CameraMetadata> compactMds;
+    std::vector<const camera_metadata_t*> physCamMdArray;
+    sShrinkCaptureResult(&shadowResult, hal_result, &compactMds, &physCamMdArray, handlePhysCam);
+
+    status_t ret = d->constructCaptureResult(result.v3_2, &shadowResult);
     if (ret != OK) {
         return;
     }
 
-    if (hal_result->num_physcam_metadata > d->mPhysicalCameraIds.size()) {
-        ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
-                hal_result->num_physcam_metadata);
-        return;
-    }
-    result.physicalCameraMetadata.resize(hal_result->num_physcam_metadata);
-    for (uint32_t i = 0; i < hal_result->num_physcam_metadata; i++) {
-        std::string physicalId = hal_result->physcam_ids[i];
-        if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
-            ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
-                  i, hal_result->physcam_ids[i]);
+    if (handlePhysCam) {
+        if (shadowResult.num_physcam_metadata > d->mPhysicalCameraIds.size()) {
+            ALOGE("%s: Fatal: Invalid num_physcam_metadata %u", __FUNCTION__,
+                    shadowResult.num_physcam_metadata);
             return;
         }
-        V3_2::CameraMetadata physicalMetadata;
-        V3_2::implementation::convertToHidl(hal_result->physcam_metadata[i], &physicalMetadata);
-        PhysicalCameraMetadata physicalCameraMetadata = {
-                .fmqMetadataSize = 0,
-                .physicalCameraId = physicalId,
-                .metadata = physicalMetadata };
-        result.physicalCameraMetadata[i] = physicalCameraMetadata;
+        result.physicalCameraMetadata.resize(shadowResult.num_physcam_metadata);
+        for (uint32_t i = 0; i < shadowResult.num_physcam_metadata; i++) {
+            std::string physicalId = shadowResult.physcam_ids[i];
+            if (d->mPhysicalCameraIds.find(physicalId) == d->mPhysicalCameraIds.end()) {
+                ALOGE("%s: Fatal: Invalid physcam_ids[%u]: %s", __FUNCTION__,
+                      i, shadowResult.physcam_ids[i]);
+                return;
+            }
+            V3_2::CameraMetadata physicalMetadata;
+            V3_2::implementation::convertToHidl(
+                    shadowResult.physcam_metadata[i], &physicalMetadata);
+            PhysicalCameraMetadata physicalCameraMetadata = {
+                    .fmqMetadataSize = 0,
+                    .physicalCameraId = physicalId,
+                    .metadata = physicalMetadata };
+            result.physicalCameraMetadata[i] = physicalCameraMetadata;
+        }
     }
     d->mResultBatcher_3_4.processCaptureResult_3_4(result);
 }
diff --git a/current.txt b/current.txt
index fb784d5..75ea5db 100644
--- a/current.txt
+++ b/current.txt
@@ -311,7 +311,7 @@
 3b17c1fdfc389e0abe626c37054954b07201127d890c2bc05d47613ec1f4de4f android.hardware.automotive.evs@1.0::types
 b3caf524c46a47d67e6453a34419e1881942d059e146cda740502670e9a752c3 android.hardware.automotive.vehicle@2.0::IVehicle
 7ce8728b27600e840cacf0a832f6942819fe535f9d3797ae052d5eef5065921c android.hardware.automotive.vehicle@2.0::IVehicleCallback
-44c8b452186b65f5140a224721f238b76ed3adc42460f26b801b561593744c7e android.hardware.automotive.vehicle@2.0::types
+3562503f550f70eec7a688343a600fb92b74efb807a31452b70195dfab328b22 android.hardware.automotive.vehicle@2.0::types
 32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
 ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
 27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index 357c772..6a32071 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -45,6 +45,10 @@
     return client;
 }
 
+sp<V2_2::IComposerClient> ComposerClient_v2_2::getRaw() const {
+    return mClient_v2_2;
+}
+
 std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient_v2_2::getPerFrameMetadataKeys(
     Display display) {
     std::vector<IComposerClient::PerFrameMetadataKey> keys;
diff --git a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
index 62ab83f..1c6d7ae 100644
--- a/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
+++ b/graphics/composer/2.2/utils/vts/include/composer-vts/2.2/ComposerVts.h
@@ -63,6 +63,8 @@
     ComposerClient_v2_2(const sp<IComposerClient>& client)
         : V2_1::vts::ComposerClient(client), mClient_v2_2(client){};
 
+    sp<V2_2::IComposerClient> getRaw() const;
+
     void execute_v2_2(V2_1::vts::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
 
     std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 4e41333..f0d2250 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -78,6 +78,11 @@
         // explicitly disable vsync
         mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
         mComposerCallback->setVsyncAllowed(false);
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+            mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) {
+                mHasReadbackBuffer = tmpError == Error::NONE;
+            });
     }
 
     void TearDown() override {
@@ -96,6 +101,7 @@
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
+    bool mHasReadbackBuffer;
 
    private:
     Display waitForFirstDisplay() {
@@ -257,18 +263,44 @@
 }
 
 TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) {
-    mComposerClient->setReadbackBuffer(mPrimaryDisplay, nullptr, -1);
-}
+    if (!mHasReadbackBuffer) {
+        return;
+    }
 
-TEST_F(GraphicsComposerHidlTest, getReadbackBufferFence) {
-    int32_t fence;
-    mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence);
-}
-
-TEST_F(GraphicsComposerHidlTest, getReadbackBufferAttributes) {
     PixelFormat pixelFormat;
     Dataspace dataspace;
     mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace);
+    ASSERT_LT(static_cast<PixelFormat>(0), pixelFormat);
+    ASSERT_NE(Dataspace::UNKNOWN, dataspace);
+
+    IMapper::BufferDescriptorInfo info{};
+    Config config = mComposerClient->getActiveConfig(mPrimaryDisplay);
+    info.width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                      IComposerClient::Attribute::WIDTH);
+    info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                       IComposerClient::Attribute::HEIGHT);
+    info.layerCount = 1;
+    info.format = pixelFormat;
+    // BufferUsage::COMPOSER_OUTPUT is missing
+    info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
+
+    std::unique_ptr<Gralloc> gralloc;
+    const native_handle_t* buffer;
+    ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
+    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info));
+
+    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
+}
+
+TEST_F(GraphicsComposerHidlTest, getReadbackBufferFenceInactive) {
+    if (!mHasReadbackBuffer) {
+        return;
+    }
+
+    mComposerClient->getRaw()->getReadbackBufferFence(
+        mPrimaryDisplay, [&](const auto& tmpError, const auto&) {
+            ASSERT_EQ(Error::UNSUPPORTED, tmpError) << "readback buffer is active";
+        });
 }
 
 /**
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index d07e799..724e0ee 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -55,5 +55,6 @@
         }
     });
 
-    return 0;
+    // b/77934844: Avoid running static destructors.
+    _exit(1);
 }
diff --git a/wifi/1.0/README-NAN.md b/wifi/1.0/README-NAN.md
index f4b3320..645c9f9 100644
--- a/wifi/1.0/README-NAN.md
+++ b/wifi/1.0/README-NAN.md
@@ -14,7 +14,7 @@
 
 # Wi-Fi Aware (NAN) HAL API Usage
 
-The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/\<version\>/</i>):
+The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/1.0/</i>):
 
 * IWifiNanIface.hal
 * IWifiNanIfaceEventCallback.hal
@@ -23,7 +23,7 @@
 The Wi-Fi Aware (NAN) HAL API surface is very large - only a subset is used from the framework.
 
 Understanding of the HAL API subset which is actively used by the Android framework can be deduced
-by reviewing framework code, specifically (<i>frameworks/opt/net/wif/</i>):
+by reviewing framework code, specifically (<i>frameworks/opt/net/wifi/</i>):
 
 * WifiAwareNativeApi.java
 * WifiAwareNativeCallback.java
@@ -41,7 +41,7 @@
 
 Format:
 * Hard-coded values are in <b>bold</b>, e.g. <b>true</b> or <b>5</b>
-* Assigned but not fixed value are specified using the <i>variable</i> keyword, possibly with some
+* Assigned but not fixed values are specified using the <i>variable</i> keyword, possibly with some
 details/constraints
 * Unassigned values are specified using the <i>N/A</i> keyword. Unassigned usually means initialized
 to 0.
diff --git a/wifi/1.2/README-NAN.md b/wifi/1.2/README-NAN.md
new file mode 100644
index 0000000..00b9169
--- /dev/null
+++ b/wifi/1.2/README-NAN.md
@@ -0,0 +1,231 @@
+Copyright 2018 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.
+
+# Wi-Fi Aware (NAN) HAL API Usage
+
+The Wi-Fi Aware (NAN) HAL API is defined in (<i>hardware/interfaces/wifi/1.0/</i> and
+<i>hardware/interfaces/wifi/1.2/</i>):
+
+* IWifiNanIface.hal
+* IWifiNanIfaceEventCallback.hal
+* types.hal (structure definitions)
+
+Note that the <i>1.2</i> HAL is supplemental to the <i>1.0</i> HAL - not a replacement.
+
+The Wi-Fi Aware (NAN) HAL API surface is very large - only a subset is used from the framework.
+
+Understanding of the HAL API subset which is actively used by the Android framework can be deduced
+by reviewing framework code, specifically (<i>frameworks/opt/net/wifi/</i>):
+
+* WifiAwareNativeApi.java
+* WifiAwareNativeCallback.java
+
+The above framework files determine the API usage - and should be consulted as the authoritative
+reference. Please consult the primary HAL file for documentation - they will not be replicated
+in this document. APIs which are in the HAL but are not listed in this README file are not used by
+the framework.
+
+Note: the HAL API is translated to the legacy HAL API (<i>wifi_nan.h</i>). This README file covers
+the new HAL API only. To understand the mapping between new and legacy HALs please consult
+<i>hardware/interfaces/wifi/\<version\>/default/hidl_struct_util.cpp</i>.
+
+## IWifiNanIface
+
+Format:
+* Hard-coded values are in <b>bold</b>, e.g. <b>true</b> or <b>5</b>
+* Assigned but not fixed values are specified using the <i>variable</i> keyword, possibly with some
+details/constraints
+* Unassigned values are specified using the <i>N/A</i> keyword. Unassigned usually means initialized
+to 0.
+
+APIs:
+
+* registerEventCallback_1_2(IWifiNanIfaceEventCallback_1_2 callback)
+* getCapabilitiesRequest
+* enableRequest_1_2
+  * NanEnableRequest
+    * bool[2] operateInBand
+        * Index [NanBandIndex.NAN_BAND_24GHZ] = <b>true</b>
+        * Index [NanBandIndex.NAN_BAND_5GHZ] = <i>variable</i>
+    * uint8_t hopCountMax = <b>2</b>
+    * NanConfigRequest configParams
+        * uint8_t masterPref = <i>variable</i>
+        * bool disableDiscoveryAddressChangeIndication = <i>variable</i>
+        * bool disableStartedClusterIndication = <i>variable</i>
+        * bool disableJoinedClusterIndication = <i>variable</i>
+        * bool includePublishServiceIdsInBeacon = <b>true</b>
+        * uint8_t numberOfPublishServiceIdsInBeacon = <b>0</b>
+        * bool includeSubscribeServiceIdsInBeacon = <b>true</b>
+        * uint8_t numberOfSubscribeServiceIdsInBeacon = <b>0</b>
+        * uint16_t rssiWindowSize = <b>8</b>
+        * uint32_t macAddressRandomizationIntervalSec = <i>variable</i>
+            * Normal run-time: set to <b>1800</b> (30 minutes)
+            * Tests: set to <b>120</b> (2 minutes)
+        * NanBandSpecificConfig[2] bandSpecificConfig
+            * Index [NanBandIndex.NAN_BAND_24GHZ]
+                * uint8_t rssiClose = <b>60</b>
+                * uint8_t rssiMiddle = <b>70</b>
+                * uint8_t rssiCloseProximity = <b>60</b>
+                * uint8_t dwellTimeMs = <b>200</b>
+                * uint16_t scanPeriodSec = <b>20</b>
+                * bool validDiscoveryWindowIntervalVal = <i>variable</i>
+                * uint8_t discoveryWindowIntervalVal = <i>variable</i>
+            * Index [NanBandIndex.NAN_BAND_5GHZ]
+                * uint8_t rssiClose = <b>60</b>
+                * uint8_t rssiMiddle = <b>75</b>
+                * uint8_t rssiCloseProximity = <b>60</b>
+                * uint8_t dwellTimeMs = <b>200</b>
+                * uint16_t scanPeriodSec = <b>20</b>
+                * bool validDiscoveryWindowIntervalVal = <i>variable</i>
+                * uint8_t discoveryWindowIntervalVal = <i>variable</i>
+    * NanDebugConfig debugConfigs
+        * bool validClusterIdVals = <b>true</b>
+        * uint16_t clusterIdBottomRangeVal = <i>variable</i>
+        * uint16_t clusterIdTopRangeVal = <i>variable</i>
+        * bool validIntfAddrVal = <b>false</b>
+        * MacAddress intfAddrVal = <i>N/A</i>
+        * bool validOuiVal = <b>false</b>
+        * uint32_t ouiVal = <i>N/A</i>
+        * bool validRandomFactorForceVal = <b>false</b>
+        * uint8_t randomFactorForceVal = <i>N/A</i>
+        * bool validHopCountForceVal = <b>false</b>
+        * uint8_t hopCountForceVal = <i>N/A</i>
+        * bool validDiscoveryChannelVal = <b>false</b>
+        * WifiChannelInMhz[2] discoveryChannelMhzVal = <i>N/A</i>
+        * bool validUseBeaconsInBandVal = <b>false</b>
+        * bool[2] useBeaconsInBandVal = <i>N/A</i>
+        * bool validUseSdfInBandVal = <b>false</b>
+        * bool[2] useSdfInBandVal = <i>N/A</i>
+  * NanConfigRequestSupplemental
+    * uint32_t discoveryBeaconIntervalMs = <b>0</b>
+    * uint32_t numberOfSpatialStreamsInDiscovery = <b>0</b>
+    * bool enableDiscoveryWindowEarlyTermination = <b>false</b>
+    * bool enableRanging = <b>true</b>
+* configRequest_1_2
+    * NanConfigRequest: same as for <i>enableRequest_1_2</i>
+* disableRequest
+* startPublishRequest
+    * NanPublishRequest
+        * NanDiscoveryCommonConfig baseConfigs
+            * uint8_t sessionId = <i>variable</i>
+            * uint16_t ttlSec = <i>variable</i>
+            * uint16_t discoveryWindowPeriod = <b>1</b>
+            * uint8_t discoveryCount = <b>0</b>
+            * vec<uint8_t> serviceName = <i>variable</i>
+            * NanMatchAlg discoveryMatchIndicator = <b>NanMatchAlg.MATCH_NEVER</b>
+            * vec<uint8_t> serviceSpecificInfo = <i>variable</i>
+            * vec<uint8_t> extendedServiceSpecificInfo = <i>N/A</i>
+            e vec<uint8_t> rxMatchFilter = <i>variable</i>
+            * vec<uint8_t> txMatchFilter = <i>variable</i>
+            * bool useRssiThreshold = <b>false</b>
+            * bool disableDiscoveryTerminationIndication = <i>variable</i>
+            * bool disableMatchExpirationIndication = <b>true</b>
+            * bool disableFollowupReceivedIndication = <b>false</b>
+            * NanDataPathSecurityConfig securityConfig = <b>NanDataPathSecurityType.OPEN</b>
+            * bool rangingRequired = <b>false</b>
+            * uint32_t rangingIntervalMsec = <i>N/A</i>
+            * bitfield<NanRangingIndication> configRangingIndications = <i>N/A</i>
+            * uint16_t distanceIngressCm = <i>N/A</i>
+            * uint16_t distanceEgressCm = <i>N/A</i>
+        * NanPublishType publishType = <i>variable</i>
+        * NanTxType txType = <b>NanTxType.BROADCAST</b>
+        * bool autoAcceptDataPathRequests = <b>false</b>
+* stopPublishRequest
+* startSubscribeRequest
+    * NanSubscribeRequest
+        * NanDiscoveryCommonConfig baseConfigs
+            * Mostly same as <i>publish</i> above except:
+            * NanMatchAlg discoveryMatchIndicator = <b>NanMatchAlg.MATCH_ONCE</b>
+        * NanSubscribeType subscribeType = <i>variable</i>
+        * NanSrfType srfType = <i>N/A</i>
+        * bool srfRespondIfInAddressSet = <i>N/A</i>
+        * bool shouldUseSrf = <i>N/A</i>
+        * bool isSsiRequiredForMatch = <i>N/A</i>
+        * vec<MacAddress> intfAddr = <i>N/A</i>
+* stopSubscribeRequest
+* transmitFollowupRequest
+    * NanTransmitFollowupRequest
+        * uint8_t discoverySessionId = <i>variable</i>
+        * uint32_t peerId = <i>variable</i>
+        * MacAddress addr = <i>variable</i>
+        * bool isHighPriority = <b>false</b>
+        * bool shouldUseDiscoveryWindow = <b>true</b>
+        * vec<uint8_t> serviceSpecificInfo = <i>variable</i>
+        * vec<uint8_t> extendedServiceSpecificInfo = <i>N/A</i>
+        * bool disableFollowupResultIndication = <b>false</b>
+* createDataInterfaceRequest
+* deleteDataInterfaceRequest
+* initiateDataPathRequest
+    * NanInitiateDataPathRequest
+        * uint32_t peerId = <i>variable</i>
+        * MacAddress peerDiscMacAddr = <i>variable</i>
+        * NanDataPathChannelCfg channelRequestType =
+        <i>NanDataPathChannelCfg.CHANNEL_NOT_REQUESTED</i>
+        * WifiChannelInMhz channel = <b>2437</b> (note that should be ignored though -
+        CHANNEL_NOT_REQUESTED!)
+        * string ifaceName = <i>variable</i>
+        * NanDataPathSecurityConfig securityConfig = <i>variable</i>
+        * vec<uint8_t> appInfo = <i>N/A</i>
+        * vec<uint8_t> serviceNameOutOfBand = <i>variable</i>
+* respondToDataPathIndicationRequest
+    * NanRespondToDataPathIndicationRequest
+        * bool acceptRequest = <i>variable</i>
+        * uint32_t ndpInstanceId = <i>variable</i>
+        * string ifaceName = <i>variable</i>
+        * NanDataPathSecurityConfig securityConfig = <i>variable</i>
+        * vec<uint8_t> appInfo = <i>N/A</i>
+        * vec<uint8_t> serviceNameOutOfBand = <i>variable</i>
+* terminateDataPathRequest
+
+## IWifiNanIfaceEventCallback_1_2
+
+Format:
+* Parameters whose values are <i>ignored</i> will be flagged, otherwise the parameter value is used
+by the framework.
+
+API:
+
+* notifyXxxResponse: all callbacks are used by framework
+* eventClusterEvent
+* eventDisabled
+* eventPublishTerminated
+* eventSubscribeTerminated
+* eventMatch
+    * NanMatchInd (all parameters are used except those listed below)
+        * vec<uint8_t> extendedServiceSpecificInfo: <i>ignored</i>
+        * bool matchOccuredInBeaconFlag: <i>ignored</i>
+        * bool outOfResourceFlag: <i>ignored</i>
+        * uint8_t rssiValue: <i>ignored</i>
+        * NanCipherSuiteType peerCipherType: <i>ignored</i>
+        * bool peerRequiresSecurityEnabledInNdp: <i>ignored</i>
+        * bool peerRequiresRanging: <i>ignored</i>
+        * uint32_t rangingMeasurementInCm: <i>ignored</i>
+        * bitfield<NanRangingIndication> rangingIndicationType: <i>ignored</i>
+* eventMatchExpired: <i>ignored</i>
+* eventFollowupReceived
+    * NanFollowupReceivedInd (all parameters are used except those listed below)
+        * bool receivedInFaw: <i>ignored</i>
+        * vec<uint8_t> extendedServiceSpecificInfo: <i>ignored</i>
+* eventTransmitFollowup
+* eventDataPathRequest
+    * NanDataPathRequestInd (all parameters are used except those listed below)
+        * bool securityRequired: <i>ignored</i>
+        * vec<uint8_t> appInfo: <i>ignored</i>
+* eventDataPathConfirm
+    * NanDataPathConfirmInd (all parameters are used except those listed below)
+        * vec<uint8_t> appInfo: <i>ignored</i>
+* eventDataPathScheduleUpdate
+    * NanDataPathScheduleUpdateInd
+* eventDataPathTerminated
+