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