1 /* 2 * Copyright (C) 2024 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.kanon; 18 19 import android.annotation.RequiresApi; 20 import android.content.Context; 21 import android.os.Build; 22 23 import androidx.annotation.NonNull; 24 25 import com.android.adservices.concurrency.AdServicesExecutors; 26 import com.android.adservices.service.Flags; 27 import com.android.adservices.service.FlagsFactory; 28 import com.android.adservices.service.common.SingletonRunner; 29 import com.android.internal.annotations.VisibleForTesting; 30 31 import com.google.common.util.concurrent.FluentFuture; 32 import com.google.common.util.concurrent.Futures; 33 34 import java.util.Objects; 35 import java.util.function.Supplier; 36 37 @RequiresApi(Build.VERSION_CODES.S) 38 public class KAnonSignJoinBackgroundJobWorker { 39 public static final String JOB_DESCRIPTION = "FLEDGE KAnon Sign Join Background Job"; 40 private static final Object SINGLETON_LOCK = new Object(); 41 private static volatile KAnonSignJoinBackgroundJobWorker sKAnonSignJoinBackgroundJobWorker; 42 43 private final KAnonSignJoinManager mKAnonSignJoinManager; 44 private final Flags mFlags; 45 private final SingletonRunner<Void> mSingletonRunner = 46 new SingletonRunner<>(JOB_DESCRIPTION, this::doRun); 47 48 /** 49 * Gets an instance of a {@link KAnonSignJoinBackgroundJobWorker}. If an instance hasn't been 50 * initialized, a new singleton will be created and returned. 51 */ getInstance(@onNull Context context)52 public static KAnonSignJoinBackgroundJobWorker getInstance(@NonNull Context context) { 53 Objects.requireNonNull(context); 54 if (sKAnonSignJoinBackgroundJobWorker == null) { 55 synchronized (SINGLETON_LOCK) { 56 sKAnonSignJoinBackgroundJobWorker = 57 new KAnonSignJoinBackgroundJobWorker( 58 context, 59 FlagsFactory.getFlags(), 60 new KAnonSignJoinFactory(context).getKAnonSignJoinManager()); 61 } 62 } 63 return sKAnonSignJoinBackgroundJobWorker; 64 } 65 66 @VisibleForTesting KAnonSignJoinBackgroundJobWorker( @onNull Context context, @NonNull Flags flags, @NonNull KAnonSignJoinManager kAnonSignJoinManager)67 public KAnonSignJoinBackgroundJobWorker( 68 @NonNull Context context, 69 @NonNull Flags flags, 70 @NonNull KAnonSignJoinManager kAnonSignJoinManager) { 71 Objects.requireNonNull(kAnonSignJoinManager); 72 Objects.requireNonNull(flags); 73 Objects.requireNonNull(context); 74 75 mKAnonSignJoinManager = kAnonSignJoinManager; 76 mFlags = flags; 77 } 78 79 /** 80 * Runs the k-anon sign job. 81 * 82 * @return A future to be used to check when the task has completed. 83 */ runSignJoinBackgroundProcess()84 public FluentFuture<Void> runSignJoinBackgroundProcess() { 85 return mSingletonRunner.runSingleInstance(); 86 } 87 doRun(@onNull Supplier<Boolean> shouldStop)88 private FluentFuture<Void> doRun(@NonNull Supplier<Boolean> shouldStop) { 89 if (shouldStop.get() || !mFlags.getFledgeKAnonBackgroundProcessEnabled()) { 90 return FluentFuture.from(Futures.immediateVoidFuture()); 91 } 92 return FluentFuture.from(Futures.immediateVoidFuture()) 93 .transform( 94 ignored -> { 95 mKAnonSignJoinManager.processMessagesFromDatabase( 96 mFlags.getFledgeKAnonMessagesPerBackgroundProcess()); 97 return null; 98 }, 99 AdServicesExecutors.getBackgroundExecutor()); 100 } 101 102 /** Requests that any ongoing work be stopped. */ stopWork()103 public void stopWork() { 104 mSingletonRunner.stopWork(); 105 } 106 } 107