OSDN Git Service

Fork a new developer options page.
authorFan Zhang <zhfan@google.com>
Fri, 8 Sep 2017 22:29:54 +0000 (15:29 -0700)
committerFan Zhang <zhfan@google.com>
Sun, 10 Sep 2017 22:02:51 +0000 (15:02 -0700)
- Create a new activity/fragment and add it to manifest
- Mark old activity/fragment deprecated
- Enable/disable the new activity based on FeatureFlag
- Initial skeleton code for new fragment

Bug: 65522852
Test: make RunSettingsRoboTests -j40 ROBOTEST_FILTER=DevelopmentSettingsDashboardFragmentTest
Change-Id: Ib1395693f8b6f61d4726573a9ea841ea53cf207b

AndroidManifest.xml
src/com/android/settings/Settings.java
src/com/android/settings/SettingsActivity.java
src/com/android/settings/core/gateway/SettingsGateway.java
src/com/android/settings/dashboard/DashboardFragmentRegistry.java
src/com/android/settings/development/DevelopmentSettings.java
src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java [new file with mode: 0644]
tests/robotests/assets/grandfather_not_in_search_index_provider_registry
tests/robotests/src/android/util/FeatureFlagUtils.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java [new file with mode: 0644]

index 7702257..46c6490 100644 (file)
                 android:value="true" />
         </activity>
 
+        <activity android:name="Settings$DevelopmentSettingsDashboardActivity"
+                  android:label="@string/development_settings_title"
+                  android:icon="@drawable/ic_settings_development"
+                  android:taskAffinity="com.android.settings"
+                  android:parentActivityName="Settings">
+
+            <!-- Enable when deleting DevelopmentSettingsActivity
+            <intent-filter android:priority="1">
+                <action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
+                <action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            -->
+            <intent-filter android:priority="50">
+                <action android:name="com.android.settings.action.SETTINGS" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.category"
+                       android:value="com.android.settings.category.ia.system" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/summary_empty"/>
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.development.DevelopmentSettingsDashboardFragment" />
+            <meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
+                       android:value="true" />
+        </activity>
+
         <!-- The opposite of DevelopmentSettingsActivity, it's no-op and only enabled when the real
              activity is disabled to be CTS compliant. -->
         <activity
index 1ec4284..cd479a5 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.settings;
 
 import android.os.Bundle;
+import android.util.FeatureFlagUtils;
 
 import com.android.settings.applications.AppOpsSummary;
 import com.android.settings.enterprise.EnterprisePrivacySettings;
@@ -70,7 +71,17 @@ public class Settings extends SettingsActivity {
     }
     public static class BackgroundCheckSummaryActivity extends SettingsActivity { /* empty */ }
     public static class StorageUseActivity extends SettingsActivity { /* empty */ }
+
+    /**
+     * @deprecated in favor of {@link DevelopmentSettingsDashboardActivity}.
+     */
+    @Deprecated
     public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ }
+    public static class DevelopmentSettingsDashboardActivity extends SettingsActivity {
+        public static final boolean isEnabled() {
+            return FeatureFlagUtils.isEnabled("dev_option_v2");
+        }
+    }
     public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ }
     public static class CaptioningSettingsActivity extends SettingsActivity { /* empty */ }
     public static class AccessibilityInversionSettingsActivity extends SettingsActivity { /* empty */ }
index f9b849e..c927889 100644 (file)
@@ -50,6 +50,7 @@ import android.view.View.OnClickListener;
 import android.view.ViewGroup;
 import android.widget.Button;
 import android.widget.Toolbar;
+
 import com.android.internal.util.ArrayUtils;
 import com.android.settings.Settings.WifiSettingsActivity;
 import com.android.settings.backup.BackupSettingsActivity;
@@ -58,7 +59,6 @@ import com.android.settings.core.instrumentation.MetricsFeatureProvider;
 import com.android.settings.core.instrumentation.SharedPreferencesLogger;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.DashboardSummary;
-import com.android.settings.development.DevelopmentSettings;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.SearchActivity;
 import com.android.settings.wfd.WifiDisplaySettings;
@@ -66,6 +66,7 @@ import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.drawer.DashboardCategory;
 import com.android.settingslib.drawer.SettingsDrawerActivity;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -831,9 +832,16 @@ public class SettingsActivity extends SettingsDrawerActivity
 
         final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
                 && !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
