Merge "Add flag listeners." into sc-v2-dev am: 64eea77e08
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15405312 Change-Id: Iae2f9b70f5ef583b3e5077d28aff3d5c5f30bcc2
This commit is contained in:
@@ -56,4 +56,16 @@ public interface FlagReaderPlugin extends Plugin {
|
|||||||
default double getValue(int id, double def) {
|
default double getValue(int id, double def) {
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Add a listener to be alerted when any flag changes. */
|
||||||
|
default void addListener(Listener listener) {}
|
||||||
|
|
||||||
|
/** Remove a listener to be alerted when any flag changes. */
|
||||||
|
default void removeListener(Listener listener) {}
|
||||||
|
|
||||||
|
/** A simple listener to be alerted when a flag changes. */
|
||||||
|
interface Listener {
|
||||||
|
/** */
|
||||||
|
void onFlagChanged(int id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,6 +114,14 @@ public class FeatureFlagReader {
|
|||||||
return mPlugin.getValue(flag.getId(), flag.getDefault());
|
return mPlugin.getValue(flag.getId(), flag.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addListener(FlagReaderPlugin.Listener listener) {
|
||||||
|
mPlugin.addListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeListener(FlagReaderPlugin.Listener listener) {
|
||||||
|
mPlugin.removeListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the specified feature flag has been enabled.
|
* Returns true if the specified feature flag has been enabled.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ package com.android.systemui.flags;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.FeatureFlagUtils;
|
import android.util.FeatureFlagUtils;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
|
import com.android.systemui.plugins.FlagReaderPlugin;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -37,11 +40,26 @@ import javax.inject.Inject;
|
|||||||
public class FeatureFlags {
|
public class FeatureFlags {
|
||||||
private final FeatureFlagReader mFlagReader;
|
private final FeatureFlagReader mFlagReader;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
private final Map<Integer, Flag<?>> mFlagMap = new HashMap<>();
|
||||||
|
private final Map<Integer, List<Listener>> mListeners = new HashMap<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public FeatureFlags(FeatureFlagReader flagReader, Context context) {
|
public FeatureFlags(FeatureFlagReader flagReader, Context context) {
|
||||||
mFlagReader = flagReader;
|
mFlagReader = flagReader;
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
|
||||||
|
flagReader.addListener(mListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FlagReaderPlugin.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,6 +110,20 @@ public class FeatureFlags {
|
|||||||
return mFlagReader.getValue(flag);
|
return mFlagReader.getValue(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isNewNotifPipelineEnabled() {
|
public boolean isNewNotifPipelineEnabled() {
|
||||||
return mFlagReader.isEnabled(R.bool.flag_notification_pipeline2);
|
return mFlagReader.isEnabled(R.bool.flag_notification_pipeline2);
|
||||||
}
|
}
|
||||||
@@ -160,27 +192,6 @@ public class FeatureFlags {
|
|||||||
return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
|
return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Integer, Flag<?>> collectFlags() {
|
|
||||||
Map<Integer, Flag<?>> flags = new HashMap<>();
|
|
||||||
|
|
||||||
Field[] fields = this.getClass().getFields();
|
|
||||||
|
|
||||||
for (Field field : fields) {
|
|
||||||
Class<?> t = field.getType();
|
|
||||||
if (Flag.class.isAssignableFrom(t)) {
|
|
||||||
try {
|
|
||||||
//flags.add((Flag<?>) field.get(null));
|
|
||||||
Flag flag = (Flag) field.get(null);
|
|
||||||
flags.put(flag.getId(), flag);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
// no-op
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Simple interface for beinga alerted when a specific flag changes value. */
|
/** Simple interface for beinga alerted when a specific flag changes value. */
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
/** */
|
/** */
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.flags;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.plugins.FlagReaderPlugin;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
public class FeatureFlagsTest extends SysuiTestCase {
|
||||||
|
|
||||||
|
@Mock FeatureFlagReader mFeatureFlagReader;
|
||||||
|
|
||||||
|
private FeatureFlags mFeatureFlags;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
mFeatureFlags = new FeatureFlags(mFeatureFlagReader, getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddListener() {
|
||||||
|
Flag<?> flag = new BooleanFlag(1);
|
||||||
|
mFeatureFlags.addFlag(flag);
|
||||||
|
|
||||||
|
// Assert and capture that a plugin listener was added.
|
||||||
|
ArgumentCaptor<FlagReaderPlugin.Listener> pluginListenerCaptor =
|
||||||
|
ArgumentCaptor.forClass(FlagReaderPlugin.Listener.class);
|
||||||
|
|
||||||
|
verify(mFeatureFlagReader).addListener(pluginListenerCaptor.capture());
|
||||||
|
FlagReaderPlugin.Listener pluginListener = pluginListenerCaptor.getValue();
|
||||||
|
|
||||||
|
// Signal a change. No listeners, so no real effect.
|
||||||
|
pluginListener.onFlagChanged(flag.getId());
|
||||||
|
|
||||||
|
// Add a listener for the flag
|
||||||
|
final Flag<?>[] changedFlag = {null};
|
||||||
|
FeatureFlags.Listener listener = f -> changedFlag[0] = f;
|
||||||
|
mFeatureFlags.addFlagListener(flag, listener);
|
||||||
|
|
||||||
|
// No changes seen yet.
|
||||||
|
assertThat(changedFlag[0]).isNull();
|
||||||
|
|
||||||
|
// Signal a change.
|
||||||
|
pluginListener.onFlagChanged(flag.getId());
|
||||||
|
|
||||||
|
// Assert that the change was for the correct flag.
|
||||||
|
assertThat(changedFlag[0]).isEqualTo(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveListener() {
|
||||||
|
Flag<?> flag = new BooleanFlag(1);
|
||||||
|
mFeatureFlags.addFlag(flag);
|
||||||
|
|
||||||
|
// Assert and capture that a plugin listener was added.
|
||||||
|
ArgumentCaptor<FlagReaderPlugin.Listener> pluginListenerCaptor =
|
||||||
|
ArgumentCaptor.forClass(FlagReaderPlugin.Listener.class);
|
||||||
|
|
||||||
|
verify(mFeatureFlagReader).addListener(pluginListenerCaptor.capture());
|
||||||
|
FlagReaderPlugin.Listener pluginListener = pluginListenerCaptor.getValue();
|
||||||
|
|
||||||
|
// Add a listener for the flag
|
||||||
|
final Flag<?>[] changedFlag = {null};
|
||||||
|
FeatureFlags.Listener listener = f -> changedFlag[0] = f;
|
||||||
|
mFeatureFlags.addFlagListener(flag, listener);
|
||||||
|
|
||||||
|
// Signal a change.
|
||||||
|
pluginListener.onFlagChanged(flag.getId());
|
||||||
|
|
||||||
|
// Assert that the change was for the correct flag.
|
||||||
|
assertThat(changedFlag[0]).isEqualTo(flag);
|
||||||
|
|
||||||
|
changedFlag[0] = null;
|
||||||
|
|
||||||
|
// Now remove the listener.
|
||||||
|
mFeatureFlags.removeFlagListener(flag, listener);
|
||||||
|
// Signal a change.
|
||||||
|
pluginListener.onFlagChanged(flag.getId());
|
||||||
|
// Assert that the change was not triggered
|
||||||
|
assertThat(changedFlag[0]).isNull();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user