Merge "Migrate fake value generator."
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index e1b9729..c33a2e7 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/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 4af3e5b..3fc9353 100644
--- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -105,7 +105,7 @@
   EV_BATTERY_DISPLAY_UNITS = 289408515,
   FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME = 287311364,
   VEHICLE_SPEED_DISPLAY_UNITS = 289408517,
-  EPOCH_TIME = 290457094,
+  ANDROID_EPOCH_TIME = 290457094,
   STORAGE_ENCRYPTION_BINDING_SEED = 292554247,
   ENV_OUTSIDE_TEMPERATURE = 291505923,
   AP_POWER_STATE_REQ = 289475072,
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 65a22db..e3b5a38 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -1035,24 +1035,32 @@
     VEHICLE_SPEED_DISPLAY_UNITS = 0x0605 + 0x10000000 + 0x01000000
             + 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
     /**
-     * Current date and time, encoded as Unix time (in milliseconds).
+     * Current date and time, encoded as Epoch time (in milliseconds).
      * This value denotes the number of milliseconds seconds that have
      * elapsed since 1/1/1970 UTC.
      *
-     * Reading this value will give you the system’s time. This can be
-     * useful to synchronize other vehicle systems (dash clock etc).
+     * CarServices will write to this value to give VHAL the Android system's
+     * time, if the VHAL supports this property. This can be useful to
+     * synchronize other vehicle systems (dash clock etc) with Android's time.
      *
-     * Writing this value will update the ‘ExternalTimeSuggestion’
-     * value (if enabled). This value may be consumed by the “Time
-     * Detector Service”, if other sources do not have a higher
-     * priority. For information on how to adjust time source
-     * priorities see Time Detector Service documentation.
+     * AAOS writes to this property once during boot, and
+     * will thereafter write only when some time-source changes are propagated.
+     * AAOS will fill in VehiclePropValue.timestamp correctly.
+     * Note that AAOS will not send updates for natural elapse of time.
+     *     int64Values[0] = provided Unix time (in milliseconds)
+     *
+     * Note that the property may take >0 ms to get propagated through the stack
+     * and, having a timestamped property helps reduce any time drift. So,
+     * for all writes to the property, the timestamp can be used to negate this
+     * drift:
+     *     drift = elapsedTime - PropValue.timestamp
+     *     effectiveTime = PropValue.value.int64Values[0] + drift
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
+     * @access VehiclePropertyAccess:WRITE_ONLY
      * @unit VehicleUnit:MILLI_SECS
      */
-    EPOCH_TIME = 0x0606 + 0x10000000 + 0x01000000
+    ANDROID_EPOCH_TIME = 0x0606 + 0x10000000 + 0x01000000
             + 0x00500000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT64
     /**
      * External encryption binding seed.
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
index 12a5691..d2b69af 100644
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -1016,8 +1016,8 @@
         {
                 .config =
                         {
-                                .prop = toInt(VehicleProperty::EPOCH_TIME),
-                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .prop = toInt(VehicleProperty::ANDROID_EPOCH_TIME),
+                                .access = VehiclePropertyAccess::WRITE,
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
index ea06752..31b0dc7 100644
--- a/graphics/composer/2.2/vts/functional/OWNERS
+++ b/graphics/composer/2.2/vts/functional/OWNERS
@@ -1,7 +1,5 @@
+# Bug component: 25423
 # Graphics team
 adyabr@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
index ea06752..31b0dc7 100644
--- a/graphics/composer/2.3/vts/functional/OWNERS
+++ b/graphics/composer/2.3/vts/functional/OWNERS
@@ -1,7 +1,5 @@
+# Bug component: 25423
 # Graphics team
 adyabr@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/composer/2.4/vts/functional/OWNERS b/graphics/composer/2.4/vts/functional/OWNERS
index ea06752..31b0dc7 100644
--- a/graphics/composer/2.4/vts/functional/OWNERS
+++ b/graphics/composer/2.4/vts/functional/OWNERS
@@ -1,7 +1,5 @@
+# Bug component: 25423
 # Graphics team
 adyabr@google.com
 lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index 5006185..e33c653 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -67,3 +67,22 @@
     ],
     export_include_dirs: ["include"],
 }
+
+cc_library_headers {
+    name: "android.hardware.graphics.composer3-command-buffer",
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer3-V1-ndk",
+        "libbase",
+        "libfmq",
+        "libsync",
+    ],
+    static_libs: [
+        "libaidlcommonsupport",
+    ],
+    export_shared_lib_headers: [
+        "libfmq",
+        "libsync",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/aidl/OWNERS b/graphics/composer/aidl/OWNERS
new file mode 100644
index 0000000..9028d9d
--- /dev/null
+++ b/graphics/composer/aidl/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 1075131
+
+# Graphics team
+adyabr@google.com
+alecmouri@google.com
+sumir@google.com
\ No newline at end of file
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
index 557b3f8..9c49583 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Capability.aidl
@@ -38,4 +38,5 @@
   SIDEBAND_STREAM = 1,
   SKIP_CLIENT_COLOR_TRANSFORM = 2,
   PRESENT_FENCE_IS_NOT_RELIABLE = 3,
+  SKIP_VALIDATE = 4,
 }
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index 8824f5a..5c37018 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -40,7 +40,6 @@
   void destroyVirtualDisplay(long display);
   android.hardware.graphics.composer3.ExecuteCommandsStatus executeCommands(int inLength, in android.hardware.common.NativeHandle[] inHandles);
   int getActiveConfig(long display);
-  void getClientTargetSupport(long display, int width, int height, in android.hardware.graphics.composer3.ClientTargetProperty clientTargetProperty);
   android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
   float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
   int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
index 028b6f5..ea619ae 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Capability.aidl
@@ -46,4 +46,15 @@
      * representation of the actual present time of a frame.
      */
     PRESENT_FENCE_IS_NOT_RELIABLE = 3,
