Remove separate_platform_variant entries. am: a049eb0faf am: 08643bdf3a am: d01346a45c

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1927650

Change-Id: I6e24f0acc9ba9ed9d70b670a12568b0d1982392b
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 8fb7111..6a0d0a0 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -48,6 +48,8 @@
         "libhidlbase",
         "liblog",
         "libmedia_helper",
+        "libmediautils_vendor",
+        "libmemunreachable",
         "libutils",
         "android.hardware.audio.common-util",
     ],
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index 130dfba..c33e6f3 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -30,6 +30,8 @@
 #include <algorithm>
 
 #include <android/log.h>
+#include <mediautils/MemoryLeakTrackUtil.h>
+#include <memunreachable/memunreachable.h>
 
 #include <HidlUtils.h>
 
@@ -456,9 +458,32 @@
 }
 #endif
 
-Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& /* options */) {
+Return<void> Device::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
     if (fd.getNativeHandle() != nullptr && fd->numFds == 1) {
-        analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+        const int fd0 = fd->data[0];
+        bool dumpMem = false;
+        bool unreachableMemory = false;
+        for (const auto& option : options) {
+            if (option == "-m") {
+                dumpMem = true;
+            } else if (option == "--unreachable") {
+                unreachableMemory = true;
+            }
+        }
+
+        if (dumpMem) {
+            dprintf(fd0, "\nDumping memory:\n");
+            std::string s = dumpMemoryAddresses(100 /* limit */);
+            write(fd0, s.c_str(), s.size());
+        }
+        if (unreachableMemory) {
+            dprintf(fd0, "\nDumping unreachable memory:\n");
+            // TODO - should limit be an argument parameter?
+            std::string s = GetUnreachableMemoryString(true /* contents */, 100 /* limit */);
+            write(fd0, s.c_str(), s.size());
+        }
+
+        analyzeStatus("dump", mDevice->dump(mDevice, fd0));
     }
     return Void();
 }
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index c0c17e2..163fdb7 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -64,4 +64,5 @@
         "android.hardware.automotive@libc++fs",
         "libnl++",
     ],
+    vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
 }
diff --git a/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
new file mode 100644
index 0000000..2078ce5
--- /dev/null
+++ b/automotive/can/1.0/default/manifest_android.hardware.automotive.can@1.0.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<manifest version="1.0" type="device" >
+    <hal format="hidl">
+        <name>android.hardware.automotive.can</name>
+        <transport>hwbinder</transport>
+        <fqname>@1.0::ICanController/socketcan</fqname>
+    </hal>
+</manifest>
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 8cc1882..1216d36 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -79,19 +79,24 @@
 using IEvsDisplay_1_0 = ::android::hardware::automotive::evs::V1_0::IEvsDisplay;
 using IEvsDisplay_1_1 = ::android::hardware::automotive::evs::V1_1::IEvsDisplay;
 
+namespace {
+
 /*
  * Plese note that this is different from what is defined in
  * libhardware/modules/camera/3_4/metadata/types.h; this has one additional
  * field to store a framerate.
  */
-const size_t kStreamCfgSz = 5;
 typedef struct {
+    int32_t id;
     int32_t width;
     int32_t height;
     int32_t format;
     int32_t direction;
     int32_t framerate;
 } RawStreamConfig;
+constexpr const size_t kStreamCfgSz = sizeof(RawStreamConfig) / sizeof(int32_t);
+
+} // anonymous namespace
 
 
 // The main test class for EVS
@@ -236,6 +241,28 @@
         return physicalCameras;
     }
 
+    Stream getFirstStreamConfiguration(camera_metadata_t* metadata) {
+        Stream targetCfg = {};
+        camera_metadata_entry_t streamCfgs;
+        if (!find_camera_metadata_entry(metadata,
+                 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+                 &streamCfgs)) {
+            // Stream configurations are found in metadata
+            RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
+                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
+                    targetCfg.width = ptr->width;
+                    targetCfg.height = ptr->height;
+                    targetCfg.format = static_cast<PixelFormat>(ptr->format);
+                    break;
+                }
+                ++ptr;
+            }
+        }
+
+        return targetCfg;
+    }
 
     sp<IEvsEnumerator>              pEnumerator;   // Every test needs access to the service
     std::vector<CameraDesc>         cameraInfo;    // Empty unless/until loadCameraList() is called
@@ -265,10 +292,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Open and close each camera twice
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -278,8 +301,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         for (int pass = 0; pass < 2; pass++) {
-            sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg);
+            sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
             ASSERT_NE(pCam, nullptr);
 
             for (auto&& devName : devices) {
@@ -343,10 +372,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Open and close each camera twice
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -356,10 +381,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         activeCameras.clear();
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -372,9 +401,7 @@
                                 }
         );
 
-        sp<IEvsCamera_1_1> pCam2 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam2 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam2, nullptr);
 
         // Store a camera handle for a clean-up
@@ -422,10 +449,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -435,9 +458,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -519,10 +546,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -532,9 +555,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -601,10 +628,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Request available display IDs
     uint8_t targetDisplayId = 0;
     pEnumerator->getDisplayIdList([&targetDisplayId](auto ids) {
@@ -642,9 +665,13 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -708,24 +735,22 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCam0);
 
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -812,10 +837,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     Return<EvsResult> result = EvsResult::OK;
     for (auto&& cam: cameraInfo) {
@@ -828,10 +849,14 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create a camera client
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera
@@ -961,10 +986,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -976,18 +997,20 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCamPrimary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamPrimary, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCamPrimary);
 
-        sp<IEvsCamera_1_1> pCamSecondary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamSecondary, nullptr);
 
         // Store a camera handle for a clean-up
@@ -1142,10 +1165,6 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
         bool isLogicalCam = false;
@@ -1157,18 +1176,20 @@
             continue;
         }
 
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two camera clients.
-        sp<IEvsCamera_1_1> pCamPrimary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamPrimary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamPrimary, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCamPrimary);
 
-        sp<IEvsCamera_1_1> pCamSecondary =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCamSecondary = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCamSecondary, nullptr);
 
         // Store a camera handle for a clean-up
@@ -1615,28 +1636,26 @@
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Request exclusive access to the EVS display
     sp<IEvsDisplay_1_0> pDisplay = pEnumerator->openDisplay();
     ASSERT_NE(pDisplay, nullptr);
 
     // Test each reported camera
     for (auto&& cam: cameraInfo) {
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
+
         // Create two clients
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
         activeCameras.push_back(pCam0);
 
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2001,7 +2020,7 @@
                  &streamCfgs)) {
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
-            for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
 
@@ -2026,9 +2045,7 @@
             continue;
         }
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2106,7 +2123,7 @@
                  &streamCfgs)) {
             // Stream configurations are found in metadata
             RawStreamConfig *ptr = reinterpret_cast<RawStreamConfig *>(streamCfgs.data.i32);
-            for (unsigned idx = 0; idx < streamCfgs.count; idx += kStreamCfgSz) {
+            for (unsigned offset = 0; offset < streamCfgs.count; offset += kStreamCfgSz) {
                 if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
                     ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
 
@@ -2132,9 +2149,7 @@
         }
 
         // Create the first camera client with a selected stream configuration.
-        sp<IEvsCamera_1_1> pCam0 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam0 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam0, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2144,9 +2159,7 @@
         // configuration.
         int32_t id = targetCfg.id;
         targetCfg.id += 1;  // EVS manager sees only the stream id.
-        sp<IEvsCamera_1_1> pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_EQ(pCam1, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2154,9 +2167,7 @@
 
         // Try again with same stream configuration.
         targetCfg.id = id;
-        pCam1 =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg))
-            .withDefault(nullptr);
+        pCam1 = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam1, nullptr);
 
         // Set up per-client frame receiver objects which will fire up its own thread
