Loading src/com/android/settings/development/featureflags/FeatureFlagPreference.java 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.development.featureflags; import android.content.Context; import android.support.v14.preference.SwitchPreference; import android.util.FeatureFlagUtils; public class FeatureFlagPreference extends SwitchPreference { private final String mKey; public FeatureFlagPreference(Context context, String key) { super(context); mKey = key; setKey(key); setTitle(key); setCheckedInternal(FeatureFlagUtils.isEnabled(mKey)); } @Override public void setChecked(boolean isChecked) { setCheckedInternal(isChecked); FeatureFlagUtils.setEnabled(mKey, isChecked); } private void setCheckedInternal(boolean isChecked) { super.setChecked(isChecked); setSummary(Boolean.toString(isChecked)); } } src/com/android/settings/development/featureflags/FeatureFlagsDashboard.java +4 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settingslib.core.AbstractPreferenceController; import java.util.ArrayList; import java.util.List; public class FeatureFlagsDashboard extends DashboardFragment { Loading Loading @@ -51,6 +52,8 @@ public class FeatureFlagsDashboard extends DashboardFragment { @Override protected List<AbstractPreferenceController> getPreferenceControllers(Context context) { return null; final List<AbstractPreferenceController> controllers = new ArrayList<>(); controllers.add(new FeatureFlagsPreferenceController(context, getLifecycle())); return controllers; } } src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.development.featureflags; import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.util.FeatureFlagUtils; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import java.util.Map; public class FeatureFlagsPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver, OnStart { private PreferenceScreen mScreen; public FeatureFlagsPreferenceController(Context context, Lifecycle lifecycle) { super(context); if (lifecycle != null) { lifecycle.addObserver(this); } } @Override public boolean isAvailable() { return true; } @Override public String getPreferenceKey() { return null; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mScreen = screen; } @Override public void onStart() { if (mScreen == null) { return; } final Map<String, String> featureMap = FeatureFlagUtils.getAllFeatureFlags(); if (featureMap == null) { return; } mScreen.removeAll(); final Context prefContext = mScreen.getContext(); for (String prefixedFeature : featureMap.keySet()) { if (prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_PREFIX) && !prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX)) { final String feature = prefixedFeature.substring( FeatureFlagUtils.FFLAG_PREFIX.length()); final Preference pref = new FeatureFlagPreference(prefContext, feature); mScreen.addPreference(pref); } } } } tests/robotests/src/android/util/FeatureFlagUtils.java +18 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package android.util; import android.os.SystemProperties; import android.text.TextUtils; import java.util.HashMap; import java.util.Map; /** * This class is only needed to get around Robolectric issue. */ Loading @@ -43,4 +46,19 @@ public class FeatureFlagUtils { value = SystemProperties.get(FFLAG_PREFIX + feature); return Boolean.parseBoolean(value); } /** * Override feature flag to new state. */ public static void setEnabled(String feature, boolean enabled) { SystemProperties.set(FFLAG_OVERRIDE_PREFIX + feature, enabled ? "true" : "false"); } public static Map<String, String> getAllFeatureFlags() { final Map<String, String> features = new HashMap<>(); features.put(FFLAG_PREFIX + "abc", "false"); features.put(FFLAG_OVERRIDE_PREFIX + "abc", "true"); return features; } } tests/robotests/src/com/android/settings/development/featureflags/FeatureFlagPreferenceControllerTest.java 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.development.featureflags; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.support.v7.preference.PreferenceScreen; import com.android.settings.TestConfig; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class FeatureFlagPreferenceControllerTest { @Mock private PreferenceScreen mScreen; private Context mContext; private Lifecycle mLifecycle; private FeatureFlagsPreferenceController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mLifecycle = new Lifecycle(); mController = new FeatureFlagsPreferenceController(mContext, mLifecycle); when(mScreen.getContext()).thenReturn(mContext); mController.displayPreference(mScreen); } @Test public void verifyConstants() { assertThat(mController.isAvailable()).isTrue(); assertThat(mController.getPreferenceKey()).isNull(); } @Test public void onStart_shouldRefreshFeatureFlags() { mLifecycle.onStart(); verify(mScreen).removeAll(); verify(mScreen).addPreference(any(FeatureFlagPreference.class)); } } Loading
src/com/android/settings/development/featureflags/FeatureFlagPreference.java 0 → 100644 +45 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.development.featureflags; import android.content.Context; import android.support.v14.preference.SwitchPreference; import android.util.FeatureFlagUtils; public class FeatureFlagPreference extends SwitchPreference { private final String mKey; public FeatureFlagPreference(Context context, String key) { super(context); mKey = key; setKey(key); setTitle(key); setCheckedInternal(FeatureFlagUtils.isEnabled(mKey)); } @Override public void setChecked(boolean isChecked) { setCheckedInternal(isChecked); FeatureFlagUtils.setEnabled(mKey, isChecked); } private void setCheckedInternal(boolean isChecked) { super.setChecked(isChecked); setSummary(Boolean.toString(isChecked)); } }
src/com/android/settings/development/featureflags/FeatureFlagsDashboard.java +4 −1 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settingslib.core.AbstractPreferenceController; import java.util.ArrayList; import java.util.List; public class FeatureFlagsDashboard extends DashboardFragment { Loading Loading @@ -51,6 +52,8 @@ public class FeatureFlagsDashboard extends DashboardFragment { @Override protected List<AbstractPreferenceController> getPreferenceControllers(Context context) { return null; final List<AbstractPreferenceController> controllers = new ArrayList<>(); controllers.add(new FeatureFlagsPreferenceController(context, getLifecycle())); return controllers; } }
src/com/android/settings/development/featureflags/FeatureFlagsPreferenceController.java 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.development.featureflags; import android.content.Context; import android.support.v7.preference.Preference; import android.support.v7.preference.PreferenceScreen; import android.util.FeatureFlagUtils; import com.android.settings.core.PreferenceControllerMixin; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import java.util.Map; public class FeatureFlagsPreferenceController extends AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver, OnStart { private PreferenceScreen mScreen; public FeatureFlagsPreferenceController(Context context, Lifecycle lifecycle) { super(context); if (lifecycle != null) { lifecycle.addObserver(this); } } @Override public boolean isAvailable() { return true; } @Override public String getPreferenceKey() { return null; } @Override public void displayPreference(PreferenceScreen screen) { super.displayPreference(screen); mScreen = screen; } @Override public void onStart() { if (mScreen == null) { return; } final Map<String, String> featureMap = FeatureFlagUtils.getAllFeatureFlags(); if (featureMap == null) { return; } mScreen.removeAll(); final Context prefContext = mScreen.getContext(); for (String prefixedFeature : featureMap.keySet()) { if (prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_PREFIX) && !prefixedFeature.startsWith(FeatureFlagUtils.FFLAG_OVERRIDE_PREFIX)) { final String feature = prefixedFeature.substring( FeatureFlagUtils.FFLAG_PREFIX.length()); final Preference pref = new FeatureFlagPreference(prefContext, feature); mScreen.addPreference(pref); } } } }
tests/robotests/src/android/util/FeatureFlagUtils.java +18 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,9 @@ package android.util; import android.os.SystemProperties; import android.text.TextUtils; import java.util.HashMap; import java.util.Map; /** * This class is only needed to get around Robolectric issue. */ Loading @@ -43,4 +46,19 @@ public class FeatureFlagUtils { value = SystemProperties.get(FFLAG_PREFIX + feature); return Boolean.parseBoolean(value); } /** * Override feature flag to new state. */ public static void setEnabled(String feature, boolean enabled) { SystemProperties.set(FFLAG_OVERRIDE_PREFIX + feature, enabled ? "true" : "false"); } public static Map<String, String> getAllFeatureFlags() { final Map<String, String> features = new HashMap<>(); features.put(FFLAG_PREFIX + "abc", "false"); features.put(FFLAG_OVERRIDE_PREFIX + "abc", "true"); return features; } }
tests/robotests/src/com/android/settings/development/featureflags/FeatureFlagPreferenceControllerTest.java 0 → 100644 +72 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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.settings.development.featureflags; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; import android.support.v7.preference.PreferenceScreen; import com.android.settings.TestConfig; import com.android.settings.testutils.SettingsRobolectricTestRunner; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @RunWith(SettingsRobolectricTestRunner.class) @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) public class FeatureFlagPreferenceControllerTest { @Mock private PreferenceScreen mScreen; private Context mContext; private Lifecycle mLifecycle; private FeatureFlagsPreferenceController mController; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = RuntimeEnvironment.application; mLifecycle = new Lifecycle(); mController = new FeatureFlagsPreferenceController(mContext, mLifecycle); when(mScreen.getContext()).thenReturn(mContext); mController.displayPreference(mScreen); } @Test public void verifyConstants() { assertThat(mController.isAvailable()).isTrue(); assertThat(mController.getPreferenceKey()).isNull(); } @Test public void onStart_shouldRefreshFeatureFlags() { mLifecycle.onStart(); verify(mScreen).removeAll(); verify(mScreen).addPreference(any(FeatureFlagPreference.class)); } }