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