Merge "Add additional data elements into scan results" into tm-mainline-prod
diff --git a/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java b/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java
index 9b1bdb5..5a76d96 100644
--- a/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java
+++ b/nearby/service/java/com/android/server/nearby/presence/PresenceDiscoveryResult.java
@@ -138,6 +138,12 @@
         return false;
     }
 
+    @VisibleForTesting
+    /** Gets presence {@link DataElement}s of the discovery result. */
+    public List<DataElement> getExtendedProperties() {
+        return mExtendedProperties;
+    }
+
     private boolean identityMatches(List<PublicCredential> publicCredentials) {
         if (mEncryptedIdentityTag.length == 0) {
             return true;
diff --git a/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java b/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java
index ab6904f..44a3a23 100644
--- a/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java
+++ b/nearby/service/java/com/android/server/nearby/provider/ChreDiscoveryProvider.java
@@ -20,6 +20,10 @@
 
 import static com.android.server.nearby.NearbyService.TAG;
 
+import static service.proto.Blefilter.DataElement.ElementType.DE_BATTERY_STATUS;
+import static service.proto.Blefilter.DataElement.ElementType.DE_CONNECTION_STATUS;
+import static service.proto.Blefilter.DataElement.ElementType.DE_FAST_PAIR_ACCOUNT_KEY;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -250,15 +254,10 @@
                                                 encryptedMetaData)
                                         .setRssi(filterResult.getRssi())
                                         .addMedium(NearbyDevice.Medium.BLE);
-                        // Fast Pair account keys added to Data Elements.
+                        // Data Elements reported from nanoapp added to Data Elements.
+                        // i.e. Fast Pair account keys, connection status and battery
                         for (Blefilter.DataElement element : filterResult.getDataElementList()) {
-                            if (element.getKey()
-                                    == Blefilter.DataElement.ElementType.DE_FAST_PAIR_ACCOUNT_KEY) {
-                                presenceDeviceBuilder.addExtendedProperty(
-                                        new DataElement(
-                                                DataElement.DataType.ACCOUNT_KEY_DATA,
-                                                element.getValue().toByteArray()));
-                            }
+                            addDataElementsToPresenceDevice(element, presenceDeviceBuilder);
                         }
                         // BlE address appended to Data Element.
                         if (filterResult.hasBluetoothAddress()) {
@@ -274,7 +273,6 @@
                                             DataElement.DataType.BLE_SERVICE_DATA,
                                             filterResult.getBleServiceData().toByteArray()));
                         }
-
                         // Add action
                         if (filterResult.hasIntent()) {
                             presenceDeviceBuilder.addExtendedProperty(
@@ -310,5 +308,30 @@
                 }
             }
         }
+
+        private void addDataElementsToPresenceDevice(Blefilter.DataElement element,
+                PresenceDevice.Builder presenceDeviceBuilder) {
+            int endIndex = element.hasValueLength() ? element.getValueLength() :
+                    element.getValue().size();
+            switch (element.getKey()) {
+                case DE_FAST_PAIR_ACCOUNT_KEY:
+                    presenceDeviceBuilder.addExtendedProperty(
+                            new DataElement(DataElement.DataType.ACCOUNT_KEY_DATA,
+                                    element.getValue().substring(0, endIndex).toByteArray()));
+                    break;
+                case DE_CONNECTION_STATUS:
+                    presenceDeviceBuilder.addExtendedProperty(
+                            new DataElement(DataElement.DataType.CONNECTION_STATUS,
+                                    element.getValue().substring(0, endIndex).toByteArray()));
+                    break;
+                case DE_BATTERY_STATUS:
+                    presenceDeviceBuilder.addExtendedProperty(
+                            new DataElement(DataElement.DataType.BATTERY,
+                                    element.getValue().substring(0, endIndex).toByteArray()));
+                    break;
+                default:
+                    break;
+            }
+        }
     }
 }
diff --git a/nearby/service/proto/src/presence/blefilter.proto b/nearby/service/proto/src/presence/blefilter.proto
index 47f4144..a4f479b 100644
--- a/nearby/service/proto/src/presence/blefilter.proto
+++ b/nearby/service/proto/src/presence/blefilter.proto
@@ -60,6 +60,8 @@
   enum ElementType {
     DE_NONE = 0;
     DE_FAST_PAIR_ACCOUNT_KEY = 1;
+    DE_CONNECTION_STATUS = 10;
+    DE_BATTERY_STATUS = 11;
   }
 
   optional ElementType key = 1;