+    /**
+     * Specifies that a device is able to skip the validateDisplay call before
+     * receiving a call to presentDisplay. The client will always skip
+     * validateDisplay and try to call presentDisplay regardless of the changes
+     * in the properties of the layers. If the device returns anything else than
+     * no error, it will call validateDisplay then presentDisplay again.
+     * For this capability to be worthwhile the device implementation of
+     * presentDisplay should fail as fast as possible in the case a
+     * validateDisplay step is needed.
+     */
+    SKIP_VALIDATE = 4,
 }
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index 20a6ffc..2a9545d 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -189,25 +189,6 @@
     int getActiveConfig(long display);
 
     /**
-     * Returns whether a client target with the given properties can be
-     * handled by the device.
-     *
-     * This function must return true for a client target with width and
-     * height equal to the active display configuration dimensions,
-     * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to
-     * return true for any other configuration.
-     *
-     * @param display is the display to query.
-     * @param width is the client target width in pixels.
-     * @param height is the client target height in pixels.
-     * @param clientTargetProperty is the client target format and dataspace.
-     * @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
-     * @exception EX_UNSUPPORTED when the given configuration is not supported.
-     */
-    void getClientTargetSupport(
-            long display, int width, int height, in ClientTargetProperty clientTargetProperty);
-
-    /**
      * Returns the color modes supported on this display.
      *
      * All devices must support at least ColorMode::NATIVE.
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
index a593e90..d59190d 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/translate-ndk.cpp
@@ -70,6 +70,9 @@
         static_cast<aidl::android::hardware::graphics::composer3::Capability>(
                 ::android::hardware::graphics::composer::V2_1::IComposer::Capability::
                         PRESENT_FENCE_IS_NOT_RELIABLE));
+// HWC2_CAPABILITY_SKIP_VALIDATE was never defined for HIDL, so we just hardcode its value
+static_assert(aidl::android::hardware::graphics::composer3::Capability::SKIP_VALIDATE ==
+              static_cast<aidl::android::hardware::graphics::composer3::Capability>(4));
 
 static_assert(aidl::android::hardware::graphics::composer3::LayerRequest::CLEAR_CLIENT_TARGET ==
               static_cast<aidl::android::hardware::graphics::composer3::LayerRequest>(
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
new file mode 100644
index 0000000..d02cf9c
--- /dev/null
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/command-buffer.h
@@ -0,0 +1,895 @@
+/*
+ * Copyright 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.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <aidl/android/hardware/graphics/composer3/BlendMode.h>
+#include <aidl/android/hardware/graphics/composer3/ClientTargetProperty.h>
+#include <aidl/android/hardware/graphics/composer3/Color.h>
+#include <aidl/android/hardware/graphics/composer3/Command.h>
+#include <aidl/android/hardware/graphics/composer3/Composition.h>
+#include <aidl/android/hardware/graphics/composer3/FloatColor.h>
+#include <aidl/android/hardware/graphics/composer3/HandleIndex.h>
+#include <aidl/android/hardware/graphics/composer3/IComposer.h>
+#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
+#include <aidl/android/hardware/graphics/composer3/PerFrameMetadata.h>
+#include <aidl/android/hardware/graphics/composer3/PerFrameMetadataBlob.h>
+
+#include <aidl/android/hardware/graphics/common/ColorTransform.h>
+#include <aidl/android/hardware/graphics/common/FRect.h>
+#include <aidl/android/hardware/graphics/common/Rect.h>
+#include <aidl/android/hardware/graphics/common/Transform.h>
+
+#include <fmq/AidlMessageQueue.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+#include <aidlcommonsupport/NativeHandle.h>
+
+using aidl::android::hardware::graphics::common::ColorTransform;
+using aidl::android::hardware::graphics::common::Dataspace;
+using aidl::android::hardware::graphics::common::FRect;
+using aidl::android::hardware::graphics::common::Rect;
+using aidl::android::hardware::graphics::common::Transform;
+
+using aidl::android::hardware::graphics::composer3::BlendMode;
+using aidl::android::hardware::graphics::composer3::ClientTargetProperty;
+using aidl::android::hardware::graphics::composer3::Color;
+using aidl::android::hardware::graphics::composer3::Command;
+using aidl::android::hardware::graphics::composer3::Composition;
+using aidl::android::hardware::graphics::composer3::FloatColor;
+using aidl::android::hardware::graphics::composer3::HandleIndex;
+using aidl::android::hardware::graphics::composer3::PerFrameMetadata;
+using aidl::android::hardware::graphics::composer3::PerFrameMetadataBlob;
+
+using aidl::android::hardware::common::NativeHandle;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using android::AidlMessageQueue;
+using CommandQueueType = AidlMessageQueue<int32_t, SynchronizedReadWrite>;
+using aidl::android::hardware::common::fmq::MQDescriptor;
+using DescriptorType = MQDescriptor<int32_t, SynchronizedReadWrite>;
+
+namespace aidl::android::hardware::graphics::composer3 {
+
+// This class helps build a command queue.  Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandWriterBase {
+  public:
+    CommandWriterBase(uint32_t initialMaxSize) : mDataMaxSize(initialMaxSize) {
+        mData = std::make_unique<int32_t[]>(mDataMaxSize);
+        reset();
+    }
+
+    virtual ~CommandWriterBase() { reset(); }
+
+    void reset() {
+        mDataWritten = 0;
+        mCommandEnd = 0;
+
+        // handles in mDataHandles are owned by the caller
+        mDataHandles.clear();
+
+        // handles in mTemporaryHandles are owned by the writer
+        for (auto handle : mTemporaryHandles) {
+            native_handle_close(handle);
+            native_handle_delete(handle);
+        }
+        mTemporaryHandles.clear();
+    }
+
+    Command getCommand(uint32_t offset) {
+        uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
+        return static_cast<Command>(val & static_cast<uint32_t>(Command::OPCODE_MASK));
+    }
+
+    bool writeQueue(bool* outQueueChanged, int32_t* outCommandLength,
+                    std::vector<NativeHandle>* outCommandHandles) {
+        if (mDataWritten == 0) {
+            *outQueueChanged = false;
+            *outCommandLength = 0;
+            outCommandHandles->clear();
+            return true;
+        }
+
+        // After data are written to the queue, it may not be read by the
+        // remote reader when
+        //
+        //  - the writer does not send them (because of other errors)
+        //  - the hwbinder transaction fails
+        //  - the reader does not read them (because of other errors)
+        //
+        // Discard the stale data here.
+        size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
+        if (staleDataSize > 0) {
+            ALOGW("discarding stale data from message queue");
+            CommandQueueType::MemTransaction tx;
+            if (mQueue->beginRead(staleDataSize, &tx)) {
+                mQueue->commitRead(staleDataSize);
+            }
+        }
+
+        // write data to queue, optionally resizing it
+        if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
+            if (!mQueue->write(mData.get(), mDataWritten)) {
+                ALOGE("failed to write commands to message queue");
+                return false;
+            }
+
+            *outQueueChanged = false;
+        } else {
+            auto newQueue = std::make_unique<CommandQueueType>(mDataMaxSize);
+            if (!newQueue->isValid() || !newQueue->write(mData.get(), mDataWritten)) {
+                ALOGE("failed to prepare a new message queue ");
+                return false;
+            }
+
+            mQueue = std::move(newQueue);
+            *outQueueChanged = true;
+        }
+
+        *outCommandLength = mDataWritten;
+        *outCommandHandles = std::move(mDataHandles);
+
+        return true;
+    }
+
+    DescriptorType getMQDescriptor() const {
+        return (mQueue) ? mQueue->dupeDesc() : DescriptorType{};
+    }
+
+    static constexpr uint16_t kSelectDisplayLength = 2;
+    void selectDisplay(int64_t display) {
+        beginCommand(Command::SELECT_DISPLAY, kSelectDisplayLength);
+        write64(display);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSelectLayerLength = 2;
+    void selectLayer(int64_t layer) {
+        beginCommand(Command::SELECT_LAYER, kSelectLayerLength);
+        write64(layer);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetErrorLength = 2;
+    void setError(uint32_t location, int32_t error) {
+        beginCommand(Command::SET_ERROR, kSetErrorLength);
+        write(location);
+        writeSigned(error);
+        endCommand();
+    }
+
+    static constexpr uint32_t kPresentOrValidateDisplayResultLength = 1;
+    void setPresentOrValidateResult(uint32_t state) {
+        beginCommand(Command::SET_PRESENT_OR_VALIDATE_DISPLAY_RESULT,
+                     kPresentOrValidateDisplayResultLength);
+        write(state);
+        endCommand();
+    }
+
+    void setChangedCompositionTypes(const std::vector<int64_t>& layers,
+                                    const std::vector<Composition>& types) {
+        size_t totalLayers = std::min(layers.size(), types.size());
+        size_t currentLayer = 0;
+
+        while (currentLayer < totalLayers) {
+            size_t count =
+                    std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);
+
+            beginCommand(Command::SET_CHANGED_COMPOSITION_TYPES, count * 3);
+            for (size_t i = 0; i < count; i++) {
+                write64(layers[currentLayer + i]);
+                writeSigned(static_cast<int32_t>(types[currentLayer + i]));
+            }
+            endCommand();
+
+            currentLayer += count;
+        }
+    }
+
+    void setDisplayRequests(uint32_t displayRequestMask, const std::vector<int64_t>& layers,
+                            const std::vector<uint32_t>& layerRequestMasks) {
+        size_t totalLayers = std::min(layers.size(), layerRequestMasks.size());
+        size_t currentLayer = 0;
+
+        while (currentLayer < totalLayers) {
+            size_t count =
+                    std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength - 1) / 3);
+
+            beginCommand(Command::SET_DISPLAY_REQUESTS, 1 + count * 3);
+            write(displayRequestMask);
+            for (size_t i = 0; i < count; i++) {
+                write64(layers[currentLayer + i]);
+                write(static_cast<int32_t>(layerRequestMasks[currentLayer + i]));
+            }
+            endCommand();
+
+            currentLayer += count;
+        }
+    }
+
+    static constexpr uint16_t kSetPresentFenceLength = 1;
+    void setPresentFence(int presentFence) {
+        beginCommand(Command::SET_PRESENT_FENCE, kSetPresentFenceLength);
+        writeFence(presentFence);
+        endCommand();
+    }
+
+    void setReleaseFences(const std::vector<int64_t>& layers,
+                          const std::vector<int>& releaseFences) {
+        size_t totalLayers = std::min(layers.size(), releaseFences.size());
+        size_t currentLayer = 0;
+
+        while (currentLayer < totalLayers) {
+            size_t count =
+                    std::min(totalLayers - currentLayer, static_cast<size_t>(kMaxLength) / 3);
+
+            beginCommand(Command::SET_RELEASE_FENCES, count * 3);
+            for (size_t i = 0; i < count; i++) {
+                write64(layers[currentLayer + i]);
+                writeFence(releaseFences[currentLayer + i]);
+            }
+            endCommand();
+
+            currentLayer += count;
+        }
+    }
+
+    static constexpr uint16_t kSetColorTransformLength = 17;
+    void setColorTransform(const float* matrix, ColorTransform hint) {
+        beginCommand(Command::SET_COLOR_TRANSFORM, kSetColorTransformLength);
+        for (int i = 0; i < 16; i++) {
+            writeFloat(matrix[i]);
+        }
+        writeSigned(static_cast<int32_t>(hint));
+        endCommand();
+    }
+
+    void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
+                         Dataspace dataspace, const std::vector<Rect>& damage) {
+        setClientTargetInternal(slot, target, acquireFence, static_cast<int32_t>(dataspace),
+                                damage);
+    }
+
+    static constexpr uint16_t kSetOutputBufferLength = 3;
+    void setOutputBuffer(uint32_t slot, const native_handle_t* buffer, int releaseFence) {
+        beginCommand(Command::SET_OUTPUT_BUFFER, kSetOutputBufferLength);
+        write(slot);
+        writeHandle(buffer, true);
+        writeFence(releaseFence);
+        endCommand();
+    }
+
+    static constexpr uint16_t kValidateDisplayLength = 0;
+    void validateDisplay() {
+        beginCommand(Command::VALIDATE_DISPLAY, kValidateDisplayLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kPresentOrValidateDisplayLength = 0;
+    void presentOrvalidateDisplay() {
+        beginCommand(Command::PRESENT_OR_VALIDATE_DISPLAY, kPresentOrValidateDisplayLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kAcceptDisplayChangesLength = 0;
+    void acceptDisplayChanges() {
+        beginCommand(Command::ACCEPT_DISPLAY_CHANGES, kAcceptDisplayChangesLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kPresentDisplayLength = 0;
+    void presentDisplay() {
+        beginCommand(Command::PRESENT_DISPLAY, kPresentDisplayLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerCursorPositionLength = 2;
+    void setLayerCursorPosition(int32_t x, int32_t y) {
+        beginCommand(Command::SET_LAYER_CURSOR_POSITION, kSetLayerCursorPositionLength);
+        writeSigned(x);
+        writeSigned(y);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerBufferLength = 3;
+    void setLayerBuffer(uint32_t slot, const native_handle_t* buffer, int acquireFence) {
+        beginCommand(Command::SET_LAYER_BUFFER, kSetLayerBufferLength);
+        write(slot);
+        writeHandle(buffer, true);
+        writeFence(acquireFence);
+        endCommand();
+    }
+
+    void setLayerSurfaceDamage(const std::vector<Rect>& damage) {
+        bool doWrite = (damage.size() <= kMaxLength / 4);
+        size_t length = (doWrite) ? damage.size() * 4 : 0;
+
+        beginCommand(Command::SET_LAYER_SURFACE_DAMAGE, length);
+        // When there are too many rectangles in the damage region and doWrite
+        // is false, we write no rectangle at all which means the entire
+        // layer is damaged.
+        if (doWrite) {
+            writeRegion(damage);
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerBlendModeLength = 1;
+    void setLayerBlendMode(BlendMode mode) {
+        beginCommand(Command::SET_LAYER_BLEND_MODE, kSetLayerBlendModeLength);
+        writeSigned(static_cast<int32_t>(mode));
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerColorLength = 1;
+    void setLayerColor(Color color) {
+        beginCommand(Command::SET_LAYER_COLOR, kSetLayerColorLength);
+        writeColor(color);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerCompositionTypeLength = 1;
+    void setLayerCompositionType(Composition type) {
+        beginCommand(Command::SET_LAYER_COMPOSITION_TYPE, kSetLayerCompositionTypeLength);
+        writeSigned(static_cast<int32_t>(type));
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerDataspaceLength = 1;
+    void setLayerDataspace(Dataspace dataspace) {
+        setLayerDataspaceInternal(static_cast<int32_t>(dataspace));
+    }
+
+    static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
+    void setLayerDisplayFrame(const Rect& frame) {
+        beginCommand(Command::SET_LAYER_DISPLAY_FRAME, kSetLayerDisplayFrameLength);
+        writeRect(frame);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerPlaneAlphaLength = 1;
+    void setLayerPlaneAlpha(float alpha) {
+        beginCommand(Command::SET_LAYER_PLANE_ALPHA, kSetLayerPlaneAlphaLength);
+        writeFloat(alpha);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerSidebandStreamLength = 1;
+    void setLayerSidebandStream(const native_handle_t* stream) {
+        beginCommand(Command::SET_LAYER_SIDEBAND_STREAM, kSetLayerSidebandStreamLength);
+        writeHandle(stream);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerSourceCropLength = 4;
+    void setLayerSourceCrop(const FRect& crop) {
+        beginCommand(Command::SET_LAYER_SOURCE_CROP, kSetLayerSourceCropLength);
+        writeFRect(crop);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerTransformLength = 1;
+    void setLayerTransform(Transform transform) {
+        beginCommand(Command::SET_LAYER_TRANSFORM, kSetLayerTransformLength);
+        writeSigned(static_cast<int32_t>(transform));
+        endCommand();
+    }
+
+    void setLayerVisibleRegion(const std::vector<Rect>& visible) {
+        bool doWrite = (visible.size() <= kMaxLength / 4);
+        size_t length = (doWrite) ? visible.size() * 4 : 0;
+
+        beginCommand(Command::SET_LAYER_VISIBLE_REGION, length);
+        // When there are too many rectangles in the visible region and
+        // doWrite is false, we write no rectangle at all which means the
+        // entire layer is visible.
+        if (doWrite) {
+            writeRegion(visible);
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerZOrderLength = 1;
+    void setLayerZOrder(uint32_t z) {
+        beginCommand(Command::SET_LAYER_Z_ORDER, kSetLayerZOrderLength);
+        write(z);
+        endCommand();
+    }
+
+    void setLayerPerFrameMetadata(const std::vector<PerFrameMetadata>& metadataVec) {
+        beginCommand(Command::SET_LAYER_PER_FRAME_METADATA, metadataVec.size() * 2);
+        for (const auto& metadata : metadataVec) {
+            writeSigned(static_cast<int32_t>(metadata.key));
+            writeFloat(metadata.value);
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerColorTransformLength = 16;
+    void setLayerColorTransform(const float* matrix) {
+        beginCommand(Command::SET_LAYER_COLOR_TRANSFORM, kSetLayerColorTransformLength);
+        for (int i = 0; i < 16; i++) {
+            writeFloat(matrix[i]);
+        }
+        endCommand();
+    }
+
+    void setLayerPerFrameMetadataBlobs(const std::vector<PerFrameMetadataBlob>& metadata) {
+        // in units of uint32_t's
+        size_t commandLength = 0;
+
+        if (metadata.size() > std::numeric_limits<uint32_t>::max()) {
+            LOG_FATAL("too many metadata blobs - dynamic metadata size is too large");
+            return;
+        }
+
+        // space for numElements
+        commandLength += 1;
+
+        for (auto metadataBlob : metadata) {
+            commandLength += 1;  // key of metadata blob
+            commandLength += 1;  // size information of metadata blob
+
+            // metadata content size
+            size_t metadataSize = metadataBlob.blob.size() / sizeof(uint32_t);
+            commandLength += metadataSize;
+            commandLength +=
+                    (metadataBlob.blob.size() - (metadataSize * sizeof(uint32_t)) > 0) ? 1 : 0;
+        }
+
+        if (commandLength > std::numeric_limits<uint16_t>::max()) {
+            LOG_FATAL("dynamic metadata size is too large");
+            return;
+        }
+
+        // Blobs are written as:
+        // {numElements, key1, size1, blob1, key2, size2, blob2, key3, size3...}
+        uint16_t length = static_cast<uint16_t>(commandLength);
+        beginCommand(Command::SET_LAYER_PER_FRAME_METADATA_BLOBS, length);
+        write(static_cast<uint32_t>(metadata.size()));
+        for (auto metadataBlob : metadata) {
+            writeSigned(static_cast<int32_t>(metadataBlob.key));
+            write(static_cast<uint32_t>(metadataBlob.blob.size()));
+            writeBlob(static_cast<uint32_t>(metadataBlob.blob.size()), metadataBlob.blob.data());
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerFloatColorLength = 4;
+    void setLayerFloatColor(FloatColor color) {
+        beginCommand(Command::SET_LAYER_FLOAT_COLOR, kSetLayerFloatColorLength);
+        writeFloatColor(color);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetClientTargetPropertyLength = 2;
+    void setClientTargetProperty(const ClientTargetProperty& clientTargetProperty) {
+        beginCommand(Command::SET_CLIENT_TARGET_PROPERTY, kSetClientTargetPropertyLength);
+        writeSigned(static_cast<int32_t>(clientTargetProperty.pixelFormat));
+        writeSigned(static_cast<int32_t>(clientTargetProperty.dataspace));
+        endCommand();
+    }
+
+    void setLayerGenericMetadata(const std::string& key, const bool mandatory,
+                                 const std::vector<uint8_t>& value) {
+        const size_t commandSize = 3 + sizeToElements(key.size()) + sizeToElements(value.size());
+        if (commandSize > std::numeric_limits<uint16_t>::max()) {
+            LOG_FATAL("Too much generic metadata (%zu elements)", commandSize);
+            return;
+        }
+
+        beginCommand(Command::SET_LAYER_GENERIC_METADATA, static_cast<uint16_t>(commandSize));
+        write(key.size());
+        writeBlob(key.size(), reinterpret_cast<const unsigned char*>(key.c_str()));
+        write(mandatory);
+        write(value.size());
+        writeBlob(value.size(), value.data());
+        endCommand();
+    }
+
+  protected:
+    template <typename T>
+    void beginCommand(T command, uint16_t length) {
+        beginCommandBase(static_cast<Command>(command), length);
+    }
+
+    void setClientTargetInternal(uint32_t slot, const native_handle_t* target, int acquireFence,
+                                 int32_t dataspace, const std::vector<Rect>& damage) {
+        bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
+        size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
+
+        beginCommand(Command::SET_CLIENT_TARGET, length);
+        write(slot);
+        writeHandle(target, true);
+        writeFence(acquireFence);
+        writeSigned(dataspace);
+        // When there are too many rectangles in the damage region and doWrite
+        // is false, we write no rectangle at all which means the entire
+        // client target is damaged.
+        if (doWrite) {
+            writeRegion(damage);
+        }
+        endCommand();
+    }
+
+    void setLayerDataspaceInternal(int32_t dataspace) {
+        beginCommand(Command::SET_LAYER_DATASPACE, kSetLayerDataspaceLength);
+        writeSigned(dataspace);
+        endCommand();
+    }
+
+    void beginCommandBase(Command command, uint16_t length) {
+        if (mCommandEnd) {
+            LOG_FATAL("endCommand was not called before command 0x%x", command);
+        }
+
+        growData(1 + length);
+        write(static_cast<uint32_t>(command) | length);
+
+        mCommandEnd = mDataWritten + length;
+    }
+
+    void endCommand() {
+        if (!mCommandEnd) {
+            LOG_FATAL("beginCommand was not called");
+        } else if (mDataWritten > mCommandEnd) {
+            LOG_FATAL("too much data written");
+            mDataWritten = mCommandEnd;
+        } else if (mDataWritten < mCommandEnd) {
+            LOG_FATAL("too little data written");
+            while (mDataWritten < mCommandEnd) {
+                write(0);
+            }
+        }
+
+        mCommandEnd = 0;
+    }
+
+    void write(uint32_t val) { mData[mDataWritten++] = val; }
+
+    void writeSigned(int32_t val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }
+
+    void writeFloat(float val) { memcpy(&mData[mDataWritten++], &val, sizeof(val)); }
+
+    void write64(uint64_t val) {
+        uint32_t lo = static_cast<uint32_t>(val & 0xffffffff);
+        uint32_t hi = static_cast<uint32_t>(val >> 32);
+        write(lo);
+        write(hi);
+    }
+
+    void writeRect(const Rect& rect) {
+        writeSigned(rect.left);
+        writeSigned(rect.top);
+        writeSigned(rect.right);
+        writeSigned(rect.bottom);
+    }
+
+    void writeRegion(const std::vector<Rect>& region) {
+        for (const auto& rect : region) {
+            writeRect(rect);
+        }
+    }
+
+    void writeFRect(const FRect& rect) {
+        writeFloat(rect.left);
+        writeFloat(rect.top);
+        writeFloat(rect.right);
+        writeFloat(rect.bottom);
+    }
+
+    void writeColor(const Color& color) {
+        write((color.r << 0) | (color.g << 8) | (color.b << 16) | (color.a << 24));
+    }
+
+    void writeFloatColor(const FloatColor& color) {
+        writeFloat(color.r);
+        writeFloat(color.g);
+        writeFloat(color.b);
+        writeFloat(color.a);
+    }
+
+    void writeBlob(uint32_t length, const unsigned char* blob) {
+        memcpy(&mData[mDataWritten], blob, length);
+        uint32_t numElements = length / 4;
+        mDataWritten += numElements;
+        mDataWritten += (length - (numElements * 4) > 0) ? 1 : 0;
+    }
+
+    // ownership of handle is not transferred
+    void writeHandle(const native_handle_t* handle, bool useCache) {
+        if (!handle) {
+            writeSigned(
+                    static_cast<int32_t>((useCache) ? HandleIndex::CACHED : HandleIndex::EMPTY));
+            return;
+        }
+
+        mDataHandles.push_back(::android::dupToAidl(handle));
+        writeSigned(mDataHandles.size() - 1);
+    }
+
+    void writeHandle(const native_handle_t* handle) { writeHandle(handle, false); }
+
+    // ownership of fence is transferred
+    void writeFence(int fence) {
+        native_handle_t* handle = nullptr;
+        if (fence >= 0) {
+            handle = getTemporaryHandle(1, 0);
+            if (handle) {
+                handle->data[0] = fence;
+            } else {
+                ALOGW("failed to get temporary handle for fence %d", fence);
+                sync_wait(fence, -1);
+                close(fence);
+            }
+        }
+
+        writeHandle(handle);
+    }
+
+    native_handle_t* getTemporaryHandle(int numFds, int numInts) {
+        native_handle_t* handle = native_handle_create(numFds, numInts);
+        if (handle) {
+            mTemporaryHandles.push_back(handle);
+        }
+        return handle;
+    }
+
+    static constexpr uint16_t kMaxLength = std::numeric_limits<uint16_t>::max();
+
+    std::unique_ptr<int32_t[]> mData;
+    uint32_t mDataWritten;
+
+  private:
+    void growData(uint32_t grow) {
+        uint32_t newWritten = mDataWritten + grow;
+        if (newWritten < mDataWritten) {
+            LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32 ", growing by %" PRIu32,
+                             mDataWritten, grow);
+        }
+
+        if (newWritten <= mDataMaxSize) {
+            return;
+        }
+
+        uint32_t newMaxSize = mDataMaxSize << 1;
+        if (newMaxSize < newWritten) {
+            newMaxSize = newWritten;
+        }
+
+        auto newData = std::make_unique<int32_t[]>(newMaxSize);
+        std::copy_n(mData.get(), mDataWritten, newData.get());
+        mDataMaxSize = newMaxSize;
+        mData = std::move(newData);
+    }
+
+    uint32_t sizeToElements(uint32_t size) { return (size + 3) / 4; }
+
+    uint32_t mDataMaxSize;
+    // end offset of the current command
+    uint32_t mCommandEnd;
+
+    std::vector<NativeHandle> mDataHandles;
+    std::vector<native_handle_t*> mTemporaryHandles;
+
+    std::unique_ptr<CommandQueueType> mQueue;
+};
+
+// This class helps parse a command queue.  Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandReaderBase {
+  public:
+    CommandReaderBase() : mDataMaxSize(0) { reset(); }
+
+    bool setMQDescriptor(const DescriptorType& descriptor) {
+        mQueue = std::make_unique<CommandQueueType>(descriptor, false);
+        if (mQueue->isValid()) {
+            return true;
+        } else {
+            mQueue = nullptr;
+            return false;
+        }
+    }
+
+    bool readQueue(int32_t commandLength, std::vector<NativeHandle> commandHandles) {
+        if (!mQueue) {
+            return false;
+        }
+
+        auto quantumCount = mQueue->getQuantumCount();
+        if (mDataMaxSize < quantumCount) {
+            mDataMaxSize = quantumCount;
+            mData = std::make_unique<int32_t[]>(mDataMaxSize);
+        }
+
+        if (commandLength > mDataMaxSize || !mQueue->read(mData.get(), commandLength)) {
+            ALOGE("failed to read commands from message queue");
+            return false;
+        }
+
+        mDataSize = commandLength;
+        mDataRead = 0;
+        mCommandBegin = 0;
+        mCommandEnd = 0;
+        mDataHandles = std::move(commandHandles);
+        return true;
+    }
+
+    void reset() {
+        mDataSize = 0;
+        mDataRead = 0;
+        mCommandBegin = 0;
+        mCommandEnd = 0;
+        mDataHandles.clear();
+    }
+
+  protected:
+    template <typename T>
+    bool beginCommand(T* outCommand, uint16_t* outLength) {
+        return beginCommandBase(reinterpret_cast<Command*>(outCommand), outLength);
+    }
+
+    bool isEmpty() const { return (mDataRead >= mDataSize); }
+
+    bool beginCommandBase(Command* outCommand, uint16_t* outLength) {
+        if (mCommandEnd) {
+            LOG_FATAL("endCommand was not called for last command");
+        }
+
+        constexpr uint32_t opcode_mask = static_cast<uint32_t>(Command::OPCODE_MASK);
+        constexpr uint32_t length_mask = static_cast<uint32_t>(Command::LENGTH_MASK);
+
+        uint32_t val = read();
+        *outCommand = static_cast<Command>(val & opcode_mask);
+        *outLength = static_cast<uint16_t>(val & length_mask);
+
+        if (mDataRead + *outLength > mDataSize) {
+            ALOGE("command 0x%x has invalid command length %" PRIu16, *outCommand, *outLength);
+            // undo the read() above
+            mDataRead--;
+            return false;
+        }
+
+        mCommandEnd = mDataRead + *outLength;
+
+        return true;
+    }
+
+    void endCommand() {
+        if (!mCommandEnd) {
+            LOG_FATAL("beginCommand was not called");
+        } else if (mDataRead > mCommandEnd) {
+            LOG_FATAL("too much data read");
+            mDataRead = mCommandEnd;
+        } else if (mDataRead < mCommandEnd) {
+            LOG_FATAL("too little data read");
+            mDataRead = mCommandEnd;
+        }
+
+        mCommandBegin = mCommandEnd;
+        mCommandEnd = 0;
+    }
+
+    uint32_t getCommandLoc() const { return mCommandBegin; }
+
+    uint32_t read() { return mData[mDataRead++]; }
+
+    int32_t readSigned() {
+        int32_t val;
+        memcpy(&val, &mData[mDataRead++], sizeof(val));
+        return val;
+    }
+
+    float readFloat() {
+        float val;
+        memcpy(&val, &mData[mDataRead++], sizeof(val));
+        return val;
+    }
+
+    uint64_t read64() {
+        uint32_t lo = read();
+        uint32_t hi = read();
+        return (static_cast<uint64_t>(hi) << 32) | lo;
+    }
+
+    Color readColor() {
+        uint32_t val = read();
+        return Color{
+                static_cast<int8_t>((val >> 0) & 0xff),
+                static_cast<int8_t>((val >> 8) & 0xff),
+                static_cast<int8_t>((val >> 16) & 0xff),
+                static_cast<int8_t>((val >> 24) & 0xff),
+        };
+    }
+
+    // ownership of handle is not transferred
+    const native_handle_t* readHandle(bool* outUseCache) {
+        const native_handle_t* handle = nullptr;
+
+        int32_t index = readSigned();
+        switch (index) {
+            case static_cast<int32_t>(HandleIndex::EMPTY):
+                *outUseCache = false;
+                break;
+            case static_cast<int32_t>(HandleIndex::CACHED):
+                *outUseCache = true;
+                break;
+            default:
+                if (static_cast<size_t>(index) < mDataHandles.size()) {
+                    handle = ::android::makeFromAidl(mDataHandles[index]);
+                } else {
+                    ALOGE("invalid handle index %zu", static_cast<size_t>(index));
+                }
+                *outUseCache = false;
+                break;
+        }
+
+        return handle;
+    }
+
+    const native_handle_t* readHandle() {
+        bool useCache;
+        return readHandle(&useCache);
+    }
+
+    // ownership of fence is transferred
+    int readFence() {
+        auto handle = readHandle();
+        if (!handle || handle->numFds == 0) {
+            return -1;
+        }
+
+        if (handle->numFds != 1) {
+            ALOGE("invalid fence handle with %d fds", handle->numFds);
+            return -1;
+        }
+
+        int fd = dup(handle->data[0]);
+        if (fd < 0) {
+            ALOGW("failed to dup fence %d", handle->data[0]);
+            sync_wait(handle->data[0], -1);
+            fd = -1;
+        }
+
+        return fd;
+    }
+
+    std::unique_ptr<int32_t[]> mData;
+    uint32_t mDataRead;
+
+  private:
+    std::unique_ptr<CommandQueueType> mQueue;
+    uint32_t mDataMaxSize;
+
+    uint32_t mDataSize;
+
+    // begin/end offsets of the current command
+    uint32_t mCommandBegin;
+    uint32_t mCommandEnd;
+
+    std::vector<NativeHandle> mDataHandles;
+};
+
+}  // namespace aidl::android::hardware::graphics::composer3
diff --git a/neuralnetworks/1.0/utils/Android.bp b/neuralnetworks/1.0/utils/Android.bp
index 8c51c67..71a190e 100644
--- a/neuralnetworks/1.0/utils/Android.bp
+++ b/neuralnetworks/1.0/utils/Android.bp
@@ -49,7 +49,7 @@
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
         "libgmock",
-        "libneuralnetworks_common",
+        "libneuralnetworks_common_hidl",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index b33c581..ae9ff0a 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -50,7 +50,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common_hidl",
     ],
     header_libs: [
         "libneuralnetworks_headers",
@@ -81,7 +81,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common_hidl",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.1/utils/Android.bp b/neuralnetworks/1.1/utils/Android.bp
index 737ff58..478a742 100644
--- a/neuralnetworks/1.1/utils/Android.bp
+++ b/neuralnetworks/1.1/utils/Android.bp
@@ -52,7 +52,7 @@
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "libgmock",
-        "libneuralnetworks_common",
+        "libneuralnetworks_common_hidl",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index c001112..4c57788 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -48,7 +48,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common_hidl",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.2/utils/Android.bp b/neuralnetworks/1.2/utils/Android.bp
index 4eefb0f..2a86a00 100644
--- a/neuralnetworks/1.2/utils/Android.bp
+++ b/neuralnetworks/1.2/utils/Android.bp
@@ -71,7 +71,7 @@
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
         "libgmock",
-        "libneuralnetworks_common",
+        "libneuralnetworks_common_hidl",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index e313b47..15a5d2f 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -71,7 +71,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common_hidl",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/1.3/utils/Android.bp b/neuralnetworks/1.3/utils/Android.bp
index 7acb4fc..8ae509f 100644
--- a/neuralnetworks/1.3/utils/Android.bp
+++ b/neuralnetworks/1.3/utils/Android.bp
@@ -69,7 +69,7 @@
         "android.hardware.neuralnetworks@1.2",
         "android.hardware.neuralnetworks@1.3",
         "libgmock",
-        "libneuralnetworks_common",
+        "libneuralnetworks_common_hidl",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
         "neuralnetworks_utils_hal_1_0",
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index ab0a018..ca59cc2 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -66,7 +66,6 @@
         "VtsHalNeuralNetworksV1_0_utils",
         "VtsHalNeuralNetworksV1_2_utils",
         "VtsHalNeuralNetworksV1_3_utils",
-        "android.hardware.neuralnetworks-V2-ndk",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
@@ -76,7 +75,7 @@
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
+        "libneuralnetworks_common_hidl",
         "libsync",
     ],
     whole_static_libs: [
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 63cf45d..2c2419b 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -23,8 +23,8 @@
     default_applicable_licenses: ["hardware_interfaces_license"],
 }
 
-cc_library_static {
-    name: "neuralnetworks_utils_hal_aidl",
+cc_defaults {
+    name: "neuralnetworks_utils_hal_aidl_defaults",
     defaults: ["neuralnetworks_utils_defaults"],
     srcs: ["src/*"],
     local_include_dirs: ["include/nnapi/hal/aidl/"],
@@ -38,7 +38,6 @@
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk",
         "libbinder_ndk",
         "libhidlbase",
     ],
@@ -49,21 +48,49 @@
     },
 }
 
-cc_test {
-    name: "neuralnetworks_utils_hal_aidl_test",
-    defaults: ["neuralnetworks_utils_defaults"],
-    srcs: [
-        "test/*.cpp",
+cc_library_static {
+    name: "neuralnetworks_utils_hal_aidl_v1",
+    defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
+    shared_libs: [
+        "android.hardware.neuralnetworks-V1-ndk",
     ],
+}
+
+cc_library_static {
+    name: "neuralnetworks_utils_hal_aidl_v2",
+    defaults: ["neuralnetworks_utils_hal_aidl_defaults"],
+    shared_libs: [
+        "android.hardware.neuralnetworks-V2-ndk",
+    ],
+}
+
+// A cc_defaults that includes the latest non-experimental AIDL utilities and other AIDL libraries
+// that are commonly used together. Modules that always depend on the latest non-experimental
+// AIDL features can include this cc_defaults to avoid managing dependency versions explicitly.
+cc_defaults {
+    name: "neuralnetworks_use_latest_utils_hal_aidl",
     static_libs: [
         "android.hardware.common-V2-ndk",
         "android.hardware.graphics.common-V3-ndk",
         "android.hardware.neuralnetworks-V2-ndk",
+        "neuralnetworks_utils_hal_aidl_v2",
+    ],
+}
+
+cc_test {
+    name: "neuralnetworks_utils_hal_aidl_test",
+    defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
+        "neuralnetworks_utils_defaults",
+    ],
+    srcs: [
+        "test/*.cpp",
+    ],
+    static_libs: [
         "libaidlcommonsupport",
         "libgmock",
         "libneuralnetworks_common",
         "neuralnetworks_types",
-        "neuralnetworks_utils_hal_aidl",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
index 1457646..d558f66 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Device.h
@@ -43,11 +43,12 @@
 
   public:
     static nn::GeneralResult<std::shared_ptr<const Device>> create(
-            std::string name, std::shared_ptr<aidl_hal::IDevice> device);
+            std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel);
 
     Device(PrivateConstructorTag tag, std::string name, std::string versionString,
-           nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
-           nn::Capabilities capabilities, std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
+           nn::Version featureLevel, nn::DeviceType deviceType,
+           std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
+           std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
            std::shared_ptr<aidl_hal::IDevice> device, DeathHandler deathHandler);
 
     const std::string& getName() const override;
@@ -84,6 +85,7 @@
   private:
     const std::string kName;
     const std::string kVersionString;
+    const nn::Version kFeatureLevel;
     const nn::DeviceType kDeviceType;
     const std::vector<nn::Extension> kExtensions;
     const nn::Capabilities kCapabilities;
diff --git a/neuralnetworks/aidl/utils/src/Device.cpp b/neuralnetworks/aidl/utils/src/Device.cpp
index e80de0b..5b7ec4e 100644
--- a/neuralnetworks/aidl/utils/src/Device.cpp
+++ b/neuralnetworks/aidl/utils/src/Device.cpp
@@ -125,7 +125,7 @@
 }  // namespace
 
 nn::GeneralResult<std::shared_ptr<const Device>> Device::create(
-        std::string name, std::shared_ptr<aidl_hal::IDevice> device) {
+        std::string name, std::shared_ptr<aidl_hal::IDevice> device, nn::Version featureLevel) {
     if (name.empty()) {
         return NN_ERROR(nn::ErrorStatus::INVALID_ARGUMENT)
                << "aidl_hal::utils::Device::create must have non-empty name";
@@ -143,18 +143,19 @@
 
     auto deathHandler = NN_TRY(DeathHandler::create(device));
     return std::make_shared<const Device>(
-            PrivateConstructorTag{}, std::move(name), std::move(versionString), deviceType,
-            std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
+            PrivateConstructorTag{}, std::move(name), std::move(versionString), featureLevel,
+            deviceType, std::move(extensions), std::move(capabilities), numberOfCacheFilesNeeded,
             std::move(device), std::move(deathHandler));
 }
 
 Device::Device(PrivateConstructorTag /*tag*/, std::string name, std::string versionString,
