1 /* 2 * Copyright (C) 2023 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.adservices.service.adselection; 18 19 import android.annotation.NonNull; 20 import android.net.Uri; 21 22 import com.android.adservices.LogUtil; 23 import com.android.adservices.data.customaudience.DBTrustedBiddingData; 24 import com.android.internal.annotations.VisibleForTesting; 25 26 27 import org.json.JSONException; 28 import org.json.JSONObject; 29 30 import java.util.List; 31 import java.util.Map; 32 import java.util.Objects; 33 34 /** Utility class to fetch the data version from trusted bidding/scoring signals. */ 35 public class DataVersionFetcher { 36 public static final String DATA_VERSION_HEADER_BIDDING_KEY = 37 "x-fledge-bidding-signals-format-version"; 38 39 public static final String DATA_VERSION_HEADER_SCORING_KEY = 40 "x-fledge-scoring-signals-format-version"; 41 42 @VisibleForTesting static final int MAX_UNSIGNED_8_BIT = 255; 43 44 /** 45 * Extracts the data version for the buyer and returns it if it exists. 46 * 47 * @param trustedBiddingData contains the {@link Uri} which is used as a key to fetch the 48 * headers for this ad. 49 * @param trustedBiddingResponsesByBaseUri contains the trusted bidding headers for this ad 50 * where we may find the data version header. 51 * @throws IllegalStateException if the data version does not exist for this combination of 52 * {@link DBTrustedBiddingData#getUri()} and {@code Map<Uri, TrustedBiddingResponse> 53 * trustedBiddingResponsesByBaseUri}, or if {@link TrustedBiddingResponse#getHeaders()} does 54 * not conform to the expected requirements. 55 */ getBuyerDataVersion( @onNull DBTrustedBiddingData trustedBiddingData, @NonNull Map<Uri, TrustedBiddingResponse> trustedBiddingResponsesByBaseUri)56 public static int getBuyerDataVersion( 57 @NonNull DBTrustedBiddingData trustedBiddingData, 58 @NonNull Map<Uri, TrustedBiddingResponse> trustedBiddingResponsesByBaseUri) 59 throws IllegalStateException { 60 if (Objects.isNull(trustedBiddingData) 61 || Objects.isNull( 62 trustedBiddingResponsesByBaseUri.get(trustedBiddingData.getUri()))) { 63 throw new IllegalStateException("Data Version Header does not exist"); 64 } 65 int dataVersion; 66 JSONObject headers; 67 try { 68 headers = 69 trustedBiddingResponsesByBaseUri.get(trustedBiddingData.getUri()).getHeaders(); 70 dataVersion = headers.getJSONArray(DATA_VERSION_HEADER_BIDDING_KEY).getInt(0); 71 } catch (JSONException e) { 72 LogUtil.v("Data version header does not conform required header formatting."); 73 throw new IllegalStateException( 74 "Data version header does not conform required header formatting."); 75 } 76 if (dataVersion < 0 || dataVersion > MAX_UNSIGNED_8_BIT) { 77 LogUtil.v("Header object: " + headers + " does not conform to 8 bit requirements."); 78 throw new IllegalStateException( 79 "Data version header does not conform to unsigned 8 bit requirements,"); 80 } 81 return dataVersion; 82 } 83 84 /** 85 * Extracts the data version for the seller and returns it if it exists. 86 * 87 * @param headers contains the trusted scoring headers for this seller where we may find the 88 * data version header. 89 * @throws IllegalStateException if the data version does not exist or it does not conform to 90 * the expected requirements. 91 */ getSellerDataVersion(@onNull Map<String, List<String>> headers)92 public static int getSellerDataVersion(@NonNull Map<String, List<String>> headers) 93 throws IllegalStateException { 94 if (Objects.isNull(headers)) { 95 throw new IllegalStateException("Data Version Header does not exist"); 96 } 97 int dataVersion; 98 try { 99 dataVersion = Integer.parseInt(headers.get(DATA_VERSION_HEADER_SCORING_KEY).get(0)); 100 } catch (Exception e) { 101 LogUtil.v("Data version header does not conform required header formatting."); 102 throw new IllegalStateException( 103 "Data version header does not conform required header formatting."); 104 } 105 if (dataVersion < 0 || dataVersion > MAX_UNSIGNED_8_BIT) { 106 LogUtil.v("Data version: " + dataVersion + " does not conform to 8 bit requirements."); 107 throw new IllegalStateException( 108 "Data version header does not conform to unsigned 8 bit requirements,"); 109 } 110 return dataVersion; 111 } 112 } 113