Loading packages/SystemUI/shared/src/com/android/systemui/flags/FlagReader.kt +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,11 @@ package com.android.systemui.flags * Plugin for loading flag values */ interface FlagReader { /** Returns a boolean value for the given flag. */ fun isEnabled(flag: BooleanFlag): Boolean { return flag.default } /** Returns a boolean value for the given flag. */ fun isEnabled(id: Int, def: Boolean): Boolean { return def Loading packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java +33 −6 Original line number Diff line number Diff line Loading @@ -26,13 +26,16 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.Bundle; import android.util.Log; import androidx.annotation.BoolRes; import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.settings.SecureSettings; Loading Loading @@ -62,14 +65,19 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { private final FlagManager mFlagManager; private final SecureSettings mSecureSettings; private final Resources mResources; private final Map<Integer, Boolean> mBooleanFlagCache = new HashMap<>(); @Inject public FeatureFlagManager(FlagManager flagManager, SecureSettings secureSettings, Context context, public FeatureFlagManager( FlagManager flagManager, Context context, SecureSettings secureSettings, @Main Resources resources, DumpManager dumpManager) { mFlagManager = flagManager; mSecureSettings = secureSettings; mResources = resources; IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_SET_FLAG); filter.addAction(ACTION_GET_FLAGS); Loading @@ -77,17 +85,32 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { dumpManager.registerDumpable(TAG, this); } /** Return a {@link BooleanFlag}'s value. */ @Override public boolean isEnabled(int id, boolean defaultValue) { public boolean isEnabled(BooleanFlag flag) { int id = flag.getId(); if (!mBooleanFlagCache.containsKey(id)) { Boolean result = isEnabledInternal(id); mBooleanFlagCache.put(id, result == null ? defaultValue : result); boolean def = flag.getDefault(); if (flag.hasResourceOverride()) { try { def = isEnabledInOverlay(flag.getResourceOverride()); } catch (Resources.NotFoundException e) { // no-op } } mBooleanFlagCache.put(id, isEnabled(id, def)); } return mBooleanFlagCache.get(id); } /** Return a {@link BooleanFlag}'s value. */ @Override public boolean isEnabled(int id, boolean defaultValue) { Boolean result = isEnabledInternal(id); return result == null ? defaultValue : result; } /** Returns the stored value or null if not set. */ private Boolean isEnabledInternal(int id) { try { Loading @@ -98,6 +121,10 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { return null; } private boolean isEnabledInOverlay(@BoolRes int resId) { return mResources.getBoolean(resId); } /** Set whether a given {@link BooleanFlag} is enabled or not. */ @Override public void setEnabled(int id, boolean value) { Loading packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java +6 −4 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.flags; import android.content.Context; import android.util.SparseBooleanArray; import androidx.annotation.NonNull; Loading @@ -24,7 +23,6 @@ import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.settings.SecureSettings; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -41,8 +39,7 @@ import javax.inject.Inject; public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { SparseBooleanArray mAccessedFlags = new SparseBooleanArray(); @Inject public FeatureFlagManager( SecureSettings secureSettings, Context context, DumpManager dumpManager) { public FeatureFlagManager(DumpManager dumpManager) { dumpManager.registerDumpable("SysUIFlags", this); } Loading @@ -52,6 +49,11 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { @Override public void removeListener(Listener run) {} @Override public boolean isEnabled(BooleanFlag flag) { return isEnabled(flag.getId(), flag.getDefault()); } @Override public boolean isEnabled(int key, boolean defaultValue) { mAccessedFlags.append(key, defaultValue); Loading packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java +2 −72 Original line number Diff line number Diff line Loading @@ -17,22 +17,11 @@ package com.android.systemui.flags; import android.content.Context; import android.content.res.Resources; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.SparseArray; import android.widget.Toast; import androidx.annotation.BoolRes; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; Loading @@ -43,31 +32,13 @@ import javax.inject.Inject; */ @SysUISingleton public class FeatureFlags { private final Resources mResources; private final FlagReader mFlagReader; private final Context mContext; private final Map<Integer, Flag<?>> mFlagMap = new HashMap<>(); private final Map<Integer, List<Listener>> mListeners = new HashMap<>(); private final SparseArray<Boolean> mCachedFlags = new SparseArray<>(); @Inject public FeatureFlags(@Main Resources resources, FlagReader flagReader, Context context) { mResources = resources; public FeatureFlags(FlagReader flagReader, Context context) { mFlagReader = flagReader; mContext = context; flagReader.addListener(mListener); } private final FlagReader.Listener mListener = id -> { if (mListeners.containsKey(id) && mFlagMap.containsKey(id)) { mListeners.get(id).forEach(listener -> listener.onFlagChanged(mFlagMap.get(id))); } }; @VisibleForTesting void addFlag(Flag<?> flag) { mFlagMap.put(flag.getId(), flag); } /** Loading @@ -75,32 +46,7 @@ public class FeatureFlags { * @return The value of the flag. */ public boolean isEnabled(BooleanFlag flag) { boolean def = flag.getDefault(); if (flag.hasResourceOverride()) { try { def = isEnabledInOverlay(flag.getResourceOverride()); } catch (Resources.NotFoundException e) { // no-op } } return mFlagReader.isEnabled(flag.getId(), def); } /** * @param flag The {@link IntFlag} of interest. /** Add a listener for a specific flag. */ public void addFlagListener(Flag<?> flag, Listener listener) { mListeners.putIfAbsent(flag.getId(), new ArrayList<>()); mListeners.get(flag.getId()).add(listener); mFlagMap.putIfAbsent(flag.getId(), flag); } /** Remove a listener for a specific flag. */ public void removeFlagListener(Flag<?> flag, Listener listener) { if (mListeners.containsKey(flag.getId())) { mListeners.get(flag.getId()).remove(listener); } return mFlagReader.isEnabled(flag); } public void assertLegacyPipelineEnabled() { Loading Loading @@ -205,20 +151,4 @@ public class FeatureFlags { public static boolean isProviderModelSettingEnabled(Context context) { return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL); } private boolean isEnabledInOverlay(@BoolRes int resId) { synchronized (mCachedFlags) { if (!mCachedFlags.contains(resId)) { mCachedFlags.put(resId, mResources.getBoolean(resId)); } return mCachedFlags.get(resId); } } /** Simple interface for beinga alerted when a specific flag changes value. */ public interface Listener { /** */ void onFlagChanged(Flag<?> flag); } } packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java +1 −6 Original line number Diff line number Diff line Loading @@ -53,8 +53,6 @@ import java.io.StringWriter; public class FeatureFlagManagerTest extends SysuiTestCase { FeatureFlagManager mFeatureFlagManager; @Mock private FlagManager mFlagManager; @Mock private SecureSettings mSecureSettings; @Mock private Context mContext; @Mock private DumpManager mDumpManager; Loading @@ -62,14 +60,11 @@ public class FeatureFlagManagerTest extends SysuiTestCase { public void setup() { MockitoAnnotations.initMocks(this); mFeatureFlagManager = new FeatureFlagManager(mSecureSettings, mContext, mDumpManager); mFeatureFlagManager = new FeatureFlagManager(mDumpManager); } @After public void onFinished() { // SecureSettings and Context are provided for constructor consistency with the // debug version of the FeatureFlagManager, but should never be used. verifyZeroInteractions(mSecureSettings, mContext); // The dump manager should be registered with even for the release version, but that's it. verify(mDumpManager).registerDumpable(anyString(), any()); verifyNoMoreInteractions(mDumpManager); Loading Loading
packages/SystemUI/shared/src/com/android/systemui/flags/FlagReader.kt +5 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,11 @@ package com.android.systemui.flags * Plugin for loading flag values */ interface FlagReader { /** Returns a boolean value for the given flag. */ fun isEnabled(flag: BooleanFlag): Boolean { return flag.default } /** Returns a boolean value for the given flag. */ fun isEnabled(id: Int, def: Boolean): Boolean { return def Loading
packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java +33 −6 Original line number Diff line number Diff line Loading @@ -26,13 +26,16 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.Bundle; import android.util.Log; import androidx.annotation.BoolRes; import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.settings.SecureSettings; Loading Loading @@ -62,14 +65,19 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { private final FlagManager mFlagManager; private final SecureSettings mSecureSettings; private final Resources mResources; private final Map<Integer, Boolean> mBooleanFlagCache = new HashMap<>(); @Inject public FeatureFlagManager(FlagManager flagManager, SecureSettings secureSettings, Context context, public FeatureFlagManager( FlagManager flagManager, Context context, SecureSettings secureSettings, @Main Resources resources, DumpManager dumpManager) { mFlagManager = flagManager; mSecureSettings = secureSettings; mResources = resources; IntentFilter filter = new IntentFilter(); filter.addAction(ACTION_SET_FLAG); filter.addAction(ACTION_GET_FLAGS); Loading @@ -77,17 +85,32 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { dumpManager.registerDumpable(TAG, this); } /** Return a {@link BooleanFlag}'s value. */ @Override public boolean isEnabled(int id, boolean defaultValue) { public boolean isEnabled(BooleanFlag flag) { int id = flag.getId(); if (!mBooleanFlagCache.containsKey(id)) { Boolean result = isEnabledInternal(id); mBooleanFlagCache.put(id, result == null ? defaultValue : result); boolean def = flag.getDefault(); if (flag.hasResourceOverride()) { try { def = isEnabledInOverlay(flag.getResourceOverride()); } catch (Resources.NotFoundException e) { // no-op } } mBooleanFlagCache.put(id, isEnabled(id, def)); } return mBooleanFlagCache.get(id); } /** Return a {@link BooleanFlag}'s value. */ @Override public boolean isEnabled(int id, boolean defaultValue) { Boolean result = isEnabledInternal(id); return result == null ? defaultValue : result; } /** Returns the stored value or null if not set. */ private Boolean isEnabledInternal(int id) { try { Loading @@ -98,6 +121,10 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { return null; } private boolean isEnabledInOverlay(@BoolRes int resId) { return mResources.getBoolean(resId); } /** Set whether a given {@link BooleanFlag} is enabled or not. */ @Override public void setEnabled(int id, boolean value) { Loading
packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java +6 −4 Original line number Diff line number Diff line Loading @@ -16,7 +16,6 @@ package com.android.systemui.flags; import android.content.Context; import android.util.SparseBooleanArray; import androidx.annotation.NonNull; Loading @@ -24,7 +23,6 @@ import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dump.DumpManager; import com.android.systemui.util.settings.SecureSettings; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -41,8 +39,7 @@ import javax.inject.Inject; public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { SparseBooleanArray mAccessedFlags = new SparseBooleanArray(); @Inject public FeatureFlagManager( SecureSettings secureSettings, Context context, DumpManager dumpManager) { public FeatureFlagManager(DumpManager dumpManager) { dumpManager.registerDumpable("SysUIFlags", this); } Loading @@ -52,6 +49,11 @@ public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable { @Override public void removeListener(Listener run) {} @Override public boolean isEnabled(BooleanFlag flag) { return isEnabled(flag.getId(), flag.getDefault()); } @Override public boolean isEnabled(int key, boolean defaultValue) { mAccessedFlags.append(key, defaultValue); Loading
packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java +2 −72 Original line number Diff line number Diff line Loading @@ -17,22 +17,11 @@ package com.android.systemui.flags; import android.content.Context; import android.content.res.Resources; import android.util.FeatureFlagUtils; import android.util.Log; import android.util.SparseArray; import android.widget.Toast; import androidx.annotation.BoolRes; import com.android.internal.annotations.VisibleForTesting; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; Loading @@ -43,31 +32,13 @@ import javax.inject.Inject; */ @SysUISingleton public class FeatureFlags { private final Resources mResources; private final FlagReader mFlagReader; private final Context mContext; private final Map<Integer, Flag<?>> mFlagMap = new HashMap<>(); private final Map<Integer, List<Listener>> mListeners = new HashMap<>(); private final SparseArray<Boolean> mCachedFlags = new SparseArray<>(); @Inject public FeatureFlags(@Main Resources resources, FlagReader flagReader, Context context) { mResources = resources; public FeatureFlags(FlagReader flagReader, Context context) { mFlagReader = flagReader; mContext = context; flagReader.addListener(mListener); } private final FlagReader.Listener mListener = id -> { if (mListeners.containsKey(id) && mFlagMap.containsKey(id)) { mListeners.get(id).forEach(listener -> listener.onFlagChanged(mFlagMap.get(id))); } }; @VisibleForTesting void addFlag(Flag<?> flag) { mFlagMap.put(flag.getId(), flag); } /** Loading @@ -75,32 +46,7 @@ public class FeatureFlags { * @return The value of the flag. */ public boolean isEnabled(BooleanFlag flag) { boolean def = flag.getDefault(); if (flag.hasResourceOverride()) { try { def = isEnabledInOverlay(flag.getResourceOverride()); } catch (Resources.NotFoundException e) { // no-op } } return mFlagReader.isEnabled(flag.getId(), def); } /** * @param flag The {@link IntFlag} of interest. /** Add a listener for a specific flag. */ public void addFlagListener(Flag<?> flag, Listener listener) { mListeners.putIfAbsent(flag.getId(), new ArrayList<>()); mListeners.get(flag.getId()).add(listener); mFlagMap.putIfAbsent(flag.getId(), flag); } /** Remove a listener for a specific flag. */ public void removeFlagListener(Flag<?> flag, Listener listener) { if (mListeners.containsKey(flag.getId())) { mListeners.get(flag.getId()).remove(listener); } return mFlagReader.isEnabled(flag); } public void assertLegacyPipelineEnabled() { Loading Loading @@ -205,20 +151,4 @@ public class FeatureFlags { public static boolean isProviderModelSettingEnabled(Context context) { return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL); } private boolean isEnabledInOverlay(@BoolRes int resId) { synchronized (mCachedFlags) { if (!mCachedFlags.contains(resId)) { mCachedFlags.put(resId, mResources.getBoolean(resId)); } return mCachedFlags.get(resId); } } /** Simple interface for beinga alerted when a specific flag changes value. */ public interface Listener { /** */ void onFlagChanged(Flag<?> flag); } }
packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java +1 −6 Original line number Diff line number Diff line Loading @@ -53,8 +53,6 @@ import java.io.StringWriter; public class FeatureFlagManagerTest extends SysuiTestCase { FeatureFlagManager mFeatureFlagManager; @Mock private FlagManager mFlagManager; @Mock private SecureSettings mSecureSettings; @Mock private Context mContext; @Mock private DumpManager mDumpManager; Loading @@ -62,14 +60,11 @@ public class FeatureFlagManagerTest extends SysuiTestCase { public void setup() { MockitoAnnotations.initMocks(this); mFeatureFlagManager = new FeatureFlagManager(mSecureSettings, mContext, mDumpManager); mFeatureFlagManager = new FeatureFlagManager(mDumpManager); } @After public void onFinished() { // SecureSettings and Context are provided for constructor consistency with the // debug version of the FeatureFlagManager, but should never be used. verifyZeroInteractions(mSecureSettings, mContext); // The dump manager should be registered with even for the release version, but that's it. verify(mDumpManager).registerDumpable(anyString(), any()); verifyNoMoreInteractions(mDumpManager); Loading