-               nn::DeviceType deviceType, std::vector<nn::Extension> extensions,
-               nn::Capabilities capabilities,
+               nn::Version featureLevel, nn::DeviceType deviceType,
+               std::vector<nn::Extension> extensions, nn::Capabilities capabilities,
                std::pair<uint32_t, uint32_t> numberOfCacheFilesNeeded,
                std::shared_ptr<aidl_hal::IDevice> device, DeathHandler deathHandler)
     : kName(std::move(name)),
       kVersionString(std::move(versionString)),
+      kFeatureLevel(featureLevel),
       kDeviceType(deviceType),
       kExtensions(std::move(extensions)),
       kCapabilities(std::move(capabilities)),
@@ -171,7 +172,7 @@
 }
 
 nn::Version Device::getFeatureLevel() const {
-    return nn::Version::ANDROID_S;
+    return kFeatureLevel;
 }
 
 nn::DeviceType Device::getType() const {
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index ac182a2..01772ee 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -17,6 +17,7 @@
 #include "Service.h"
 
 #include <AndroidVersionUtil.h>
+#include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
@@ -28,8 +29,33 @@
 #include <string>
 
 #include "Device.h"
+#include "Utils.h"
 
 namespace aidl::android::hardware::neuralnetworks::utils {
+namespace {
+
+// Map the AIDL version of an IDevice to NNAPI canonical feature level.
+nn::GeneralResult<nn::Version> getAidlServiceFeatureLevel(IDevice* service) {
+    CHECK(service != nullptr);
+    int aidlVersion;
+    const auto ret = service->getInterfaceVersion(&aidlVersion);
+    HANDLE_ASTATUS(ret) << "getInterfaceVersion failed";
+
+    // For service AIDL versions greater than or equal to the AIDL library version that the runtime
+    // was built against, clamp it to the runtime AIDL library version.
+    aidlVersion = std::min(aidlVersion, IDevice::version);
+
+    // Map stable AIDL versions to canonical versions.
+    switch (aidlVersion) {
+        case 1:
+            return nn::Version::ANDROID_S;
+        case 2:
+            return nn::Version::FEATURE_LEVEL_6;
+    }
+    return NN_ERROR() << "Unknown AIDL service version: " << aidlVersion;
+}
+
+}  // namespace
 
 nn::GeneralResult<nn::SharedDevice> getDevice(const std::string& instanceName) {
     auto fullName = std::string(IDevice::descriptor) + "/" + instanceName;
@@ -55,7 +81,8 @@
                    << " returned nullptr";
         }
         ABinderProcess_startThreadPool();
-        return Device::create(instanceName, std::move(service));
+        const auto featureLevel = NN_TRY(getAidlServiceFeatureLevel(service.get()));
+        return Device::create(instanceName, std::move(service), featureLevel);
     };
 
     return hal::utils::ResilientDevice::create(std::move(makeDevice));
diff --git a/neuralnetworks/aidl/utils/test/DeviceTest.cpp b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
index f121aca..79abe1b 100644
--- a/neuralnetworks/aidl/utils/test/DeviceTest.cpp
+++ b/neuralnetworks/aidl/utils/test/DeviceTest.cpp
@@ -146,28 +146,45 @@
     return ndk::ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
 };
 