@@ -2258,52 +2269,23 @@
     LOG(INFO) << "Starting CameraStreamExternalBuffering test";
 
     // Arbitrary constant (should be > 1 and not too big)
-    static const unsigned int kBuffersToHold = 6;
+    static const unsigned int kBuffersToHold = 3;
 
     // Get the camera list
     loadCameraList();
 
-    // Using null stream configuration makes EVS uses the default resolution and
-    // output format.
-    Stream nullCfg = {};
-
     // Acquire the graphics buffer allocator
     android::GraphicBufferAllocator& alloc(android::GraphicBufferAllocator::get());
     const auto usage =
             GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_OFTEN;
-    const auto format = HAL_PIXEL_FORMAT_RGBA_8888;
-    uint32_t width = 640;
-    uint32_t height = 360;
-    camera_metadata_entry_t streamCfgs;
 
     // Test each reported camera
     for (auto&& cam : cameraInfo) {
-        bool foundCfg = false;
-        if (!find_camera_metadata_entry(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()),
-                                        ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
-                                        &streamCfgs)) {
-            // Stream configurations are found in metadata
-            RawStreamConfig* ptr = reinterpret_cast<RawStreamConfig*>(streamCfgs.data.i32);
-
-            LOG(DEBUG) << __LINE__ << " start searching " << streamCfgs.count;
-            for (unsigned idx = 0; idx < streamCfgs.count; idx++) {
-                LOG(DEBUG) << "ptr->direction= " << ptr->direction
-                           << " ptr->format= " << ptr->format;
-                if (ptr->direction == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
-                    ptr->format == HAL_PIXEL_FORMAT_RGBA_8888) {
-                    width = ptr->width;
-                    height = ptr->height;
-                    foundCfg = true;
-                    // Always use the 1st available configuration
-                    break;
-                }
-                ++ptr;
-            }
-        }
-
-        if (!foundCfg) {
-            LOG(INFO) << "No configuration found. Use default stream configurations.";
-        }
+        // Read a target resolution from the metadata
+        Stream targetCfg =
+            getFirstStreamConfiguration(reinterpret_cast<camera_metadata_t*>(cam.metadata.data()));
+        ASSERT_GT(targetCfg.width, 0);
+        ASSERT_GT(targetCfg.height, 0);
 
         // Allocate buffers to use
         hidl_vec<BufferDesc> buffers;
@@ -2312,8 +2294,11 @@
             unsigned pixelsPerLine;
             buffer_handle_t memHandle = nullptr;
             android::status_t result =
-                    alloc.allocate(width, height, format, 1, usage, &memHandle, &pixelsPerLine, 0,
-                                   "CameraStreamExternalBufferingTest");
+                    alloc.allocate(targetCfg.width, targetCfg.height,
+                                   (android::PixelFormat)targetCfg.format,
+                                   /* layerCount = */ 1, usage, &memHandle, &pixelsPerLine,
+                                   /* graphicBufferId = */ 0,
+                                   /* requestorName = */ "CameraStreamExternalBufferingTest");
             if (result != android::NO_ERROR) {
                 LOG(ERROR) << __FUNCTION__ << " failed to allocate memory.";
                 // Release previous allocated buffers
@@ -2325,10 +2310,10 @@
                 BufferDesc buf;
                 AHardwareBuffer_Desc* pDesc =
                         reinterpret_cast<AHardwareBuffer_Desc*>(&buf.buffer.description);
-                pDesc->width = width;
-                pDesc->height = height;
+                pDesc->width = targetCfg.width;
+                pDesc->height = targetCfg.height;
                 pDesc->layers = 1;
-                pDesc->format = format;
+                pDesc->format = static_cast<uint32_t>(targetCfg.format);
                 pDesc->usage = usage;
                 pDesc->stride = pixelsPerLine;
                 buf.buffer.nativeHandle = memHandle;
@@ -2340,9 +2325,7 @@
         bool isLogicalCam = false;
         getPhysicalCameraIds(cam.v1.cameraId, isLogicalCam);
 
-        sp<IEvsCamera_1_1> pCam =
-            IEvsCamera_1_1::castFrom(pEnumerator->openCamera_1_1(cam.v1.cameraId, nullCfg))
-            .withDefault(nullptr);
+        sp<IEvsCamera_1_1> pCam = pEnumerator->openCamera_1_1(cam.v1.cameraId, targetCfg);
         ASSERT_NE(pCam, nullptr);
 
         // Store a camera handle for a clean-up
@@ -2362,7 +2345,7 @@
         }
 
         EXPECT_EQ(result, EvsResult::OK);
-        EXPECT_GE(delta, 0);
+        EXPECT_GE(delta, kBuffersToHold);
 
         // Set up a frame receiver object which will fire up its own thread.
         sp<FrameHandler> frameHandler = new FrameHandler(pCam, cam,
@@ -2378,7 +2361,7 @@
         sleep(1);   // 1 second should be enough for at least 5 frames to be delivered worst case
         unsigned framesReceived = 0;
         frameHandler->getFramesCounters(&framesReceived, nullptr);
-        ASSERT_EQ(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
+        ASSERT_LE(kBuffersToHold, framesReceived) << "Stream didn't stall at expected buffer limit";
 
 
         // Give back one buffer
@@ -2387,9 +2370,10 @@
 
         // Once we return a buffer, it shouldn't take more than 1/10 second to get a new one
         // filled since we require 10fps minimum -- but give a 10% allowance just in case.
+        unsigned framesReceivedAfter = 0;
         usleep(110 * kMillisecondsToMicroseconds);
-        frameHandler->getFramesCounters(&framesReceived, nullptr);
-        EXPECT_EQ(kBuffersToHold+1, framesReceived) << "Stream should've resumed";
+        frameHandler->getFramesCounters(&framesReceivedAfter, nullptr);
+        EXPECT_EQ(framesReceived + 1, framesReceivedAfter) << "Stream should've resumed";
 
         // Even when the camera pointer goes out of scope, the FrameHandler object will
         // keep the stream alive unless we tell it to shutdown.
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
index 583a455..58423c8 100644
--- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <fuzzer/FuzzedDataProvider.h>
 #include <cmath>
 #include <cstdlib>
 #include <cstring>
@@ -21,36 +22,43 @@
 #include "FormatConvert.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
-    if (size < 256) {
+    // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2)
+    if (size < (4 + 16 * 2 * 2)) {
         return 0;
     }
+    FuzzedDataProvider fdp(data, size);
+    std::size_t image_pixel_size = size - 4;
+    image_pixel_size = (image_pixel_size & INT_MAX) / 2;
 
-    std::srand(std::time(nullptr));  // use current time as seed for random generator
-    int random_variable = std::rand() % 10;
-    int width = (int)sqrt(size);
-    int height = width * ((float)random_variable / 10.0);
+    // API have a requirement that width must be divied by 16 except yuyvtorgb
+    int min_height = 2;
+    int max_height = (image_pixel_size / 16) & ~(1);  // must be even number
+    int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height);
+    int width = (image_pixel_size / height) & ~(16);  // must be divisible by 16
 
-    uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
-    memcpy(src, data, sizeof(uint8_t) * (size));
-    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+    uint8_t* src = (uint8_t*)(data + 4);
+    uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
 
 #ifdef COPY_NV21_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_NV21_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YV12_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YV12_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+    android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt,
+                                                                       width);
 #elif COPY_YUYV_TO_RGB32
-    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
-                                                                       0);
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
+                                                                       tgt, width);
 #elif COPY_YUYV_TO_BGR32
