[uwb] Add service profile data to hold to service config
Applet Id and Adf Id can be set later.
Bug: 229410097
Test: Verified manually by implementing profile manager
Change-Id: I680795a343d1b0977f4921131a63565a4a213bea
diff --git a/service/java/com/android/server/uwb/data/ServiceProfileData.java b/service/java/com/android/server/uwb/data/ServiceProfileData.java
new file mode 100644
index 0000000..0459670
--- /dev/null
+++ b/service/java/com/android/server/uwb/data/ServiceProfileData.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package com.android.server.uwb.data;
+
+import static com.android.server.uwb.UwbConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION;
+import static com.android.server.uwb.UwbConfigStore.STORE_FILE_USER_GENERAL;
+
+import android.util.Log;
+
+import androidx.annotation.Nullable;
+
+import com.android.server.uwb.UwbConfigStore;
+import com.android.server.uwb.proto.UwbConfigProto;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+public class ServiceProfileData implements UwbConfigStore.StoreData {
+
+ private static String TAG = "ServiceProfileData";
+
+ public ServiceProfileData(DataSource dataSource) {
+ this.mDataSource = dataSource;
+ }
+
+ public static class ServiceProfileInfo {
+ /**
+ * Unique 128-bit service instance ID
+ */
+ public final UUID serviceInstanceID;
+ /**
+ * App uid
+ */
+ public final int uid;
+ /**
+ * App package name
+ */
+ public final String packageName;
+ /**
+ * Service ID, like PACS or custom service
+ */
+ public final int serviceID;
+ /**
+ * Applet ID for dynamic STS
+ */
+ private int serviceAppletID;
+ /**
+ * ADF OID
+ */
+ private int serviceAdfID;
+
+ /**
+ *
+ * serviceAppletID and serviceAdfID will be set after provisioning.
+ */
+ public ServiceProfileInfo(UUID serviceInstanceID, int uid,
+ String packageName, int serviceID) {
+ this.serviceInstanceID = serviceInstanceID;
+ this.uid = uid;
+ this.packageName = packageName;
+ this.serviceID = serviceID;
+ }
+
+ public void setServiceAppletID(int serviceAppletID) {
+ this.serviceAppletID = serviceAppletID;
+ }
+
+ public void setServiceAdfID(int serviceAdfID) {
+ this.serviceAdfID = serviceAdfID;
+ }
+
+ public int getServiceAppletID() {
+ return serviceAppletID;
+ }
+
+ public int getServiceAdfID() {
+ return serviceAdfID;
+ }
+
+ }
+
+ /**
+ * Interface define the data source for service config store data.
+ */
+ public interface DataSource {
+ /**
+ * Retrieve the service config list from the data source to serialize them to disk.
+ *
+ * @return Map of package name to {@link ServiceProfileInfo}
+ */
+ Map<UUID, ServiceProfileInfo> toSerialize();
+
+ /**
+ * Set the service config list in the data source after serializing them from disk.
+ *
+ * @param serviceProfileData Map of package name to {@link ServiceProfileInfo}
+ */
+ void fromDeserialized(Map<UUID, ServiceProfileInfo> serviceProfileData);
+
+ /**
+ * Clear internal data structure in preparation for user switch or initial store read.
+ */
+ void reset();
+
+ /**
+ * Indicates whether there is new data to serialize.
+ */
+ boolean hasNewDataToSerialize();
+ }
+
+ /**
+ * Data source
+ */
+ private final DataSource mDataSource;
+
+ /**
+ *
+ * @param builder
+ * Add all service configs to builder so that uwb config store can build and store.
+ */
+ @Override
+ public void serializeData(UwbConfigProto.UwbConfig.Builder builder) {
+ for (Map.Entry<UUID, ServiceProfileInfo> entry : mDataSource.toSerialize().entrySet()) {
+ UwbConfigProto.ServiceConfig.Builder serviceConfigBuilder =
+ UwbConfigProto.ServiceConfig.newBuilder();
+ ServiceProfileInfo serviceProfileInfo = entry.getValue();
+ serviceConfigBuilder.setServiceInstanceId(serviceProfileInfo
+ .serviceInstanceID.toString());
+ serviceConfigBuilder.setPackageName(serviceProfileInfo.packageName);
+ serviceConfigBuilder.setUid(serviceProfileInfo.uid);
+ serviceConfigBuilder.setServiceId(serviceProfileInfo.serviceID);
+ serviceConfigBuilder.setServiceAppletId(serviceProfileInfo.getServiceAppletID());
+ serviceConfigBuilder.setServiceAdfId(serviceProfileInfo.getServiceAdfID());
+ builder.addServiceConfig(serviceConfigBuilder.build());
+ }
+ }
+ /**
+ *
+ * @param uwbConfig
+ * Wrapper to check whether we are using correct version of uwb-config-proto
+ */
+ @Override
+ public void deserializeData(@Nullable UwbConfigProto.UwbConfig uwbConfig) {
+ if (uwbConfig == null || !uwbConfig.hasVersion()) {
+ Log.i(TAG, "No data stored");
+ return;
+ }
+
+ switch (uwbConfig.getVersion()) {
+ case INITIAL_CONFIG_STORE_DATA_VERSION :
+ deserializeDataVersion1(uwbConfig);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown Uwb config store version");
+ }
+ }
+
+ /**
+ * Get all data stored and put it in a map
+ */
+ public void deserializeDataVersion1(UwbConfigProto.UwbConfig uwbConfig) {
+ List<UwbConfigProto.ServiceConfig> serviceConfigList = uwbConfig.getServiceConfigList();
+ Map<UUID, ServiceProfileInfo> serviceProfileDataMap = new HashMap<>();
+ for (UwbConfigProto.ServiceConfig serviceConfig : serviceConfigList) {
+ ServiceProfileInfo serviceProfileInfo = new ServiceProfileInfo(
+ UUID.fromString(serviceConfig.getServiceInstanceId()),
+ serviceConfig.getUid(),
+ serviceConfig.getPackageName(),
+ serviceConfig.getServiceId());
+ serviceProfileInfo.setServiceAppletID(serviceConfig.getServiceAppletId());
+ serviceProfileInfo.setServiceAdfID(serviceConfig.getServiceAdfId());
+ serviceProfileDataMap.put(serviceProfileInfo.serviceInstanceID, serviceProfileInfo);
+ }
+ mDataSource.fromDeserialized(serviceProfileDataMap);
+ }
+
+ @Override
+ public void resetData() {
+ mDataSource.reset();
+ }
+
+ @Override
+ public boolean hasNewDataToSerialize() {
+ return mDataSource.hasNewDataToSerialize();
+ }
+
+ @Override
+ public String getName() {
+ return TAG;
+ }
+
+ @Override
+ public int getStoreFileId() {
+ return STORE_FILE_USER_GENERAL;
+ }
+}
diff --git a/service/tests/src/com/android/server/uwb/data/ServiceProfileDataTest.java b/service/tests/src/com/android/server/uwb/data/ServiceProfileDataTest.java
new file mode 100644
index 0000000..56af428
--- /dev/null
+++ b/service/tests/src/com/android/server/uwb/data/ServiceProfileDataTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package com.android.server.uwb.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.uwb.data.ServiceProfileData.ServiceProfileInfo;
+import com.android.server.uwb.proto.UwbConfigProto;
+
+import com.google.protobuf.InvalidProtocolBufferException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+@Presubmit
+public class ServiceProfileDataTest {
+ private MockDataSource mDataSource;
+ private ServiceProfileData mServiceProfileData;
+
+ @Before
+ public void setUp() {
+ mDataSource = new MockDataSource();
+ mServiceProfileData = new ServiceProfileData(mDataSource);
+ }
+
+ @Test
+ public void testSerializeData() {
+ UwbConfigProto.UwbConfig.Builder builder = UwbConfigProto.UwbConfig.newBuilder();
+ builder.setVersion(1);
+ mServiceProfileData.serializeData(builder);
+
+ UwbConfigProto.ServiceConfig serviceConfig = builder.getServiceConfig(0);
+ UUID serviceInstanceID = new UUID(100, 500);
+
+ assertEquals(serviceConfig.getServiceId(), 1);
+ assertEquals(serviceConfig.getServiceInstanceId(), serviceInstanceID);
+ assertEquals(serviceConfig.getUid(), 1);
+ assertEquals(serviceConfig.getPackageName(), "test");
+
+ }
+
+ @Test
+ public void testDeserializeData() throws InvalidProtocolBufferException {
+ UwbConfigProto.UwbConfig.Builder builder = UwbConfigProto.UwbConfig.newBuilder();
+ builder.setVersion(1);
+ mServiceProfileData.serializeData(builder);
+ byte[] dataBytes = builder.build().toByteArray();
+ UwbConfigProto.UwbConfig uwbConfig = UwbConfigProto.UwbConfig.parseFrom(dataBytes);
+
+ mServiceProfileData.deserializeData(uwbConfig);
+ assertTrue(mDataSource.mData.size() == 1);
+
+ mServiceProfileData.resetData();
+ assertTrue(mDataSource.mData == null);
+
+ assertTrue(mServiceProfileData.hasNewDataToSerialize());
+
+ assertEquals(mServiceProfileData.getName(), "ServiceProfileData");
+
+ assertEquals(mServiceProfileData.getStoreFileId(), 1);
+ }
+
+ private static class MockDataSource implements ServiceProfileData.DataSource {
+
+ public Map<UUID, ServiceProfileData.ServiceProfileInfo> mData =
+ new HashMap<>();
+ @Override
+ public Map<UUID, ServiceProfileInfo> toSerialize() {
+ Map<UUID, ServiceProfileInfo> mServiceProfileMap =
+ new HashMap<>();
+ UUID serviceInstanceID = new UUID(100, 500);
+ int uid = 1;
+ String packageName = "test";
+ int serviceID = 1;
+ ServiceProfileInfo mServiceProfileInfo =
+ new ServiceProfileInfo(serviceInstanceID, uid, packageName, serviceID);
+ mServiceProfileMap.put(serviceInstanceID, mServiceProfileInfo);
+ return mServiceProfileMap;
+ }
+
+ @Override
+ public void fromDeserialized(
+ Map<UUID, ServiceProfileData.ServiceProfileInfo> serviceProfileData) {
+ mData = serviceProfileData;
+ }
+
+ @Override
+ public void reset() {
+ mData = null;
+ }
+
+ @Override
+ public boolean hasNewDataToSerialize() {
+ return true;
+ }
+ }
+}