+class DeviceTest : public ::testing::TestWithParam<nn::Version> {
+  protected:
+    const nn::Version kVersion = GetParam();
+};
+
+std::string printDeviceTest(const testing::TestParamInfo<nn::Version>& info) {
+    switch (info.param) {
+        case nn::Version::ANDROID_S:
+            return "v1";
+        case nn::Version::FEATURE_LEVEL_6:
+            return "v2";
+        default:
+            LOG(FATAL) << "Invalid AIDL version: " << info.param;
+            return "invalid";
+    }
+}
+
 }  // namespace
 
-TEST(DeviceTest, invalidName) {
+TEST_P(DeviceTest, invalidName) {
     // run test
     const auto device = MockDevice::create();
-    const auto result = Device::create(kInvalidName, device);
+    const auto result = Device::create(kInvalidName, device, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
 }
 
-TEST(DeviceTest, invalidDevice) {
+TEST_P(DeviceTest, invalidDevice) {
     // run test
-    const auto result = Device::create(kName, kInvalidDevice);
+    const auto result = Device::create(kName, kInvalidDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::INVALID_ARGUMENT);
 }
 
-TEST(DeviceTest, getVersionStringError) {
+TEST_P(DeviceTest, getVersionStringError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -175,14 +192,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getVersionStringTransportFailure) {
+TEST_P(DeviceTest, getVersionStringTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -190,14 +207,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getVersionStringDeadObject) {
+TEST_P(DeviceTest, getVersionStringDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_))
@@ -205,27 +222,27 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getTypeError) {
+TEST_P(DeviceTest, getTypeError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getType(_)).Times(1).WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getTypeTransportFailure) {
+TEST_P(DeviceTest, getTypeTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getType(_))
@@ -233,14 +250,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getTypeDeadObject) {
+TEST_P(DeviceTest, getTypeDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getType(_))
@@ -248,14 +265,14 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getSupportedExtensionsError) {
+TEST_P(DeviceTest, getSupportedExtensionsError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -263,14 +280,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedExtensionsTransportFailure) {
+TEST_P(DeviceTest, getSupportedExtensionsTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -278,14 +295,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedExtensionsDeadObject) {
+TEST_P(DeviceTest, getSupportedExtensionsDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getSupportedExtensions(_))
@@ -293,20 +310,20 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeeded) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeeded) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_TRUE(result.has_value());
@@ -315,7 +332,7 @@
     EXPECT_EQ(result.value()->getNumberOfCacheFilesNeeded(), kNumberOfCacheFilesPair);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeededError) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeededError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -323,14 +340,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, dataCacheFilesExceedsSpecifiedMax) {
+TEST_P(DeviceTest, dataCacheFilesExceedsSpecifiedMax) {
     // setup test
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -341,14 +358,14 @@
                             InvokeWithoutArgs(makeStatusOk)));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, modelCacheFilesExceedsSpecifiedMax) {
+TEST_P(DeviceTest, modelCacheFilesExceedsSpecifiedMax) {
     // setup test
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -359,14 +376,14 @@
                             InvokeWithoutArgs(makeStatusOk)));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeededTransportFailure) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeededTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -374,14 +391,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getNumberOfCacheFilesNeededDeadObject) {
+TEST_P(DeviceTest, getNumberOfCacheFilesNeededDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_))
@@ -389,14 +406,14 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getCapabilitiesError) {
+TEST_P(DeviceTest, getCapabilitiesError) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -404,14 +421,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getCapabilitiesTransportFailure) {
+TEST_P(DeviceTest, getCapabilitiesTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -419,14 +436,14 @@
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getCapabilitiesDeadObject) {
+TEST_P(DeviceTest, getCapabilitiesDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getCapabilities(_))
@@ -434,17 +451,17 @@
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
 
     // run test
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
 
     // verify result
     ASSERT_FALSE(result.has_value());
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, getName) {
+TEST_P(DeviceTest, getName) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
 
     // run test
     const auto& name = device->getName();
@@ -453,19 +470,19 @@
     EXPECT_EQ(name, kName);
 }
 
-TEST(DeviceTest, getFeatureLevel) {
+TEST_P(DeviceTest, getFeatureLevel) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
 
     // run test
     const auto featureLevel = device->getFeatureLevel();
 
     // verify result
-    EXPECT_EQ(featureLevel, nn::Version::ANDROID_S);
+    EXPECT_EQ(featureLevel, kVersion);
 }
 
-TEST(DeviceTest, getCachedData) {
+TEST_P(DeviceTest, getCachedData) {
     // setup call
     const auto mockDevice = createMockDevice();
     EXPECT_CALL(*mockDevice, getVersionString(_)).Times(1);
@@ -474,7 +491,7 @@
     EXPECT_CALL(*mockDevice, getNumberOfCacheFilesNeeded(_)).Times(1);
     EXPECT_CALL(*mockDevice, getCapabilities(_)).Times(1);
 
-    const auto result = Device::create(kName, mockDevice);
+    const auto result = Device::create(kName, mockDevice, kVersion);
     ASSERT_TRUE(result.has_value())
             << "Failed with " << result.error().code << ": " << result.error().message;
     const auto& device = result.value();
@@ -487,10 +504,10 @@
     EXPECT_EQ(device->getCapabilities(), device->getCapabilities());
 }
 
-TEST(DeviceTest, getSupportedOperations) {
+TEST_P(DeviceTest, getSupportedOperations) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(DoAll(
@@ -508,10 +525,10 @@
     EXPECT_THAT(supportedOperations, Each(testing::IsTrue()));
 }
 
-TEST(DeviceTest, getSupportedOperationsError) {
+TEST_P(DeviceTest, getSupportedOperationsError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
@@ -524,10 +541,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedOperationsTransportFailure) {
+TEST_P(DeviceTest, getSupportedOperationsTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -540,10 +557,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, getSupportedOperationsDeadObject) {
+TEST_P(DeviceTest, getSupportedOperationsDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, getSupportedOperations(_, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -556,10 +573,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModel) {
+TEST_P(DeviceTest, prepareModel) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
@@ -576,10 +593,10 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(DeviceTest, prepareModelLaunchError) {
+TEST_P(DeviceTest, prepareModelLaunchError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelReturn(ErrorStatus::GENERAL_FAILURE,
@@ -594,10 +611,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelReturnError) {
+TEST_P(DeviceTest, prepareModelReturnError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelReturn(ErrorStatus::NONE,
@@ -612,10 +629,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelNullptrError) {
+TEST_P(DeviceTest, prepareModelNullptrError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(
@@ -630,10 +647,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelTransportFailure) {
+TEST_P(DeviceTest, prepareModelTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -647,10 +664,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelDeadObject) {
+TEST_P(DeviceTest, prepareModelDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModel(_, _, _, _, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -664,10 +681,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModelAsyncCrash) {
+TEST_P(DeviceTest, prepareModelAsyncCrash) {
     // setup test
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto ret = [&device]() {
         DeathMonitor::serviceDied(device->getDeathMonitor());
         return ndk::ScopedAStatus::ok();
@@ -685,10 +702,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModelFromCache) {
+TEST_P(DeviceTest, prepareModelFromCache) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto mockPreparedModel = MockPreparedModel::create();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
@@ -704,10 +721,10 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(DeviceTest, prepareModelFromCacheLaunchError) {
+TEST_P(DeviceTest, prepareModelFromCacheLaunchError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelFromCacheReturn(
@@ -721,10 +738,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheReturnError) {
+TEST_P(DeviceTest, prepareModelFromCacheReturnError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelFromCacheReturn(
@@ -738,10 +755,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheNullptrError) {
+TEST_P(DeviceTest, prepareModelFromCacheNullptrError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(Invoke(makePreparedModelFromCacheReturn(ErrorStatus::NONE, ErrorStatus::NONE,
@@ -755,10 +772,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheTransportFailure) {
+TEST_P(DeviceTest, prepareModelFromCacheTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -771,10 +788,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, prepareModelFromCacheDeadObject) {
+TEST_P(DeviceTest, prepareModelFromCacheDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, prepareModelFromCache(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -787,10 +804,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, prepareModelFromCacheAsyncCrash) {
+TEST_P(DeviceTest, prepareModelFromCacheAsyncCrash) {
     // setup test
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto ret = [&device]() {
         DeathMonitor::serviceDied(device->getDeathMonitor());
         return ndk::ScopedAStatus::ok();
@@ -807,10 +824,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
-TEST(DeviceTest, allocate) {
+TEST_P(DeviceTest, allocate) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     const auto mockBuffer = DeviceBuffer{.buffer = MockBuffer::create(), .token = 1};
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
@@ -825,10 +842,10 @@
     EXPECT_NE(result.value(), nullptr);
 }
 
-TEST(DeviceTest, allocateError) {
+TEST_P(DeviceTest, allocateError) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralFailure));
@@ -841,10 +858,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, allocateTransportFailure) {
+TEST_P(DeviceTest, allocateTransportFailure) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeGeneralTransportFailure));
@@ -857,10 +874,10 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::GENERAL_FAILURE);
 }
 
-TEST(DeviceTest, allocateDeadObject) {
+TEST_P(DeviceTest, allocateDeadObject) {
     // setup call
     const auto mockDevice = createMockDevice();
-    const auto device = Device::create(kName, mockDevice).value();
+    const auto device = Device::create(kName, mockDevice, kVersion).value();
     EXPECT_CALL(*mockDevice, allocate(_, _, _, _, _))
             .Times(1)
             .WillOnce(InvokeWithoutArgs(makeDeadObjectFailure));
@@ -873,4 +890,8 @@
     EXPECT_EQ(result.error().code, nn::ErrorStatus::DEAD_OBJECT);
 }
 
+INSTANTIATE_TEST_SUITE_P(TestDevice, DeviceTest,
+                         ::testing::Values(nn::Version::ANDROID_S, nn::Version::FEATURE_LEVEL_6),
+                         printDeviceTest);
+
 }  // namespace aidl::android::hardware::neuralnetworks::utils
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index f3404a9..8fd8f4f 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -26,6 +26,7 @@
 cc_test {
     name: "VtsHalNeuralnetworksTargetTest",
     defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
         "neuralnetworks_vts_functional_defaults",
         "use_libaidlvintf_gtest_helper_static",
     ],
@@ -51,16 +52,14 @@
     static_libs: [
         "android.hardware.common-V2-ndk",
         "android.hardware.graphics.common-V3-ndk",
-        "android.hardware.neuralnetworks-V2-ndk",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libaidlcommonsupport",
         "libgmock",
         "libhidlmemory",
+        "libneuralnetworks_common",
         "libneuralnetworks_generated_test_harness",
-        "libneuralnetworks_utils",
         "libsync",
-        "neuralnetworks_utils_hal_aidl",
     ],
     whole_static_libs: [
         "neuralnetworks_generated_V1_0_example",
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index f88e407..c0645b0 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -35,7 +35,6 @@
         "neuralnetworks_types",
     ],
     shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk",
         "libhidlbase",
         "libbinder_ndk",
     ],
@@ -53,7 +52,7 @@
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
         "libgmock",
-        "libneuralnetworks_common",
+        "libneuralnetworks_common_hidl",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
     ],
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index fbb8679..3288d05 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -25,7 +25,10 @@
 
 cc_library_static {
     name: "neuralnetworks_utils_hal_service",
-    defaults: ["neuralnetworks_utils_defaults"],
+    defaults: [
+        "neuralnetworks_use_latest_utils_hal_aidl",
+        "neuralnetworks_utils_defaults",
+    ],
     srcs: ["src/*"],
     local_include_dirs: ["include/nnapi/hal"],
     export_include_dirs: ["include"],
@@ -35,11 +38,9 @@
         "neuralnetworks_utils_hal_1_1",
         "neuralnetworks_utils_hal_1_2",
         "neuralnetworks_utils_hal_1_3",
-        "neuralnetworks_utils_hal_aidl",
         "neuralnetworks_utils_hal_common",
     ],
     shared_libs: [
-        "android.hardware.neuralnetworks-V2-ndk",
         "android.hardware.neuralnetworks@1.0",
         "android.hardware.neuralnetworks@1.1",
         "android.hardware.neuralnetworks@1.2",
diff --git a/power/1.0/vts/functional/OWNERS b/power/1.0/vts/OWNERS
similarity index 100%
copy from power/1.0/vts/functional/OWNERS
copy to power/1.0/vts/OWNERS
diff --git a/power/1.1/vts/OWNERS b/power/1.1/vts/OWNERS
new file mode 100644
index 0000000..3a64da7
--- /dev/null
+++ b/power/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+wvw@google.com
diff --git a/power/1.0/vts/functional/OWNERS b/power/1.1/vts/functional/OWNERS
similarity index 100%
rename from power/1.0/vts/functional/OWNERS
rename to power/1.1/vts/functional/OWNERS
diff --git a/power/1.2/vts/OWNERS b/power/1.2/vts/OWNERS
new file mode 100644
index 0000000..4d8c7e9
--- /dev/null
+++ b/power/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+include ../../1.1/vts/OWNERS
diff --git a/power/1.3/vts/OWNERS b/power/1.3/vts/OWNERS
new file mode 100644
index 0000000..4d8c7e9
--- /dev/null
+++ b/power/1.3/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 158088
+include ../../1.1/vts/OWNERS