-    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
-                                                                       0);
+    android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
+                                                                       tgt, width);
 #endif
 
-    free(src);
     free(tgt);
 
     return 0;
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 869c0c9..ba11a49 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -182,6 +182,7 @@
     ],
     shared_libs: [
         "libbase",
+        "libcutils",
     ],
     header_libs: ["libbase_headers"],
     test_suites: ["general-tests"],
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
index c8c89dc..44f9134 100644
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
@@ -1,4 +1,4 @@
 service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
-    class hal
+    class early_hal
     user vehicle_network
     group system inet
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
index fcfe761..6706258 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHalManager.h
@@ -76,6 +76,9 @@
     Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
   private:
+    // Set unit test class as friend class to test private functions.
+    friend class VehicleHalManagerTestHelper;
+
     using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
     // Returns true if needs to call again shortly.
     using RetriableAction = std::function<bool()>;
@@ -105,14 +108,20 @@
     void cmdDumpOneProperty(int fd, int32_t prop, int32_t areaId);
     void cmdDumpOneProperty(int fd, int rowNumber, const VehiclePropConfig& config);
 
+    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
+
     static bool checkArgumentsSize(int fd, const hidl_vec<hidl_string>& options, size_t minSize);
     static bool checkCallerHasWritePermissions(int fd);
-    static bool safelyParseInt(int fd, int index, std::string s, int* out);
+    template <typename T>
+    static bool safelyParseInt(int fd, int index, const std::string& s, T* out);
+    static bool safelyParseFloat(int fd, int index, const std::string& s, float* out);
+    // Parses "s" as a hex string and populate "*bytes". The hex string must be in the format of
+    // valid hex format, e.g. "0xABCD".
+    static bool parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes);
     void cmdHelp(int fd) const;
     void cmdListAllProperties(int fd) const;
     void cmdDumpAllProperties(int fd);
     void cmdDumpSpecificProperties(int fd, const hidl_vec<hidl_string>& options);
-    void cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options);
 
     static bool isSubscribable(const VehiclePropConfig& config,
                                SubscribeFlags flags);
@@ -120,7 +129,18 @@
     static float checkSampleRate(const VehiclePropConfig& config,
                                  float sampleRate);
     static ClientId getClientId(const sp<IVehicleCallback>& callback);
-private:
+
+    // Parses the cmdline options for "--set" command. "*prop" would be populated with the
+    // the properties to be set. Returns true when the cmdline options are valid, false otherwise.
+    static bool parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+                                    VehiclePropValue* prop);
+    // Parses the options and get the values for the current option specified by "*index". "*index"
+    // would advance to the next option field (e.g., the next "-f"). Returns a list of values for
+    // the current option.
+    static std::vector<std::string> getOptionValues(const hidl_vec<hidl_string>& options,
+                                                    size_t* index);
+
+  private:
     VehicleHal* mHal;
     std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
     SubscriptionManager mSubscriptionManager;
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index dc5d3d3..e34e692 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -20,7 +20,9 @@
 
 #include <cmath>
 #include <fstream>
+#include <unordered_set>
 
+#include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <android/hardware/automotive/vehicle/2.0/BpHwVehicleCallback.h>
@@ -44,15 +46,34 @@
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 
+namespace {
+
 constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
 
 const VehiclePropValue kEmptyValue{};
 
+// A list of supported options for "--set" command.
+const std::unordered_set<std::string> kSetPropOptions = {
+        // integer.
+        "-i",
+        // 64bit integer.
+        "-i64",
+        // float.
+        "-f",
+        // string.
+        "-s",
+        // bytes in hex format, e.g. 0xDEADBEEF.
+        "-b",
+        // Area id in integer.
+        "-a"};
+
+}  // namespace
+
 /**
  * Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
  * to store in reusable object pool.
  */
-constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+constexpr auto kMaxHidlVecOfVehiclePropValuePoolSize = 20;
 
 Return<void> VehicleHalManager::getAllPropConfigs(getAllPropConfigs_cb _hidl_cb) {
     ALOGI("getAllPropConfigs called");
@@ -213,6 +234,11 @@
     } else if (EqualsIgnoreCase(option, "--get")) {
         cmdDumpSpecificProperties(fd, options);
     } else if (EqualsIgnoreCase(option, "--set")) {
+        if (!checkCallerHasWritePermissions(fd)) {
+            dprintf(fd, "Caller does not have write permission\n");
+            return;
+        }
+        // Ignore the return value for this.
         cmdSetOneProperty(fd, options);
     } else {
         dprintf(fd, "Invalid option: %s\n", option.c_str());
@@ -239,7 +265,8 @@
     return false;
 }
 
