• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ondevicepersonalization.services;
18 
19 import android.adservices.ondevicepersonalization.CalleeMetadata;
20 import android.adservices.ondevicepersonalization.OnDevicePersonalizationManager;
21 import android.adservices.ondevicepersonalization.aidl.IIsFeatureEnabledCallback;
22 import android.os.Binder;
23 import android.os.RemoteException;
24 import android.os.SystemClock;
25 
26 import com.android.internal.annotations.VisibleForTesting;
27 import com.android.ondevicepersonalization.internal.util.LoggerFactory;
28 
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.function.Supplier;
34 
35 public class FeatureStatusManager {
36     private static final Object sLock = new Object();
37 
38     private static final String TAG = FeatureStatusManager.class.getSimpleName();
39     private static final LoggerFactory.Logger sLogger = LoggerFactory.getLogger();
40     private static volatile FeatureStatusManager sFeatureStatusManager = null;
41 
42     private final Map<String, Supplier<Boolean>> mFlaggedFeaturesMap = new HashMap<>();
43 
44     private final Set<String> mNonFlaggedFeaturesSet = new HashSet<>();
45 
46     private Flags mFlags;
47 
48     /** Returns the status of the feature. */
getFeatureStatusAndSendResult( String featureName, long serviceEntryTime, IIsFeatureEnabledCallback callback)49     public static void getFeatureStatusAndSendResult(
50             String featureName,
51             long serviceEntryTime,
52             IIsFeatureEnabledCallback callback) {
53         int result = getInstance().isFeatureEnabled(featureName);
54         try {
55             callback.onResult(
56                     result,
57                     new CalleeMetadata.Builder()
58                             .setServiceEntryTimeMillis(serviceEntryTime)
59                             .setCallbackInvokeTimeMillis(
60                                     SystemClock.elapsedRealtime()).build());
61         } catch (RemoteException e) {
62             sLogger.w(TAG + ": Callback error", e);
63         }
64     }
65 
66     /** Returns the singleton instance of FeatureManager. */
getInstance()67     public static FeatureStatusManager getInstance() {
68         if (sFeatureStatusManager == null) {
69             synchronized (sLock) {
70                 if (sFeatureStatusManager == null) {
71                     long origId = Binder.clearCallingIdentity();
72                     sFeatureStatusManager = new FeatureStatusManager(FlagsFactory.getFlags());
73                     Binder.restoreCallingIdentity(origId);
74                 }
75             }
76         }
77         return sFeatureStatusManager;
78     }
79 
80     @VisibleForTesting
FeatureStatusManager(Flags flags)81     FeatureStatusManager(Flags flags) {
82         mFlags = flags;
83         // Add flagged features here, for example:
84         // mFlaggedFeaturesMap.put("featureName", mFlags::isFeatureEnabled);
85 
86         // Add non-flagged features here, for example:
87         // mNonFlaggedFeaturesSet.add("featureName");
88     }
89 
90     @VisibleForTesting
FeatureStatusManager(Flags flags, Map<String, Supplier<Boolean>> flaggedFeaturesMap, Set<String> nonFlaggedFeaturesSet)91     FeatureStatusManager(Flags flags,
92             Map<String, Supplier<Boolean>> flaggedFeaturesMap,
93             Set<String> nonFlaggedFeaturesSet) {
94         mFlags = flags;
95 
96         // Add flagged features here
97         mFlaggedFeaturesMap.putAll(flaggedFeaturesMap);
98 
99         // Add non-flagged features here
100         mNonFlaggedFeaturesSet.addAll(nonFlaggedFeaturesSet);
101     }
102 
103     @VisibleForTesting
isFeatureEnabled(String featureName)104     int isFeatureEnabled(String featureName) {
105         if (mNonFlaggedFeaturesSet.contains(featureName)) {
106             return OnDevicePersonalizationManager.FEATURE_ENABLED;
107         }
108 
109         if (mFlaggedFeaturesMap.containsKey(featureName)) {
110             boolean flagValue = mFlaggedFeaturesMap.get(featureName).get();
111             return flagValue ? OnDevicePersonalizationManager.FEATURE_ENABLED
112                     : OnDevicePersonalizationManager.FEATURE_DISABLED;
113         }
114 
115         return OnDevicePersonalizationManager.FEATURE_UNSUPPORTED;
116     }
117 }
118