1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.uwb.data; 18 19 import static com.android.server.uwb.UwbConfigStore.INITIAL_CONFIG_STORE_DATA_VERSION; 20 import static com.android.server.uwb.UwbConfigStore.STORE_FILE_USER_GENERAL; 21 22 import android.util.Log; 23 24 import androidx.annotation.Nullable; 25 26 import com.android.proto.uwb.UwbConfigProto; 27 import com.android.server.uwb.UwbConfigStore; 28 import com.android.server.uwb.util.ObjectIdentifier; 29 30 import com.google.protobuf.ByteString; 31 32 import java.util.HashMap; 33 import java.util.List; 34 import java.util.Map; 35 import java.util.Optional; 36 import java.util.UUID; 37 38 public class ServiceProfileData implements UwbConfigStore.StoreData { 39 private static final String LOG_TAG = "ServiceProfileData"; 40 ServiceProfileData(DataSource dataSource)41 public ServiceProfileData(DataSource dataSource) { 42 this.mDataSource = dataSource; 43 } 44 45 public static class ServiceProfileInfo { 46 public static final int ADF_STATUS_NOT_PROVISIONED = 0; 47 public static final int ADF_STATUS_CREATED = 1; 48 public static final int ADF_STATUS_PROVISIONED = 2; 49 /** 50 * Unique 128-bit service instance ID 51 */ 52 public final UUID serviceInstanceID; 53 /** 54 * App uid 55 */ 56 public final int uid; 57 /** 58 * App package name 59 */ 60 public final String packageName; 61 /** 62 * Service ID, like PACS or custom service 63 */ 64 public final int serviceID; 65 /** 66 * Applet ID for dynamic STS 67 */ 68 private int mServiceAppletId; 69 70 private int mAdfStatus = ADF_STATUS_NOT_PROVISIONED; 71 /** 72 * ADF OID 73 */ 74 private Optional<ObjectIdentifier> mServiceAdfOid = Optional.empty(); 75 76 /** 77 * secure blob for ADF. 78 */ 79 private Optional<byte[]> mSecureBlob = Optional.empty(); 80 81 /** 82 * 83 * serviceAppletID and serviceAdfOid will be set after provisioning. 84 */ ServiceProfileInfo(UUID serviceInstanceID, int uid, String packageName, int serviceID)85 public ServiceProfileInfo(UUID serviceInstanceID, int uid, 86 String packageName, int serviceID) { 87 this.serviceInstanceID = serviceInstanceID; 88 this.uid = uid; 89 this.packageName = packageName; 90 this.serviceID = serviceID; 91 } 92 setServiceAppletId(int serviceAppletId)93 public void setServiceAppletId(int serviceAppletId) { 94 this.mServiceAppletId = serviceAppletId; 95 } 96 setServiceAdfOid(@ullable ObjectIdentifier serviceAdfOid)97 public void setServiceAdfOid(@Nullable ObjectIdentifier serviceAdfOid) { 98 this.mServiceAdfOid = Optional.ofNullable(serviceAdfOid); 99 } 100 getServiceAppletId()101 public int getServiceAppletId() { 102 return mServiceAppletId; 103 } 104 setSecureBlob(@ullable byte[] secureBlob)105 public void setSecureBlob(@Nullable byte[] secureBlob) { 106 mSecureBlob = Optional.ofNullable(secureBlob); 107 } 108 getSecureBlob()109 public Optional<byte[]> getSecureBlob() { 110 return mSecureBlob; 111 } 112 getServiceAdfOid()113 public Optional<ObjectIdentifier> getServiceAdfOid() { 114 return mServiceAdfOid; 115 } 116 setAdfStatus(int status)117 public void setAdfStatus(int status) { 118 mAdfStatus = status; 119 } 120 getAdfStatus()121 public int getAdfStatus() { 122 return mAdfStatus; 123 } 124 125 } 126 127 /** 128 * Interface define the data source for service config store data. 129 */ 130 public interface DataSource { 131 /** 132 * Retrieve the service config list from the data source to serialize them to disk. 133 * 134 * @return Map of package name to {@link ServiceProfileInfo} 135 */ toSerialize()136 Map<UUID, ServiceProfileInfo> toSerialize(); 137 138 /** 139 * Set the service config list in the data source after serializing them from disk. 140 * 141 * @param serviceProfileData Map of package name to {@link ServiceProfileInfo} 142 */ fromDeserialized(Map<UUID, ServiceProfileInfo> serviceProfileData)143 void fromDeserialized(Map<UUID, ServiceProfileInfo> serviceProfileData); 144 145 /** 146 * Clear internal data structure in preparation for user switch or initial store read. 147 */ reset()148 void reset(); 149 150 /** 151 * Indicates whether there is new data to serialize. 152 */ hasNewDataToSerialize()153 boolean hasNewDataToSerialize(); 154 } 155 156 /** 157 * Data source 158 */ 159 private final DataSource mDataSource; 160 161 /** 162 * 163 * @param builder 164 * Add all service configs to builder so that uwb config store can build and store. 165 */ 166 @Override serializeData(UwbConfigProto.UwbConfig.Builder builder)167 public void serializeData(UwbConfigProto.UwbConfig.Builder builder) { 168 for (Map.Entry<UUID, ServiceProfileInfo> entry : mDataSource.toSerialize().entrySet()) { 169 UwbConfigProto.ServiceConfig.Builder serviceConfigBuilder = 170 UwbConfigProto.ServiceConfig.newBuilder(); 171 ServiceProfileInfo serviceProfileInfo = entry.getValue(); 172 serviceConfigBuilder.setServiceInstanceId(serviceProfileInfo 173 .serviceInstanceID.toString()); 174 serviceConfigBuilder.setPackageName(serviceProfileInfo.packageName); 175 serviceConfigBuilder.setUid(serviceProfileInfo.uid); 176 serviceConfigBuilder.setServiceId(serviceProfileInfo.serviceID); 177 serviceConfigBuilder.setServiceAppletId(serviceProfileInfo.getServiceAppletId()); 178 serviceConfigBuilder.setAdfStatus(serviceProfileInfo.getAdfStatus()); 179 serviceProfileInfo.getServiceAdfOid().ifPresent( 180 adfOid -> serviceConfigBuilder.setServiceAdfOid( 181 ByteString.copyFrom(adfOid.value))); 182 serviceProfileInfo.getSecureBlob().ifPresent( 183 secureBlob -> serviceConfigBuilder.setSecureBlob( 184 ByteString.copyFrom(secureBlob))); 185 builder.addServiceConfig(serviceConfigBuilder.build()); 186 } 187 } 188 /** 189 * 190 * @param uwbConfig 191 * Wrapper to check whether we are using correct version of uwb-config-proto 192 */ 193 @Override deserializeData(@ullable UwbConfigProto.UwbConfig uwbConfig)194 public void deserializeData(@Nullable UwbConfigProto.UwbConfig uwbConfig) { 195 if (uwbConfig == null || !uwbConfig.hasVersion()) { 196 Log.i(LOG_TAG, "No data stored"); 197 return; 198 } 199 200 switch (uwbConfig.getVersion()) { 201 case INITIAL_CONFIG_STORE_DATA_VERSION : 202 deserializeDataVersion1(uwbConfig); 203 break; 204 default: 205 throw new IllegalArgumentException("Unknown Uwb config store version"); 206 } 207 } 208 209 /** 210 * Get all data stored and put it in a map 211 */ deserializeDataVersion1(UwbConfigProto.UwbConfig uwbConfig)212 public void deserializeDataVersion1(UwbConfigProto.UwbConfig uwbConfig) { 213 List<UwbConfigProto.ServiceConfig> serviceConfigList = uwbConfig.getServiceConfigList(); 214 Map<UUID, ServiceProfileInfo> serviceProfileDataMap = new HashMap<>(); 215 for (UwbConfigProto.ServiceConfig serviceConfig : serviceConfigList) { 216 ServiceProfileInfo serviceProfileInfo = new ServiceProfileInfo( 217 UUID.fromString(serviceConfig.getServiceInstanceId()), 218 serviceConfig.getUid(), 219 serviceConfig.getPackageName(), 220 serviceConfig.getServiceId()); 221 serviceProfileInfo.setServiceAppletId(serviceConfig.getServiceAppletId()); 222 serviceProfileInfo.setAdfStatus(serviceConfig.getAdfStatus()); 223 224 serviceProfileInfo.setServiceAdfOid( 225 ObjectIdentifier.fromBytes(serviceConfig.getServiceAdfOid().toByteArray())); 226 227 serviceProfileInfo.setSecureBlob( 228 serviceConfig.getSecureBlob().toByteArray()); 229 serviceProfileDataMap.put(serviceProfileInfo.serviceInstanceID, serviceProfileInfo); 230 } 231 mDataSource.fromDeserialized(serviceProfileDataMap); 232 } 233 234 @Override resetData()235 public void resetData() { 236 mDataSource.reset(); 237 } 238 239 @Override hasNewDataToSerialize()240 public boolean hasNewDataToSerialize() { 241 return mDataSource.hasNewDataToSerialize(); 242 } 243 244 @Override getName()245 public String getName() { 246 return LOG_TAG; 247 } 248 249 @Override getStoreFileId()250 public int getStoreFileId() { 251 return STORE_FILE_USER_GENERAL; 252 } 253 } 254