-bool VehicleHalManager::safelyParseInt(int fd, int index, std::string s, int* out) {
+template <typename T>
+bool VehicleHalManager::safelyParseInt(int fd, int index, const std::string& s, T* out) {
     if (!android::base::ParseInt(s, out)) {
         dprintf(fd, "non-integer argument at index %d: %s\n", index, s.c_str());
         return false;
@@ -247,19 +274,27 @@
     return true;
 }
 
+bool VehicleHalManager::safelyParseFloat(int fd, int index, const std::string& s, float* out) {
+    if (!android::base::ParseFloat(s, out)) {
+        dprintf(fd, "non-float argument at index %d: %s\n", index, s.c_str());
+        return false;
+    }
+    return true;
+}
+
 void VehicleHalManager::cmdHelp(int fd) const {
     dprintf(fd, "Usage: \n\n");
     dprintf(fd, "[no args]: dumps (id and value) all supported properties \n");
     dprintf(fd, "--help: shows this help\n");
     dprintf(fd, "--list: lists the ids of all supported properties\n");
     dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
-    // TODO: support other formats (int64, float, bytes)
     dprintf(fd,
-            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
-            "property PROP, using arbitrary number of key/value parameters (i for int32, "
-            "s for string) and an optional area.\n"
-            "Notice that the string value can be set just once, while the other can have multiple "
-            "values (so they're used in the respective array)\n");
+            "--set <PROP> [-i INT_VALUE [INT_VALUE ...]] [-i64 INT64_VALUE [INT64_VALUE ...]] "
+            "[-f FLOAT_VALUE [FLOAT_VALUE ...]] [-s STR_VALUE] "
+            "[-b BYTES_VALUE] [-a AREA_ID] : sets the value of property PROP. "
+            "Notice that the string, bytes and area value can be set just once, while the other can"
+            " have multiple values (so they're used in the respective array), "
+            "BYTES_VALUE is in the form of 0xXXXX, e.g. 0xdeadbeef.\n");
 }
 
 void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -337,102 +372,49 @@
     VehiclePropValue input;
     input.prop = prop;
     input.areaId = areaId;
-    auto callback = [&](StatusCode status, const VehiclePropValue& output) {
+    auto callback = [&fd, &prop](StatusCode status, const VehiclePropValue& output) {
         if (status == StatusCode::OK) {
             dprintf(fd, "%s\n", toString(output).c_str());
         } else {
             dprintf(fd, "Could not get property %d. Error: %s\n", prop, toString(status).c_str());
         }
     };
-    get(input, callback);
+
+    StatusCode status;
+    auto value = mHal->get(input, &status);
+    callback(status, value.get() ? *value : kEmptyValue);
 }
 
-void VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
-    if (!checkCallerHasWritePermissions(fd) || !checkArgumentsSize(fd, options, 3)) return;
-
-    size_t size = options.size();
-
-    // Syntax is --set PROP Type1 Value1 TypeN ValueN, so number of arguments must be even
-    if (size % 2 != 0) {
-        dprintf(fd, "must pass even number of arguments (passed %zu)\n", size);
-        return;
+bool VehicleHalManager::cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+    if (!checkArgumentsSize(fd, options, 4)) {
+        dprintf(fd, "Requires at least 4 options, see help\n");
+        return false;
     }
-    int numberValues = (size - 2) / 2;
 
-    VehiclePropValue prop;
-    if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
-    prop.timestamp = elapsedRealtimeNano();
-    prop.status = VehiclePropertyStatus::AVAILABLE;
-
-    // First pass: calculate sizes
-    int sizeInt32 = 0;
-    int stringIndex = 0;
-    int areaIndex = 0;
-    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
-        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
-        std::string type = options[i];
-        std::string value = options[i + 1];
-        if (EqualsIgnoreCase(type, "i")) {
-            sizeInt32++;
-        } else if (EqualsIgnoreCase(type, "s")) {
-            if (stringIndex != 0) {
-                dprintf(fd,
-                        "defining string value (%s) again at index %d (already defined at %d=%s"
-                        ")\n",
-                        value.c_str(), i, stringIndex, options[stringIndex + 1].c_str());
-                return;
-            }
-            stringIndex = i;
-        } else if (EqualsIgnoreCase(type, "a")) {
-            if (areaIndex != 0) {
-                dprintf(fd,
-                        "defining area value (%s) again at index %d (already defined at %d=%s"
-                        ")\n",
-                        value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
-                return;
-            }
-            areaIndex = i;
-        } else {
-            dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
-            return;
-        }
-        i += 2;
-    }
-    prop.value.int32Values.resize(sizeInt32);
-
-    // Second pass: populate it
-    int indexInt32 = 0;
-    for (int i = 2, kv = 1; kv <= numberValues; kv++) {
-        // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
-        int valueIndex = i + 1;
-        std::string type = options[i];
-        std::string value = options[valueIndex];
-        if (EqualsIgnoreCase(type, "i")) {
-            int safeInt;
-            if (!safelyParseInt(fd, valueIndex, value, &safeInt)) return;
-            prop.value.int32Values[indexInt32++] = safeInt;
-        } else if (EqualsIgnoreCase(type, "s")) {
-            prop.value.stringValue = value;
-        } else if (EqualsIgnoreCase(type, "a")) {
-            if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
-        }
-        i += 2;
+    VehiclePropValue prop = {};
+    if (!parseSetPropOptions(fd, options, &prop)) {
+        return false;
     }
     ALOGD("Setting prop %s", toString(prop).c_str());
-    auto status = set(prop);
+
+    // Do not use VehicleHalManager::set here because we don't want to check write permission.
+    // Caller should be able to use the debug interface to set read-only properties.
+    handlePropertySetEvent(prop);
+    auto status = mHal->set(prop);
+
     if (status == StatusCode::OK) {
         dprintf(fd, "Set property %s\n", toString(prop).c_str());
-    } else {
-        dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
-                toString(status).c_str());
+        return true;
     }
+    dprintf(fd, "Failed to set property %s: %s\n", toString(prop).c_str(),
+            toString(status).c_str());
+    return false;
 }
 
 void VehicleHalManager::init() {
     ALOGI("VehicleHalManager::init");
 
-    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
-
+    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclePropValuePoolSize);
 
     mBatchingConsumer.run(&mEventQueue,
                           kHalEventBatchingTimeWindow,
@@ -486,7 +468,7 @@
     for (const HalClientValues& cv : clientValues) {
         auto vecSize = cv.values.size();
         hidl_vec<VehiclePropValue> vec;
-        if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+        if (vecSize < kMaxHidlVecOfVehiclePropValuePoolSize) {
             vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
         } else {
             vec.resize(vecSize);
@@ -595,6 +577,158 @@
     }
 }
 
+std::vector<std::string> VehicleHalManager::getOptionValues(const hidl_vec<hidl_string>& options,
+                                                            size_t* index) {
+    std::vector<std::string> values;
+    while (*index < options.size()) {
+        std::string option = options[*index];
+        if (kSetPropOptions.find(option) != kSetPropOptions.end()) {
+            return std::move(values);
+        }
+        values.push_back(option);
+        (*index)++;
+    }
+    return std::move(values);
+}
+
+bool VehicleHalManager::parseSetPropOptions(int fd, const hidl_vec<hidl_string>& options,
+                                            VehiclePropValue* prop) {
+    // Options format:
+    // --set PROP [-f f1 f2...] [-i i1 i2...] [-i64 i1 i2...] [-s s1 s2...] [-b b1 b2...] [-a a]
+    size_t optionIndex = 1;
+    int propValue;
+    if (!safelyParseInt(fd, optionIndex, options[optionIndex], &propValue)) {
+        dprintf(fd, "property value: \"%s\" is not a valid int\n", options[optionIndex].c_str());
+        return false;
+    }
+    prop->prop = propValue;
+    prop->timestamp = elapsedRealtimeNano();
+    prop->status = VehiclePropertyStatus::AVAILABLE;
+    optionIndex++;
+    std::unordered_set<std::string> parsedOptions;
+
+    while (optionIndex < options.size()) {
+        std::string type = options[optionIndex];
+        optionIndex++;
+        size_t currentIndex = optionIndex;
+        std::vector<std::string> values = getOptionValues(options, &optionIndex);
+        if (parsedOptions.find(type) != parsedOptions.end()) {
+            dprintf(fd, "duplicate \"%s\" options\n", type.c_str());
+            return false;
+        }
+        parsedOptions.insert(type);
+        if (EqualsIgnoreCase(type, "-i")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-i\"\n");
+                return false;
+            }
+            prop->value.int32Values.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                int32_t safeInt;
+                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+                    dprintf(fd, "value: \"%s\" is not a valid int\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.int32Values[i] = safeInt;
+            }
+        } else if (EqualsIgnoreCase(type, "-i64")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-i64\"\n");
+                return false;
+            }
+            prop->value.int64Values.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                int64_t safeInt;
+                if (!safelyParseInt(fd, currentIndex + i, values[i], &safeInt)) {
+                    dprintf(fd, "value: \"%s\" is not a valid int64\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.int64Values[i] = safeInt;
+            }
+        } else if (EqualsIgnoreCase(type, "-f")) {
+            if (values.size() == 0) {
+                dprintf(fd, "no values specified when using \"-f\"\n");
+                return false;
+            }
+            prop->value.floatValues.resize(values.size());
+            for (size_t i = 0; i < values.size(); i++) {
+                float safeFloat;
+                if (!safelyParseFloat(fd, currentIndex + i, values[i], &safeFloat)) {
+                    dprintf(fd, "value: \"%s\" is not a valid float\n", values[i].c_str());
+                    return false;
+                }
+                prop->value.floatValues[i] = safeFloat;
+            }
+        } else if (EqualsIgnoreCase(type, "-s")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-s\"\n");
+                return false;
+            }
+            prop->value.stringValue = values[0];
+        } else if (EqualsIgnoreCase(type, "-b")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-b\"\n");
+                return false;
+            }
+            std::vector<uint8_t> bytes;
+            if (!parseHexString(fd, values[0], &bytes)) {
+                dprintf(fd, "value: \"%s\" is not a valid hex string\n", values[0].c_str());
+                return false;
+            }
+            prop->value.bytes = bytes;
+        } else if (EqualsIgnoreCase(type, "-a")) {
+            if (values.size() != 1) {
+                dprintf(fd, "expect exact one value when using \"-a\"\n");
+                return false;
+            }
+            if (!safelyParseInt(fd, currentIndex, values[0], &(prop->areaId))) {
+                dprintf(fd, "area ID: \"%s\" is not a valid int\n", values[0].c_str());
+                return false;
+            }
+        } else {
+            dprintf(fd, "unknown option: %s\n", type.c_str());
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool VehicleHalManager::parseHexString(int fd, const std::string& s, std::vector<uint8_t>* bytes) {
+    if (s.size() % 2 != 0) {
+        dprintf(fd, "invalid hex string: %s, should have even size\n", s.c_str());
+        return false;
+    }
+    if (strncmp(s.substr(0, 2).c_str(), "0x", 2)) {
+        dprintf(fd, "hex string should start with \"0x\", got %s\n", s.c_str());
+        return false;
+    }
+    std::string subs = s.substr(2);
+    std::transform(subs.begin(), subs.end(), subs.begin(),
+                   [](unsigned char c) { return std::tolower(c); });
+
+    bool highDigit = true;
+    for (size_t i = 0; i < subs.size(); i++) {
+        char c = subs[i];
+        uint8_t v;
+        if (c >= '0' && c <= '9') {
+            v = c - '0';
+        } else if (c >= 'a' && c <= 'f') {
+            v = c - 'a' + 10;
+        } else {
+            dprintf(fd, "invalid character %c in hex string %s\n", c, subs.c_str());
+            return false;
+        }
+        if (highDigit) {
+            (*bytes).push_back(v * 16);
+        } else {
+            (*bytes)[bytes->size() - 1] += v;
+        }
+        highDigit = !highDigit;
+    }
+    return true;
+}
+
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
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 8ff4924..55617be 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
@@ -307,6 +307,18 @@
                          .prop = toInt(VehicleProperty::CRITICALLY_LOW_TIRE_PRESSURE),
                          .access = VehiclePropertyAccess::READ,
                          .changeMode = VehiclePropertyChangeMode::STATIC,
+                         .areaConfigs = {VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_LEFT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_FRONT_RIGHT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_LEFT,
+                                         },
+                                         VehicleAreaConfig{
+                                                 .areaId = WHEEL_REAR_RIGHT,
+                                         }},
                  },
          .initialAreaValues = {{WHEEL_FRONT_LEFT, {.floatValues = {137.0f}}},
                                {WHEEL_FRONT_RIGHT, {.floatValues = {137.0f}}},
@@ -1032,14 +1044,6 @@
         {
                 .config =
                         {
-                                .prop = toInt(VehicleProperty::STORAGE_ENCRYPTION_BINDING_SEED),
-                                .access = VehiclePropertyAccess::READ_WRITE,
-                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
-                        },
-        },
-        {
-                .config =
-                        {
                                 .prop = toInt(VehicleProperty::WATCHDOG_ALIVE),
                                 .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -1105,6 +1109,42 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_INT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_FLOAT,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.floatValues = {0.0f}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_BOOLEAN,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.int32Values = {0 /* false */}},
+        },
+        {
+                .config =
+                        {
+                                .prop = PLACEHOLDER_PROPERTY_STRING,
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+                .initialValue = {.stringValue = {"Test"}},
+        },
 #ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
         // Vendor propetry for E2E ClusterHomeService testing.
         {
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
index d5f6a18..51251a7 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/PropertyUtils.h
@@ -189,6 +189,19 @@
     KeyPress = 100,
 };
 
+/**
+ * These properties are placeholder properties for developers to test new features without
+ * implementing a real property.
+ */
+constexpr int32_t PLACEHOLDER_PROPERTY_INT =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::INT32;
+constexpr int32_t PLACEHOLDER_PROPERTY_FLOAT =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::FLOAT;
+constexpr int32_t PLACEHOLDER_PROPERTY_BOOLEAN =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::BOOLEAN;
+constexpr int32_t PLACEHOLDER_PROPERTY_STRING =
+        0x2a11 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::STRING;
+
 const int32_t kHvacPowerProperties[] = {
     toInt(VehicleProperty::HVAC_FAN_SPEED),
     toInt(VehicleProperty::HVAC_FAN_DIRECTION),
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 0975071..bdf46fb 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -18,6 +18,7 @@
 #include <iostream>
 
 #include <android-base/macros.h>
+#include <cutils/native_handle.h>
 #include <utils/SystemClock.h>
 
 #include <gtest/gtest.h>
@@ -32,6 +33,18 @@
 namespace vehicle {
 namespace V2_0 {
 
+// A simple helper class to expose 'cmdSetOneProperty' to the unit tests.
+class VehicleHalManagerTestHelper {
+  public:
+    VehicleHalManagerTestHelper(VehicleHalManager* manager) { mManager = manager; }
+    bool cmdSetOneProperty(int fd, const hidl_vec<hidl_string>& options) {
+        return mManager->cmdSetOneProperty(fd, options);
+    }
+
+  public:
+    VehicleHalManager* mManager;
+};
+
 namespace {
 
 using namespace std::placeholders;
@@ -57,33 +70,21 @@
         auto property = static_cast<VehicleProperty>(requestedPropValue.prop);
         int32_t areaId = requestedPropValue.areaId;
 
-        switch (property) {
-            case VehicleProperty::INFO_MAKE:
-                pValue = getValuePool()->obtainString(kCarMake);
-                break;
-            case VehicleProperty::INFO_FUEL_CAPACITY:
-                if (fuelCapacityAttemptsLeft-- > 0) {
-                    // Emulate property not ready yet.
-                    *outStatus = StatusCode::TRY_AGAIN;
-                } else {
-                    pValue = getValuePool()->obtainFloat(42.42);
-                }
-                break;
-            default:
-                if (requestedPropValue.prop == kCustomComplexProperty) {
-                    pValue = getValuePool()->obtainComplex();
-                    pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
-                    pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
-                    pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
-                    pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
-                    pValue->value.stringValue = kCarMake;
-                    break;
-                }
-                auto key = makeKey(toInt(property), areaId);
-                if (mValues.count(key) == 0) {
-                    ALOGW("");
-                }
-                pValue = getValuePool()->obtain(mValues[key]);
+        if (property == VehicleProperty::INFO_FUEL_CAPACITY) {
+            if (fuelCapacityAttemptsLeft-- > 0) {
+                // Emulate property not ready yet.
+                *outStatus = StatusCode::TRY_AGAIN;
+            } else {
+                pValue = getValuePool()->obtainFloat(42.42);
+            }
+        } else {
+            auto key = makeKey(requestedPropValue);
+            if (mValues.count(key) == 0) {
+                ALOGW("key not found\n");
+                *outStatus = StatusCode::INVALID_ARG;
+                return pValue;
+            }
+            pValue = getValuePool()->obtain(mValues[key]);
         }
 
         if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
@@ -100,7 +101,6 @@
                 && mirrorFoldAttemptsLeft-- > 0) {
             return StatusCode::TRY_AGAIN;
         }
-
         mValues[makeKey(propValue)] = propValue;
         return StatusCode::OK;
     }
@@ -181,6 +181,18 @@
         actualStatusCode = refStatus;
     }
 
+    MockedVehicleHal::VehiclePropValuePtr getComplexProperty() {
+        auto pValue = objectPool->obtainComplex();
+        pValue->prop = kCustomComplexProperty;
+        pValue->areaId = 0;
+        pValue->value.int32Values = hidl_vec<int32_t>{10, 20};
+        pValue->value.int64Values = hidl_vec<int64_t>{30, 40};
+        pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2};
+        pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3};
+        pValue->value.stringValue = kCarMake;
+        return pValue;
+    }
+
 public:
     VehiclePropValue actualValue;
     StatusCode actualStatusCode;
@@ -308,6 +320,8 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_Complex) {
+    ASSERT_EQ(StatusCode::OK, hal->set(*getComplexProperty().get()));
+
     invokeGet(kCustomComplexProperty, 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -334,6 +348,11 @@
 }
 
 TEST_F(VehicleHalManagerTest, get_StaticString) {
+    auto pValue = objectPool->obtainString(kCarMake);
+    pValue->prop = toInt(VehicleProperty::INFO_MAKE);
+    pValue->areaId = 0;
+    ASSERT_EQ(StatusCode::OK, hal->set(*pValue.get()));
+
     invokeGet(toInt(VehicleProperty::INFO_MAKE), 0);
 
     ASSERT_EQ(StatusCode::OK, actualStatusCode);
@@ -458,6 +477,138 @@
     ASSERT_TRUE(clients.isEmpty());
 }
 
+TEST_F(VehicleHalManagerTest, debug) {
+    hidl_handle fd = {};
+    fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true);
+
+    // Because debug function returns void, so no way to check return value.
+    manager->debug(fd, {});
+    manager->debug(fd, {"--help"});
+    manager->debug(fd, {"--list"});
+    manager->debug(fd, {"--get"});
+    manager->debug(fd, {"--set"});
+    manager->debug(fd, {"invalid"});
+}
+
+struct SetPropTestCase {
+    std::string test_name;
+    const hidl_vec<hidl_string> configs;
+    bool success;
+};
+
+class VehicleHalManagerSetPropTest : public VehicleHalManagerTest,
+                                     public testing::WithParamInterface<SetPropTestCase> {};
+
+TEST_P(VehicleHalManagerSetPropTest, cmdSetOneProperty) {
+    const SetPropTestCase& tc = GetParam();
+    VehicleHalManagerTestHelper helper(manager.get());
+    ASSERT_EQ(tc.success, helper.cmdSetOneProperty(STDERR_FILENO, tc.configs));
+}
+
+std::vector<SetPropTestCase> GenSetPropParams() {
+    char infoMakeProperty[100] = {};
+    snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+    return {
+            {"success_set_string", {"--set", infoMakeProperty, "-s", kCarMake}, true},
+            {"success_set_bytes", {"--set", infoMakeProperty, "-b", "0xdeadbeef"}, true},
+            {"success_set_bytes_caps", {"--set", infoMakeProperty, "-b", "0xDEADBEEF"}, true},
+            {"success_set_int", {"--set", infoMakeProperty, "-i", "2147483647"}, true},
+            {"success_set_ints",
+             {"--set", infoMakeProperty, "-i", "2147483647", "0", "-2147483648"},
+             true},
+            {"success_set_int64",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775808"},
+             true},
+            {"success_set_int64s",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775808", "0",
+              "9223372036854775807"},
+             true},
+            {"success_set_float", {"--set", infoMakeProperty, "-f", "1.175494351E-38"}, true},
+            {"success_set_floats",
+             {"--set", infoMakeProperty, "-f", "-3.402823466E+38", "0", "3.402823466E+38"},
+             true},
+            {"success_set_area", {"--set", infoMakeProperty, "-a", "2147483647"}, true},
+            {"fail_no_options", {}, false},
+            {"fail_less_than_4_options", {"--set", infoMakeProperty, "-i"}, false},
+            {"fail_unknown_options", {"--set", infoMakeProperty, "-s", kCarMake, "-abcd"}, false},
+            {"fail_invalid_property", {"--set", "not valid", "-s", kCarMake}, false},
+            {"fail_duplicate_string",
+             {"--set", infoMakeProperty, "-s", kCarMake, "-s", kCarMake},
+             false},
+            {"fail_multiple_strings", {"--set", infoMakeProperty, "-s", kCarMake, kCarMake}, false},
+            {"fail_no_string_value", {"--set", infoMakeProperty, "-s", "-a", "1234"}, false},
+            {"fail_duplicate_bytes",
+             {"--set", infoMakeProperty, "-b", "0xdeadbeef", "-b", "0xdeadbeef"},
+             false},
+            {"fail_multiple_bytes",
+             {"--set", infoMakeProperty, "-b", "0xdeadbeef", "0xdeadbeef"},
+             false},
+            {"fail_invalid_bytes", {"--set", infoMakeProperty, "-b", "0xgood"}, false},
+            {"fail_invalid_bytes_no_prefix", {"--set", infoMakeProperty, "-b", "deadbeef"}, false},
+            {"fail_invalid_int", {"--set", infoMakeProperty, "-i", "abc"}, false},
+            {"fail_int_out_of_range", {"--set", infoMakeProperty, "-i", "2147483648"}, false},
+            {"fail_no_int_value", {"--set", infoMakeProperty, "-i", "-s", kCarMake}, false},
+            {"fail_invalid_int64", {"--set", infoMakeProperty, "-i64", "abc"}, false},
+            {"fail_int64_out_of_range",
+             {"--set", infoMakeProperty, "-i64", "-9223372036854775809"},
+             false},
+            {"fail_no_int64_value", {"--set", infoMakeProperty, "-i64", "-s", kCarMake}, false},
+            {"fail_invalid_float", {"--set", infoMakeProperty, "-f", "abc"}, false},
+            {"fail_float_out_of_range",
+             {"--set", infoMakeProperty, "-f", "-3.402823466E+39"},
+             false},
+            {"fail_no_float_value", {"--set", infoMakeProperty, "-f", "-s", kCarMake}, false},
+            {"fail_multiple_areas", {"--set", infoMakeProperty, "-a", "2147483648", "0"}, false},
+            {"fail_invalid_area", {"--set", infoMakeProperty, "-a", "abc"}, false},
+            {"fail_area_out_of_range", {"--set", infoMakeProperty, "-a", "2147483648"}, false},
+            {"fail_no_area_value", {"--set", infoMakeProperty, "-a", "-s", kCarMake}, false},
+    };
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        VehicleHalManagerSetPropTests, VehicleHalManagerSetPropTest,
+        testing::ValuesIn(GenSetPropParams()),
+        [](const testing::TestParamInfo<VehicleHalManagerSetPropTest::ParamType>& info) {
+            return info.param.test_name;
+        });
+
+TEST_F(VehicleHalManagerTest, SetComplexPropTest) {
+    char infoMakeProperty[100] = {};
+    snprintf(infoMakeProperty, sizeof(infoMakeProperty), "%d", toInt(VehicleProperty::INFO_MAKE));
+    VehicleHalManagerTestHelper helper(manager.get());
+    ASSERT_TRUE(helper.cmdSetOneProperty(
+            STDERR_FILENO, {"--set", infoMakeProperty,      "-s",   kCarMake,
+                            "-b",    "0xdeadbeef",          "-i",   "2147483647",
+                            "0",     "-2147483648",         "-i64", "-9223372036854775808",
+                            "0",     "9223372036854775807", "-f",   "-3.402823466E+38",
+                            "0",     "3.402823466E+38",     "-a",   "123"}));
+    StatusCode status = StatusCode::OK;
+    VehiclePropValue requestProp;
+    requestProp.prop = toInt(VehicleProperty::INFO_MAKE);
+    requestProp.areaId = 123;
+    auto value = hal->get(requestProp, &status);
+    ASSERT_EQ(StatusCode::OK, status);
+    ASSERT_EQ(value->prop, toInt(VehicleProperty::INFO_MAKE));
+    ASSERT_EQ(value->areaId, 123);
+    ASSERT_STREQ(kCarMake, value->value.stringValue.c_str());
+    uint8_t bytes[] = {0xde, 0xad, 0xbe, 0xef};
+    ASSERT_FALSE(memcmp(bytes, value->value.bytes.data(), sizeof(bytes)));
+    ASSERT_EQ(3u, value->value.int32Values.size());
+    ASSERT_EQ(2147483647, value->value.int32Values[0]);
+    ASSERT_EQ(0, value->value.int32Values[1]);
+    ASSERT_EQ(-2147483648, value->value.int32Values[2]);
+    ASSERT_EQ(3u, value->value.int64Values.size());
+    // -9223372036854775808 is not a valid literal since '-' and '9223372036854775808' would be two
+    // tokens and the later does not fit in unsigned long long.
+    ASSERT_EQ(-9223372036854775807 - 1, value->value.int64Values[0]);
+    ASSERT_EQ(0, value->value.int64Values[1]);
+    ASSERT_EQ(9223372036854775807, value->value.int64Values[2]);
+    ASSERT_EQ(3u, value->value.floatValues.size());
+    ASSERT_EQ(-3.402823466E+38f, value->value.floatValues[0]);
+    ASSERT_EQ(0.0f, value->value.floatValues[1]);
+    ASSERT_EQ(3.402823466E+38f, value->value.floatValues[2]);
+}
+
 }  // namespace anonymous
 
 }  // namespace V2_0
diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal
new file mode 100644
index 0000000..a09bdf9
--- /dev/null
+++ b/camera/metadata/3.7/types.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.7;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.6::CameraMetadataTag {
+    /** android.info.deviceStateOrientations [static, int64[], ndk_public]
+     */
+    ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4,
+
+    ANDROID_INFO_END_3_7,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index c89d983..d02547c 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -882,6 +882,7 @@
             camera_metadata* oldSessionParams, camera_metadata* newSessionParams);
 
     void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
+    static void overrideRotateAndCrop(::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/);
 
     static bool isDepthOnly(const camera_metadata_t* staticMeta);
 
@@ -935,6 +936,9 @@
             camera_metadata_ro_entry* streamConfigs,
             camera_metadata_ro_entry* maxResolutionStreamConfigs,
             const camera_metadata_t* staticMetadata);
+    void getPrivacyTestPatternModes(
+            const camera_metadata_t* staticMetadata,
+            std::unordered_set<int32_t>* privacyTestPatternModes/*out*/);
     static bool isColorCamera(const camera_metadata_t *metadata);
 
     static V3_2::DataspaceFlags getDataspace(PixelFormat format);
@@ -4660,6 +4664,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         hidl_handle buffer_handle;
         StreamBuffer outputBuffer;
@@ -4836,6 +4841,7 @@
         settings.setToExternal(
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (settingsBuffer)),
                 get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
 
         free_camera_metadata(staticMeta);
         ret = session->close();