+        final boolean useDevOptionV2 = Settings.DevelopmentSettingsDashboardActivity.isEnabled();
+        // Enable old Dev option if v2 is disabled
         somethingChanged = setTileEnabled(new ComponentName(packageName,
                         Settings.DevelopmentSettingsActivity.class.getName()),
-                showDev, isAdmin)
+                showDev && !useDevOptionV2, isAdmin)
+                || somethingChanged;
+        // Enable new Dev option if v2 is enable
+        somethingChanged = setTileEnabled(new ComponentName(packageName,
+                        Settings.DevelopmentSettingsDashboardActivity.class.getName()),
+                showDev && useDevOptionV2, isAdmin)
                 || somethingChanged;
 
         // Enable/disable backup settings depending on whether the user is admin.
index a03314c..884696c 100644 (file)
@@ -66,6 +66,7 @@ import com.android.settings.datausage.DataUsageList;
 import com.android.settings.datausage.DataUsageSummary;
 import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
 import com.android.settings.development.DevelopmentSettings;
+import com.android.settings.development.DevelopmentSettingsDashboardFragment;
 import com.android.settings.deviceinfo.ImeiInformation;
 import com.android.settings.deviceinfo.PrivateVolumeForget;
 import com.android.settings.deviceinfo.PrivateVolumeSettings;
