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
package com.android.settings;
import android.os.Bundle;
+import android.util.FeatureFlagUtils;
import com.android.settings.applications.AppOpsSummary;
import com.android.settings.enterprise.EnterprisePrivacySettings;
}
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 */ }
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;
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;
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;
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.
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;
PrivateVolumeSettings.class.getName(),
PublicVolumeSettings.class.getName(),
DevelopmentSettings.class.getName(),
+ DevelopmentSettingsDashboardFragment.class.getName(),
AndroidBeam.class.getName(),
WifiDisplaySettings.class.getName(),
PowerUsageSummary.class.getName(),
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;
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(),
/*
* 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 {
--- /dev/null
+/*
+ * 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);
+ }
+ };
+}
+com.android.settings.development.DevelopmentSettingsDashboardFragment
com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+}