@@ -4913,6 +4919,7 @@
                 reinterpret_cast<uint8_t *> (const_cast<camera_metadata_t *> (
                         filteredSettingsBuffer)),
                 get_camera_metadata_size(filteredSettingsBuffer));
+        overrideRotateAndCrop(&camSettings[0].settings);
         camSettings[0].fmqSettingsSize = 0;
         camSettings[0].physicalCameraId = physicalDeviceId;
 
@@ -5070,6 +5077,7 @@
         settings.setToExternal(
                 reinterpret_cast<uint8_t*>(const_cast<camera_metadata_t*>(settingsBuffer)),
                 get_camera_metadata_size(settingsBuffer));
+        overrideRotateAndCrop(&settings);
 
         free_camera_metadata(staticMeta);
         ret = session->close();
@@ -5305,6 +5313,7 @@
             camera_metadata_t *metaBuffer = requestMeta.release();
             requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
                     get_camera_metadata_size(metaBuffer), true);
+            overrideRotateAndCrop(&requestSettings[i]);
 
             requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
                 emptyInputBuffer, {outputBuffers[i]}};
@@ -5531,6 +5540,7 @@
             camera_metadata_t *metaBuffer = requestMeta.release();
             requestSettings[i].setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
                     get_camera_metadata_size(metaBuffer), true);