@@ -177,6 +178,7 @@ public class SettingsGateway {
             PrivateVolumeSettings.class.getName(),
             PublicVolumeSettings.class.getName(),
             DevelopmentSettings.class.getName(),
+            DevelopmentSettingsDashboardFragment.class.getName(),
             AndroidBeam.class.getName(),
             WifiDisplaySettings.class.getName(),
             PowerUsageSummary.class.getName(),
index fddd522..17e556e 100644 (file)
@@ -20,12 +20,14 @@ import android.util.ArrayMap;
 
 import com.android.settings.DisplaySettings;
 import com.android.settings.SecuritySettings;
+import com.android.settings.Settings;
 import com.android.settings.accounts.AccountDetailDashboardFragment;
 import com.android.settings.accounts.UserAndAccountDashboardFragment;
 import com.android.settings.applications.AppAndNotificationDashboardFragment;
 import com.android.settings.applications.DefaultAppSettings;
 import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
 import com.android.settings.development.DevelopmentSettings;
+import com.android.settings.development.DevelopmentSettingsDashboardFragment;
 import com.android.settings.deviceinfo.StorageDashboardFragment;
 import com.android.settings.fuelgauge.PowerUsageSummary;
 import com.android.settings.language.LanguageAndInputSettings;
@@ -83,8 +85,13 @@ public class DashboardFragmentRegistry {
                 SystemDashboardFragment.class.getName(), CategoryKey.CATEGORY_SYSTEM);
         PARENT_TO_CATEGORY_KEY_MAP.put(LanguageAndInputSettings.class.getName(),
                 CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
-        PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
-                CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
+        if (Settings.DevelopmentSettingsDashboardActivity.isEnabled()) {
+            PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettingsDashboardFragment.class.getName(),
+                    CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
+        } else {
+            PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
+                    CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
+        }
         PARENT_TO_CATEGORY_KEY_MAP.put(ConfigureNotificationSettings.class.getName(),
                 CategoryKey.CATEGORY_NOTIFICATIONS);
         PARENT_TO_CATEGORY_KEY_MAP.put(LockscreenDashboardFragment.class.getName(),
index 3ee1295..18fe084 100644 (file)
@@ -109,7 +109,9 @@ import java.util.List;
 
 /*
  * Displays preferences for application developers.
+ * @deprecated in favor of {@link DevelopmentSettingsDashboardFragment}
  */
+@Deprecated
 public class DevelopmentSettings extends RestrictedSettingsFragment
         implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener,
         OnPreferenceChangeListener, SwitchBar.OnSwitchChangeListener, Indexable {
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
new file mode 100644 (file)
index 0000000..30be654
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.provider.SearchIndexableResource;
+import android.util.Log;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.widget.SwitchBar;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFragment {
+
+    private static final String TAG = "DevSettingsDashboard";
+
+    private SwitchBar mSwitchBar;
+
+    public DevelopmentSettingsDashboardFragment() {
+        super(UserManager.DISALLOW_DEBUGGING_FEATURES);
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsProto.MetricsEvent.DEVELOPMENT;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    protected int getHelpResource() {
+        return 0;
+    }
+
+    @Override
+    protected int getPreferenceScreenResId() {
+        Log.d(TAG, "Creating pref screen");
+        return R.xml.development_prefs;
+    }
+
+    @Override
+    protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
+        return buildPreferenceControllers(context);
+    }
+
+    private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
+        return null;
+    }
+
+    /**
+     * For Search.
+     */
+    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+            new BaseSearchIndexProvider() {
+
+                @Override
+                protected boolean isPageSearchEnabled(Context context) {
+                    return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
+                }
+
+                @Override
+                public List<SearchIndexableResource> getXmlResourcesToIndex(
+                        Context context, boolean enabled) {
+
+                    final SearchIndexableResource sir = new SearchIndexableResource(context);
+                    sir.xmlResId = R.xml.development_prefs;
+                    return Arrays.asList(sir);
+                }
+
+                @Override
+                public List<AbstractPreferenceController> getPreferenceControllers(Context
+                        context) {
+                    return buildPreferenceControllers(context);
+                }
+            };
+}
diff --git a/tests/robotests/src/android/util/FeatureFlagUtils.java b/tests/robotests/src/android/util/FeatureFlagUtils.java
new file mode 100644 (file)
index 0000000..6bc0557
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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 android.util;
+
+import android.os.SystemProperties;
+import android.text.TextUtils;
+
+/**
+ * This class is only needed to get around Robolectric issue.
+ */
+public class FeatureFlagUtils {
+    public static final String FFLAG_PREFIX = "sys.fflag.";
+    public static final String FFLAG_OVERRIDE_PREFIX = FFLAG_PREFIX + "override.";
+
+    /**
+     * Whether or not a flag is enabled.
+     *
+     * @param feature the flag name
+     * @return true if the flag is enabled (either by default in system, or override by user)
+     */
+    public static boolean isEnabled(String feature) {
+        // Tries to get feature flag from system property.
+        // Step 1: check if feature flag has any override. Flag name: sys.fflag.override.<feature>
+        String value = SystemProperties.get(FFLAG_OVERRIDE_PREFIX + feature);
+        if (!TextUtils.isEmpty(value)) {
+            return Boolean.parseBoolean(value);
+        }
+        // Step 2: check if feature flag has any default value. Flag name: sys.fflag.<feature>
+        value = SystemProperties.get(FFLAG_PREFIX + feature);
+        return Boolean.parseBoolean(value);
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
new file mode 100644 (file)
index 0000000..04ff721
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+        shadows = {
+                SettingsShadowResources.class,
+                SettingsShadowResources.SettingsShadowTheme.class
+        })
+public class DevelopmentSettingsDashboardFragmentTest {
+
+    private DevelopmentSettingsDashboardFragment mDashboard;
+
+    @Before
+    public void setUp() {
+        mDashboard = new DevelopmentSettingsDashboardFragment();
+    }
+
+    @Test
+    public void shouldNotHaveHelpResource() {
+        assertThat(mDashboard.getHelpResource()).isEqualTo(0);
+    }
+
+    @Test
+    public void shouldLogAsFeatureFlagPage() {
+        assertThat(mDashboard.getMetricsCategory())
+                .isEqualTo(MetricsProto.MetricsEvent.DEVELOPMENT);
+    }
+
+    @Test
+    public void searchIndex_shouldIndexFromPrefXml() {
+        final List<SearchIndexableResource> index =
+                DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getXmlResourcesToIndex(RuntimeEnvironment.application, true);
+
+        assertThat(index.size()).isEqualTo(1);
+        assertThat(index.get(0).xmlResId).isEqualTo(R.xml.development_prefs);
+    }
+
+    @Test
+    public void searchIndex_pageDisabled_shouldAddAllKeysToNonIndexable() {
+        final Context appContext = RuntimeEnvironment.application;
+        DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, false);
+
+        final List<String> nonIndexableKeys =
+                DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getNonIndexableKeys(appContext);
+
+        assertThat(nonIndexableKeys).contains("development_prefs_screen");
+    }
+
+    @Test
+    public void searchIndex_pageEnabled_shouldNotAddKeysToNonIndexable() {
+        final Context appContext = RuntimeEnvironment.application;
+        DevelopmentSettingsEnabler.setDevelopmentSettingsEnabled(appContext, true);
+
+        final List<String> nonIndexableKeys =
+                DevelopmentSettingsDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
+                        .getNonIndexableKeys(appContext);
+
+        assertThat(nonIndexableKeys).doesNotContain("development_prefs_screen");
+    }
+}