Improve getAsync test.

Test: atest android.car.cts.CarPropertyManagerTest
Bug: 257143378
Change-Id: I8839079ddefb34be5516695647e8c4ff32b02b85
diff --git a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
index 9fa54dc2..355641e9 100644
--- a/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
+++ b/tests/tests/car/src/android/car/cts/CarPropertyManagerTest.java
@@ -17,6 +17,7 @@
 package android.car.cts;
 
 import static android.car.cts.utils.ShellPermissionUtils.runWithShellPermissionIdentity;
+import static android.car.hardware.property.CarPropertyManager.GetPropertyResult;
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth.assertWithMessage;
@@ -77,6 +78,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
@@ -4524,41 +4526,90 @@
     @ApiTest(apis = {"android.car.hardware.property.CarPropertyManager#getPropertiesAsync(List, "
             + "CancellationSignal, Executor, GetPropertyCallback)"})
     public void testGetAllSupportedReadablePropertiesAsync() throws Exception {
-        runWithShellPermissionIdentity(
-                () -> {
-                    Executor executor = Executors.newFixedThreadPool(1);
-                    Set<Integer> pendingRequests = new ArraySet<>();
-                    List<CarPropertyManager.GetPropertyRequest> getPropertyRequests =
-                            new ArrayList<>();
-                    List<CarPropertyConfig> configs = mCarPropertyManager.getPropertyList();
-                    for (CarPropertyConfig cfg : configs) {
-                        if (cfg.getAccess() != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ
-                                && cfg.getAccess()
-                                        != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
-                            continue;
-                        }
-                        int[] areaIds = cfg.getAreaIds();
-                        int propId = cfg.getPropertyId();
-                        for (int areaId : areaIds) {
-                            CarPropertyManager.GetPropertyRequest gpr =
-                                    mCarPropertyManager.generateGetPropertyRequest(propId, areaId);
-                            getPropertyRequests.add(gpr);
-                            pendingRequests.add(gpr.getRequestId());
-                        }
-                    }
+        runWithShellPermissionIdentity(() -> {
+            Executor executor = Executors.newFixedThreadPool(1);
+            Set<Integer> pendingRequests = new ArraySet<>();
+            List<CarPropertyManager.GetPropertyRequest> getPropertyRequests =
+                    new ArrayList<>();
+            Set<PropIdAreaId> requestPropIdAreaIds = new ArraySet<>();
+            List<CarPropertyConfig> configs = mCarPropertyManager.getPropertyList();
+            for (CarPropertyConfig cfg : configs) {
+                if (cfg.getAccess() != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ
+                        && cfg.getAccess()
+                                != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) {
+                    continue;
+                }
+                int[] areaIds = cfg.getAreaIds();
+                int propId = cfg.getPropertyId();
+                for (int areaId : areaIds) {
+                    CarPropertyManager.GetPropertyRequest gpr =
+                            mCarPropertyManager.generateGetPropertyRequest(propId, areaId);
+                    getPropertyRequests.add(gpr);
+                    pendingRequests.add(gpr.getRequestId());
+                    requestPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
+                }
+            }
 
-                    TestGetPropertyAsyncCallback testGetPropertyAsyncCallback =
-                            new TestGetPropertyAsyncCallback(pendingRequests);
-                    mCarPropertyManager.getPropertiesAsync(
-                            getPropertyRequests,
-                            /* cancellationSignal= */ null,
-                            executor,
-                            testGetPropertyAsyncCallback);
-                    testGetPropertyAsyncCallback.waitAndFinish();
-                    assertWithMessage(testGetPropertyAsyncCallback.getResultList().toString())
-                            .that(testGetPropertyAsyncCallback.getErrorList().isEmpty())
-                            .isTrue();
-                });
+            int expectedResultCount = pendingRequests.size();
+
+            TestGetPropertyAsyncCallback testGetPropertyAsyncCallback =
+                    new TestGetPropertyAsyncCallback(pendingRequests);
+            mCarPropertyManager.getPropertiesAsync(
+                    getPropertyRequests,
+                    /* cancellationSignal= */ null,
+                    executor,
+                    testGetPropertyAsyncCallback);
+            testGetPropertyAsyncCallback.waitAndFinish();
+
+            assertThat(testGetPropertyAsyncCallback.getErrorList()).isEmpty();
+            int resultCount = testGetPropertyAsyncCallback.getResultList().size();
+            assertWithMessage("must receive at least " + expectedResultCount + " results, got "
+                    + resultCount).that(resultCount).isEqualTo(expectedResultCount);
+
+            for (PropIdAreaId receivedPropIdAreaId :
+                    testGetPropertyAsyncCallback.getReceivedPropIdAreaIds()) {
+                assertWithMessage("received unexpected result for " + receivedPropIdAreaId)
+                        .that(requestPropIdAreaIds).contains(receivedPropIdAreaId);
+            }
+        });
+    }
+
+    private static final class PropIdAreaId {
+        private final int mPropId;
+        private final int mAreaId;
+
+        PropIdAreaId(int propId, int areaId) {
+            mPropId = propId;
+            mAreaId = areaId;
+        }
+
+        PropIdAreaId(PropIdAreaId other) {
+            mPropId = other.mPropId;
+            mAreaId = other.mAreaId;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mAreaId, mPropId);
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (this == other) {
+                return true;
+            }
+            if (other.getClass() != this.getClass()) {
+                return false;
+            }
+
+            PropIdAreaId o = (PropIdAreaId) other;
+            return mPropId == o.mPropId && mAreaId == o.mAreaId;
+        }
+
+        @Override
+        public String toString() {
+            return "{propId: " + mPropId + ", areaId: " + mAreaId + "}";
+        }
     }
 
     private static final class TestGetPropertyAsyncCallback implements