+            overrideRotateAndCrop(&requestSettings[i]);
 
             requests[i] = {frameNumber + i, 0 /* fmqSettingsSize */, requestSettings[i],
                 emptyInputBuffer, {outputBuffers[i]}};
@@ -5671,6 +5681,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
         StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
@@ -5755,6 +5766,7 @@
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        overrideRotateAndCrop(&settings);
 
         hidl_handle buffer_handle;
         if (useHalBufManager) {
@@ -6753,6 +6765,25 @@
     ASSERT_TRUE(-ENOENT == retcode || 0 == retcode);
 }
 
+void CameraHidlTest::getPrivacyTestPatternModes(
+        const camera_metadata_t* staticMetadata,
+        std::unordered_set<int32_t>* privacyTestPatternModes/*out*/) {
+    ASSERT_NE(staticMetadata, nullptr);
+    ASSERT_NE(privacyTestPatternModes, nullptr);
+
+    camera_metadata_ro_entry entry;
+    int retcode = find_camera_metadata_ro_entry(
+            staticMetadata, ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, &entry);
+    ASSERT_TRUE(0 == retcode);
+
+    for (auto i = 0; i < entry.count; i++) {
+        if (entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR ||
+                entry.data.i32[i] == ANDROID_SENSOR_TEST_PATTERN_MODE_BLACK) {
+            privacyTestPatternModes->insert(entry.data.i32[i]);
+        }
+    }
+}
+
 // Select an appropriate dataspace given a specific pixel format.
 V3_2::DataspaceFlags CameraHidlTest::getDataspace(PixelFormat format) {
     switch (format) {
@@ -7807,6 +7838,16 @@
         ASSERT_TRUE(isUltraHighResCamera && !isMultiCamera);
         physicalIds.insert(cameraId);
     }
+
+    std::unordered_set<int32_t> physicalRequestKeyIDs;
+    rc = getSupportedKeys(const_cast<camera_metadata_t *>(metadata),
+            ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS, &physicalRequestKeyIDs);
+    ASSERT_TRUE(Status::OK == rc);
+    bool hasTestPatternPhysicalRequestKey = physicalRequestKeyIDs.find(
+            ANDROID_SENSOR_TEST_PATTERN_MODE) != physicalRequestKeyIDs.end();
+    std::unordered_set<int32_t> privacyTestPatternModes;
+    getPrivacyTestPatternModes(metadata, &privacyTestPatternModes);
+
     // Map from image format to number of multi-resolution sizes for that format
     std::unordered_map<int32_t, size_t> multiResOutputFormatCounterMap;
     std::unordered_map<int32_t, size_t> multiResInputFormatCounterMap;
@@ -7828,6 +7869,7 @@
         camera_metadata_ro_entry physicalStreamConfigs;
         camera_metadata_ro_entry physicalMaxResolutionStreamConfigs;
         bool isUltraHighRes = false;
+        std::unordered_set<int32_t> subCameraPrivacyTestPatterns;
         if (isPublicId) {
             ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> subDevice;
             Return<void> ret;
@@ -7858,6 +7900,8 @@
                         &physicalMultiResStreamConfigs, &physicalStreamConfigs,
                         &physicalMaxResolutionStreamConfigs, staticMetadata);
                 isUltraHighRes = isUltraHighResolution(staticMetadata);
+
+                getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
             });
             ASSERT_TRUE(ret.isOk());
         } else {
@@ -7884,6 +7928,7 @@
                                 &physicalMultiResStreamConfigs, &physicalStreamConfigs,
                                 &physicalMaxResolutionStreamConfigs, staticMetadata);
                         isUltraHighRes = isUltraHighResolution(staticMetadata);
