• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
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 package com.google.android.libraries.mobiledatadownload.populator;
17 
18 import static com.google.common.util.concurrent.Futures.immediateFuture;
19 
20 import android.util.Log;
21 import com.google.android.libraries.mobiledatadownload.AddFileGroupRequest;
22 import com.google.android.libraries.mobiledatadownload.FileGroupPopulator;
23 import com.google.android.libraries.mobiledatadownload.MobileDataDownload;
24 import com.google.android.libraries.mobiledatadownload.internal.logging.LogUtil;
25 import com.google.android.libraries.mobiledatadownload.tracing.PropagatedFutures;
26 import com.google.common.base.Optional;
27 import com.google.common.base.Supplier;
28 import com.google.common.util.concurrent.FutureCallback;
29 import com.google.common.util.concurrent.ListenableFuture;
30 import com.google.common.util.concurrent.MoreExecutors;
31 import com.google.errorprone.annotations.CanIgnoreReturnValue;
32 import com.google.mobiledatadownload.DownloadConfigProto.DataFileGroup;
33 
34 /**
35  * FileGroupPopulator that gets a single file group from a supplier and populates it.
36  *
37  * <p>Client can set an optional file group overrider to override fields in the {@link
38  * DataFileGroup} if needed.
39  *
40  * <p>The overrider could also be used for on device targeting and filtering in the case that the
41  * file group is provided from a server.
42  */
43 public final class SingleDataFileGroupPopulator implements FileGroupPopulator {
44 
45   private static final String TAG = "SingleDataFileGroupPop";
46 
47   /** Builder for {@link SingleDataFileGroupPopulator}. */
48   public static final class Builder {
49     private Supplier<DataFileGroup> dataFileGroupSupplier;
50     private Optional<DataFileGroupOverrider> overriderOptional = Optional.absent();
51 
52     @CanIgnoreReturnValue
setDataFileGroupSupplier(Supplier<DataFileGroup> dataFileGroupSupplier)53     public Builder setDataFileGroupSupplier(Supplier<DataFileGroup> dataFileGroupSupplier) {
54       this.dataFileGroupSupplier = dataFileGroupSupplier;
55       return this;
56     }
57 
58     /**
59      * Sets the optional file group overrider that takes the {@link DataFileGroup} and returns a
60      * {@link DataFileGroup} after being overridden. If the overrider returns a null data file
61      * group, nothing will be populated.
62      */
63     @CanIgnoreReturnValue
setOverriderOptional(Optional<DataFileGroupOverrider> overriderOptional)64     public Builder setOverriderOptional(Optional<DataFileGroupOverrider> overriderOptional) {
65       this.overriderOptional = overriderOptional;
66       return this;
67     }
68 
build()69     public SingleDataFileGroupPopulator build() {
70       return new SingleDataFileGroupPopulator(this);
71     }
72   }
73 
74   private final Supplier<DataFileGroup> dataFileGroupSupplier;
75   private final Optional<DataFileGroupOverrider> overriderOptional;
76 
77   /** Returns a Builder for SingleDataFileGroupPopulator. */
builder()78   public static Builder builder() {
79     return new Builder();
80   }
81 
SingleDataFileGroupPopulator(Builder builder)82   private SingleDataFileGroupPopulator(Builder builder) {
83     this.dataFileGroupSupplier = builder.dataFileGroupSupplier;
84     this.overriderOptional = builder.overriderOptional;
85   }
86 
87   @Override
refreshFileGroups(MobileDataDownload mobileDataDownload)88   public ListenableFuture<Void> refreshFileGroups(MobileDataDownload mobileDataDownload) {
89     LogUtil.d("%s: Add file group to Mdd.", TAG);
90 
91     // Override data file group if the overrider is present. If the overrider returns an absent
92     // data file group, nothing will be populated.
93     ListenableFuture<Optional<DataFileGroup>> dataFileGroupOptionalFuture =
94         immediateFuture(Optional.absent());
95     if (dataFileGroupSupplier.get() != null
96         && !dataFileGroupSupplier.get().getGroupName().isEmpty()) {
97       dataFileGroupOptionalFuture =
98           overriderOptional.isPresent()
99               ? overriderOptional.get().override(dataFileGroupSupplier.get())
100               : immediateFuture(Optional.of(dataFileGroupSupplier.get()));
101     }
102 
103     ListenableFuture<Boolean> addFileGroupFuture =
104         PropagatedFutures.transformAsync(
105             dataFileGroupOptionalFuture,
106             dataFileGroupOptional -> {
107               if (dataFileGroupOptional.isPresent()
108                   && !dataFileGroupOptional.get().getGroupName().isEmpty()) {
109                 return mobileDataDownload.addFileGroup(
110                     AddFileGroupRequest.newBuilder()
111                         .setDataFileGroup(dataFileGroupOptional.get())
112                         .build());
113               }
114               LogUtil.d("%s: Not adding file group because of overrider.", TAG);
115               return immediateFuture(false);
116             },
117             MoreExecutors.directExecutor());
118 
119     PropagatedFutures.addCallback(
120         addFileGroupFuture,
121         new FutureCallback<Boolean>() {
122           @Override
123           public void onSuccess(Boolean result) {
124             String groupName = dataFileGroupSupplier.get().getGroupName();
125             if (result.booleanValue()) {
126               Log.d(TAG, "Added file group " + groupName);
127             } else {
128               Log.e(TAG, "Failed to add file group " + groupName);
129             }
130           }
131 
132           @Override
133           public void onFailure(Throwable t) {
134             Log.e(TAG, "Failed to add file group", t);
135           }
136         },
137         MoreExecutors.directExecutor());
138 
139     return PropagatedFutures.whenAllComplete(addFileGroupFuture)
140         .call(() -> null, MoreExecutors.directExecutor());
141   }
142 }
143