@@ -4571,6 +4622,8 @@
         private final List<String> mErrorList = new ArrayList<>();
         @GuardedBy("mLock")
         private final List<String> mResultList = new ArrayList<>();
+        @GuardedBy("mLock")
+        private final List<PropIdAreaId> mReceivedPropIdAreaIds = new ArrayList();
 
         TestGetPropertyAsyncCallback(Set<Integer> pendingRequests) {
             mNumberOfRequests = pendingRequests.size();
@@ -4578,16 +4631,30 @@
             mPendingRequests = pendingRequests;
         }
 
+        private static String toMsg(int requestId, int propId, int areaId) {
+            return "Request ID: " + requestId + " (propId: " + propId + ", areaId: " + areaId + ")";
+        }
+
         @Override
-        public void onSuccess(@NonNull CarPropertyManager.GetPropertyResult getPropertyResult) {
-            int requestId = getPropertyResult.getRequestId();
+        public void onSuccess(@NonNull GetPropertyResult<?> gotPropertyResult) {
+            int requestId = gotPropertyResult.getRequestId();
+            int propId = gotPropertyResult.getPropertyId();
+            int areaId = gotPropertyResult.getAreaId();
             synchronized (mLock) {
                 if (!mPendingRequests.contains(requestId)) {
-                    mErrorList.add("Request ID: " + requestId + " not present");
+                    mErrorList.add(toMsg(requestId, propId, areaId) + " not present");
                     return;
                 } else {
                     mPendingRequests.remove(requestId);
-                    mResultList.add("Request ID: " + requestId + " complete with onSuccess()");
+                    mResultList.add(toMsg(requestId, propId, areaId)
+                            + " complete with onSuccess()");
+                }
+
+                if (gotPropertyResult.getValue() == null) {
+                    mErrorList.add("The property value for " + toMsg(requestId, propId, areaId)
+                            + " is null");
+                } else {
+                    mReceivedPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
                 }
             }
             mCountDownLatch.countDown();
@@ -4596,13 +4663,17 @@
         @Override
         public void onFailure(@NonNull CarPropertyManager.GetPropertyError getPropertyError) {
             int requestId = getPropertyError.getRequestId();
+            int propId = getPropertyError.getPropertyId();
+            int areaId = getPropertyError.getAreaId();
             synchronized (mLock) {
                 if (!mPendingRequests.contains(requestId)) {
-                    mErrorList.add("Request ID: " + requestId + " not present");
+                    mErrorList.add(toMsg(requestId, propId, areaId) + " not present");
                     return;
                 } else {
-                    mResultList.add("Request ID: " + requestId + " complete with onFailure()");
+                    mResultList.add(toMsg(requestId, propId, areaId)
+                            + " complete with onFailure()");
                     mPendingRequests.remove(requestId);
+                    mReceivedPropIdAreaIds.add(new PropIdAreaId(propId, areaId));
                 }
             }
             mCountDownLatch.countDown();
@@ -4612,10 +4683,12 @@
             boolean res = mCountDownLatch.await(ASYNC_WAIT_TIMEOUT_IN_SEC, TimeUnit.SECONDS);
             synchronized (mLock) {
                 if (!res) {
+                    int gotRequestsCount = mNumberOfRequests - mPendingRequests.size();
                     mErrorList.add(
                             "Not enough responses received for getPropertiesAsync before timeout "
-                                    + "(10s), expected " + mNumberOfRequests + " responses, got "
-                                    + mPendingRequests.size());
+                                    + "(" + ASYNC_WAIT_TIMEOUT_IN_SEC + "s), expected "
+                                    + mNumberOfRequests + " responses, got "
+                                    + gotRequestsCount);
                 }
             }
         }
@@ -4635,6 +4708,14 @@
             }
             return resultList;
         }
+
+        public List<PropIdAreaId> getReceivedPropIdAreaIds() {
+            List<PropIdAreaId> receivedPropIdAreaIds;
+            synchronized (mLock) {
+                receivedPropIdAreaIds = new ArrayList<>(mReceivedPropIdAreaIds);
+            }
+            return receivedPropIdAreaIds;
+        }
     }
 
     @Test