+                        getPrivacyTestPatternModes(staticMetadata, &subCameraPrivacyTestPatterns);
                     });
             ASSERT_TRUE(ret.isOk());
 
@@ -7900,6 +7945,10 @@
             ASSERT_TRUE(ret.isOk());
         }
 
+        if (hasTestPatternPhysicalRequestKey) {
+            ASSERT_TRUE(privacyTestPatternModes == subCameraPrivacyTestPatterns);
+        }
+
         if (physicalMultiResStreamConfigs.count > 0) {
             ASSERT_GE(deviceVersion, CAMERA_DEVICE_API_VERSION_3_7);
             ASSERT_EQ(physicalMultiResStreamConfigs.count % 4, 0);
@@ -8135,6 +8184,20 @@
                 poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
     }
 
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry);
+    if (0 == retcode && entry.count > 0) {
+        ASSERT_TRUE((entry.count % 2) == 0);
+        uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1;
+        uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states
+        uint64_t stateMask = (1 << vendorStateStart) - 1;
+        stateMask &= ~((1 << maxPublicState) - 1);
+        for (int i = 0; i < entry.count; i += 2){
+            ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0);
+            ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0);
+        }
+    }
+
     verifyExtendedSceneModeCharacteristics(metadata);
     verifyZoomCharacteristics(metadata);
 }
@@ -8895,6 +8958,25 @@
     }
 }
 
+void CameraHidlTest::overrideRotateAndCrop(
+        ::android::hardware::hidl_vec<uint8_t> *settings /*in/out*/) {
+    if (settings == nullptr) {
+        return;
+    }
+
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+    requestMeta.append(reinterpret_cast<camera_metadata_t *> (settings->data()));
+    auto entry = requestMeta.find(ANDROID_SCALER_ROTATE_AND_CROP);
+    if ((entry.count > 0) && (entry.data.u8[0] == ANDROID_SCALER_ROTATE_AND_CROP_AUTO)) {
+        uint8_t disableRotateAndCrop = ANDROID_SCALER_ROTATE_AND_CROP_NONE;
+        requestMeta.update(ANDROID_SCALER_ROTATE_AND_CROP, &disableRotateAndCrop, 1);
+        settings->releaseData();
+        camera_metadata_t *metaBuffer = requestMeta.release();
+        settings->setToExternal(reinterpret_cast<uint8_t *> (metaBuffer),
+                get_camera_metadata_size(metaBuffer), true);
+    }
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CameraHidlTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, CameraHidlTest,
diff --git a/current.txt b/current.txt
index 21ee123..14e709e 100644
--- a/current.txt
+++ b/current.txt
@@ -901,6 +901,9 @@
 4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
 70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types
 
+# HALs released in Android SCv2
+77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
+
 # ABI preserving changes to HALs during Android T
 62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
 ca62a2a95d173ed323309e5e00f653ad3cceec82a6e5e4976a249cb5aafe2515 android.hardware.neuralnetworks@1.2::types
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 8cb7e22..114fe4f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -317,7 +317,7 @@
 }
 
 bool waitForFrameworkReady() {
-    int waitCount = 10;
+    int waitCount = 15;
     do {
         // Check whether package service is ready or not.
         if (!testing::checkSubstringInCommandOutput(
diff --git a/wifi/supplicant/1.4/vts/functional/Android.bp b/wifi/supplicant/1.4/vts/functional/Android.bp
index 8cbe04f..57ee830 100644
--- a/wifi/supplicant/1.4/vts/functional/Android.bp
+++ b/wifi/supplicant/1.4/vts/functional/Android.bp
@@ -77,7 +77,6 @@
         "general-tests",
         "vts",
     ],
-    disable_framework: true,
 }
 
 cc_test {
@@ -108,5 +107,4 @@
         "general-tests",
         "vts",
     ],
-    disable_framework: true,
 }