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.adservices.data.customaudience; 18 19 import android.content.Context; 20 21 import androidx.annotation.NonNull; 22 import androidx.room.AutoMigration; 23 import androidx.room.Database; 24 import androidx.room.RenameColumn; 25 import androidx.room.Room; 26 import androidx.room.RoomDatabase; 27 import androidx.room.TypeConverters; 28 import androidx.room.migration.AutoMigrationSpec; 29 30 import com.android.adservices.data.common.FledgeRoomConverters; 31 import com.android.adservices.service.FlagsFactory; 32 import com.android.adservices.service.common.BinderFlagReader; 33 34 import java.util.Objects; 35 36 /** Room based database for custom audience. */ 37 @Database( 38 entities = { 39 DBCustomAudience.class, 40 DBCustomAudienceBackgroundFetchData.class, 41 DBCustomAudienceOverride.class 42 }, 43 version = CustomAudienceDatabase.DATABASE_VERSION, 44 autoMigrations = { 45 @AutoMigration(from = 1, to = 2, spec = CustomAudienceDatabase.AutoMigration1To2.class), 46 @AutoMigration(from = 2, to = 3), 47 }) 48 @TypeConverters({FledgeRoomConverters.class}) 49 public abstract class CustomAudienceDatabase extends RoomDatabase { 50 private static final Object SINGLETON_LOCK = new Object(); 51 52 public static final int DATABASE_VERSION = 3; 53 // TODO(b/230653780): Should we separate the DB. 54 public static final String DATABASE_NAME = "customaudience.db"; 55 56 @RenameColumn( 57 tableName = DBCustomAudience.TABLE_NAME, 58 fromColumnName = "bidding_logic_url", 59 toColumnName = "bidding_logic_uri") 60 @RenameColumn( 61 tableName = DBCustomAudience.TABLE_NAME, 62 fromColumnName = "trusted_bidding_data_url", 63 toColumnName = "trusted_bidding_data_uri") 64 @RenameColumn( 65 tableName = DBCustomAudienceBackgroundFetchData.TABLE_NAME, 66 fromColumnName = "daily_update_url", 67 toColumnName = "daily_update_uri") 68 static class AutoMigration1To2 implements AutoMigrationSpec {} 69 70 private static volatile CustomAudienceDatabase sSingleton; 71 72 // TODO: How we want handle synchronized situation (b/228101878). 73 74 /** Returns an instance of the CustomAudienceDatabase given a context. */ getInstance(@onNull Context context)75 public static CustomAudienceDatabase getInstance(@NonNull Context context) { 76 Objects.requireNonNull(context, "Context must be provided."); 77 // Initialization pattern recommended on page 334 of "Effective Java" 3rd edition 78 CustomAudienceDatabase singleReadResult = sSingleton; 79 if (singleReadResult != null) { 80 return singleReadResult; 81 } 82 synchronized (SINGLETON_LOCK) { 83 if (sSingleton == null) { 84 DBCustomAudience.Converters converters = 85 new DBCustomAudience.Converters( 86 BinderFlagReader.readFlag( 87 () -> 88 FlagsFactory.getFlags() 89 .getFledgeAdSelectionFilteringEnabled())); 90 sSingleton = 91 Room.databaseBuilder(context, CustomAudienceDatabase.class, DATABASE_NAME) 92 .fallbackToDestructiveMigration() 93 .addTypeConverter(converters) 94 .build(); 95 } 96 return sSingleton; 97 } 98 } 99 100 /** 101 * Custom Audience Dao. 102 * 103 * @return Dao to access custom audience storage. 104 */ customAudienceDao()105 public abstract CustomAudienceDao customAudienceDao(); 106 } 107