diff --git a/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java b/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java
index 285816f..2b7321c 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/provider/ChreDiscoveryProviderTest.java
@@ -16,15 +16,21 @@
 
 package com.android.server.nearby.provider;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
 import android.hardware.location.NanoAppMessage;
+import android.nearby.DataElement;
+import android.nearby.NearbyDeviceParcelable;
 
 import androidx.test.filters.SdkSuppress;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.server.nearby.presence.PresenceDiscoveryResult;
+
 import com.google.protobuf.ByteString;
 
 import org.junit.Before;
@@ -34,6 +40,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Executor;
 
 import service.proto.Blefilter;
@@ -43,6 +51,10 @@
     @Mock ChreCommunication mChreCommunication;
 
     @Captor ArgumentCaptor<ChreCommunication.ContextHubCommsCallback> mChreCallbackCaptor;
+    @Captor ArgumentCaptor<NearbyDeviceParcelable> mNearbyDevice;
+
+    private static final int DATA_TYPE_CONNECTION_STATUS_KEY = 10;
+    private static final int DATA_TYPE_BATTERY_KEY = 11;
 
     private ChreDiscoveryProvider mChreDiscoveryProvider;
 
@@ -94,6 +106,63 @@
         verify(mListener).onNearbyDeviceDiscovered(any());
     }
 
+    @Test
+    @SdkSuppress(minSdkVersion = 32, codeName = "T")
+    public void testOnNearbyDeviceDiscoveredWithDataElements() {
+        final byte [] connectionStatus = new byte[] {1, 2, 3};
+        final byte [] batteryStatus = new byte[] {4, 5, 6};
+        final List<DataElement> expectedExtendedProperties = new ArrayList<>();
+        expectedExtendedProperties.add(new DataElement(DATA_TYPE_CONNECTION_STATUS_KEY,
+                connectionStatus));
+        expectedExtendedProperties.add(new DataElement(DATA_TYPE_BATTERY_KEY, batteryStatus));
+
+        Blefilter.PublicCredential credential =
+                Blefilter.PublicCredential.newBuilder()
+                        .setSecretId(ByteString.copyFrom(new byte[] {1}))
+                        .setAuthenticityKey(ByteString.copyFrom(new byte[2]))
+                        .setPublicKey(ByteString.copyFrom(new byte[3]))
+                        .setEncryptedMetadata(ByteString.copyFrom(new byte[4]))
+                        .setEncryptedMetadataTag(ByteString.copyFrom(new byte[5]))
+                        .build();
+        Blefilter.BleFilterResult result =
+                Blefilter.BleFilterResult.newBuilder()
+                        .setTxPower(2)
+                        .setRssi(1)
+                        .setPublicCredential(credential)
+                        .addDataElement(Blefilter.DataElement.newBuilder()
+                                .setKey(
+                                        Blefilter.DataElement.ElementType
+                                                .DE_CONNECTION_STATUS)
+                                .setValue(ByteString.copyFrom(connectionStatus))
+                                .setValueLength(connectionStatus.length)
+                        )
+                        .addDataElement(Blefilter.DataElement.newBuilder()
+                                .setKey(
+                                        Blefilter.DataElement.ElementType
+                                                .DE_BATTERY_STATUS)
+                                .setValue(ByteString.copyFrom(batteryStatus))
+                                .setValueLength(batteryStatus.length)
+                        )
+                        .build();
+        Blefilter.BleFilterResults results =
+                Blefilter.BleFilterResults.newBuilder().addResult(result).build();
+        NanoAppMessage chre_message =
+                NanoAppMessage.createMessageToNanoApp(
+                        ChreDiscoveryProvider.NANOAPP_ID,
+                        ChreDiscoveryProvider.NANOAPP_MESSAGE_TYPE_FILTER_RESULT,
+                        results.toByteArray());
+        mChreDiscoveryProvider.getController().setListener(mListener);
+        mChreDiscoveryProvider.init();
+        mChreDiscoveryProvider.onStart();
+        verify(mChreCommunication).start(mChreCallbackCaptor.capture(), any());
+        mChreCallbackCaptor.getValue().onMessageFromNanoApp(chre_message);
+        verify(mListener).onNearbyDeviceDiscovered(mNearbyDevice.capture());
+
+        List<DataElement> extendedProperties = PresenceDiscoveryResult
+                .fromDevice(mNearbyDevice.getValue()).getExtendedProperties();
+        assertThat(expectedExtendedProperties.equals(extendedProperties)).isTrue();
+    }
+
     private static class InLineExecutor implements Executor {
         @Override
         public void execute(Runnable command) {