Allows for system navigation settings to be added dynamically.
This allows for controller-backed preferences to be added or overridden via xml. Similarly, if the controllers cause all of the preferences for 2 or 3 button nav to be unavailable, we hide the settings button. Bug: 324036308 Test: Manual and unit tests Flag: NA Change-Id: I2371f3173076172489966728ac69c8767570cd56 Merged-In: I2371f3173076172489966728ac69c8767570cd56
This commit is contained in:
@@ -10478,7 +10478,7 @@
|
|||||||
<string name="back_sensitivity_dialog_title">Back Sensitivity</string>
|
<string name="back_sensitivity_dialog_title">Back Sensitivity</string>
|
||||||
|
|
||||||
<!-- Title for the screen to show all the gesture navigation settings [CHAR LIMIT=80] -->
|
<!-- Title for the screen to show all the gesture navigation settings [CHAR LIMIT=80] -->
|
||||||
<string name="gesture_settings_activity_title">Gesture Navigation Sensitivity</string>
|
<string name="gesture_settings_activity_title">Gesture Navigation</string>
|
||||||
|
|
||||||
<!-- Title for the screen to show all the 2- and 3-button navigation settings. [CHAR LIMIT=80] -->
|
<!-- Title for the screen to show all the 2- and 3-button navigation settings. [CHAR LIMIT=80] -->
|
||||||
<string name="button_navigation_settings_activity_title">Button navigation</string>
|
<string name="button_navigation_settings_activity_title">Button navigation</string>
|
||||||
|
@@ -27,6 +27,8 @@ import android.text.TextUtils;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
|
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
@@ -93,6 +95,25 @@ public class PreferenceControllerListHelper {
|
|||||||
return controllers;
|
return controllers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given PreferenceScreen will be empty due to all preferences being unavailable.
|
||||||
|
*
|
||||||
|
* @param xmlResId resource id of the PreferenceScreen to check
|
||||||
|
* @return {@code true} if none of the preferences in the given screen will appear
|
||||||
|
*/
|
||||||
|
public static boolean areAllPreferencesUnavailable(@NonNull Context context,
|
||||||
|
@NonNull PreferenceManager preferenceManager, @XmlRes int xmlResId) {
|
||||||
|
PreferenceScreen screen = preferenceManager.inflateFromResource(context, xmlResId,
|
||||||
|
/* rootPreferences= */ null);
|
||||||
|
List<BasePreferenceController> preferenceControllers =
|
||||||
|
getPreferenceControllersFromXml(context, xmlResId);
|
||||||
|
if (screen.getPreferenceCount() != preferenceControllers.size()) {
|
||||||
|
// There are some preferences without controllers, which will show regardless.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return preferenceControllers.stream().noneMatch(BasePreferenceController::isAvailable);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a sub list of {@link AbstractPreferenceController} to only contain controller that
|
* Return a sub list of {@link AbstractPreferenceController} to only contain controller that
|
||||||
* doesn't exist in filter.
|
* doesn't exist in filter.
|
||||||
|
@@ -43,6 +43,8 @@ import androidx.preference.PreferenceScreen;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.accessibility.AccessibilityGestureNavigationTutorial;
|
import com.android.settings.accessibility.AccessibilityGestureNavigationTutorial;
|
||||||
|
import com.android.settings.core.BasePreferenceController;
|
||||||
|
import com.android.settings.core.PreferenceControllerListHelper;
|
||||||
import com.android.settings.core.SubSettingLauncher;
|
import com.android.settings.core.SubSettingLauncher;
|
||||||
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
@@ -147,14 +149,20 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment i
|
|||||||
final PreferenceScreen screen = getPreferenceScreen();
|
final PreferenceScreen screen = getPreferenceScreen();
|
||||||
screen.removeAll();
|
screen.removeAll();
|
||||||
screen.addPreference(mVideoPreference);
|
screen.addPreference(mVideoPreference);
|
||||||
|
addPreferencesFromResource(getPreferenceScreenResId());
|
||||||
|
final List<BasePreferenceController> preferenceControllers = PreferenceControllerListHelper
|
||||||
|
.getPreferenceControllersFromXml(getContext(), getPreferenceScreenResId());
|
||||||
|
preferenceControllers.forEach(controller -> {
|
||||||
|
controller.updateState(findPreference(controller.getPreferenceKey()));
|
||||||
|
controller.displayPreference(screen);
|
||||||
|
});
|
||||||
|
|
||||||
final List<? extends CandidateInfo> candidateList = getCandidates();
|
final List<? extends CandidateInfo> candidateList = getCandidates();
|
||||||
if (candidateList == null) {
|
if (candidateList == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (CandidateInfo info : candidateList) {
|
for (CandidateInfo info : candidateList) {
|
||||||
SelectorWithWidgetPreference pref =
|
SelectorWithWidgetPreference pref = new SelectorWithWidgetPreference(getPrefContext());
|
||||||
new SelectorWithWidgetPreference(getPrefContext());
|
|
||||||
bindPreference(pref, info.getKey(), info, defaultKey);
|
bindPreference(pref, info.getKey(), info, defaultKey);
|
||||||
bindPreferenceExtra(pref, info.getKey(), info, defaultKey, systemDefaultKey);
|
bindPreferenceExtra(pref, info.getKey(), info, defaultKey, systemDefaultKey);
|
||||||
screen.addPreference(pref);
|
screen.addPreference(pref);
|
||||||
@@ -176,8 +184,11 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment i
|
|||||||
GestureNavigationSettingsFragment.GESTURE_NAVIGATION_SETTINGS)));
|
GestureNavigationSettingsFragment.GESTURE_NAVIGATION_SETTINGS)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (KEY_SYSTEM_NAV_2BUTTONS.equals(info.getKey()) || KEY_SYSTEM_NAV_3BUTTONS.equals(
|
if ((KEY_SYSTEM_NAV_2BUTTONS.equals(info.getKey())
|
||||||
info.getKey())) {
|
|| KEY_SYSTEM_NAV_3BUTTONS.equals(info.getKey()))
|
||||||
|
// Don't add the settings button if that page will be blank.
|
||||||
|
&& !PreferenceControllerListHelper.areAllPreferencesUnavailable(
|
||||||
|
getContext(), getPreferenceManager(), R.xml.button_navigation_settings)) {
|
||||||
pref.setExtraWidgetOnClickListener((v) ->
|
pref.setExtraWidgetOnClickListener((v) ->
|
||||||
new SubSettingLauncher(getContext())
|
new SubSettingLauncher(getContext())
|
||||||
.setDestination(ButtonNavigationSettingsFragment.class.getName())
|
.setDestination(ButtonNavigationSettingsFragment.class.getName())
|
||||||
|
36
tests/robotests/res/xml-mcc997/location_settings.xml
Normal file
36
tests/robotests/res/xml-mcc997/location_settings.xml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2024 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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:key="fake_title_key"
|
||||||
|
android:title="screen_title">
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="key1"
|
||||||
|
android:title="title"
|
||||||
|
android:icon="@drawable/ic_android"
|
||||||
|
android:summary="summary1"
|
||||||
|
settings:controller="com.android.settings.core.UnavailablePreferenceController"/>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="key2"
|
||||||
|
android:title="title"
|
||||||
|
android:icon="@drawable/ic_android"
|
||||||
|
android:summary="summary2"
|
||||||
|
settings:controller="com.android.settings.core.UnavailablePreferenceController"/>
|
||||||
|
|
||||||
|
</PreferenceScreen>
|
@@ -20,6 +20,8 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.slices.FakePreferenceController;
|
import com.android.settings.slices.FakePreferenceController;
|
||||||
import com.android.settingslib.core.AbstractPreferenceController;
|
import com.android.settingslib.core.AbstractPreferenceController;
|
||||||
@@ -38,10 +40,12 @@ import java.util.List;
|
|||||||
public class PreferenceControllerListHelperTest {
|
public class PreferenceControllerListHelperTest {
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
private PreferenceManager mPreferenceManager;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = RuntimeEnvironment.application;
|
mContext = RuntimeEnvironment.application;
|
||||||
|
mPreferenceManager = new PreferenceManager(mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -68,6 +72,30 @@ public class PreferenceControllerListHelperTest {
|
|||||||
assertThat(controllers.get(0)).isInstanceOf(FakePreferenceController.class);
|
assertThat(controllers.get(0)).isInstanceOf(FakePreferenceController.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(qualifiers = "mcc999")
|
||||||
|
public void areAllPreferencesUnavailable_allAvailable() {
|
||||||
|
// All preferences have controllers indicating they are available.
|
||||||
|
assertThat(PreferenceControllerListHelper.areAllPreferencesUnavailable(mContext,
|
||||||
|
mPreferenceManager, R.xml.location_settings)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(qualifiers = "mcc997")
|
||||||
|
public void areAllPreferencesUnavailable_allUnavailable() {
|
||||||
|
// All preferences have controllers indicating they are unavailable. (note the qualifier)
|
||||||
|
assertThat(PreferenceControllerListHelper.areAllPreferencesUnavailable(mContext,
|
||||||
|
mPreferenceManager, R.xml.location_settings)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(qualifiers = "mcc999")
|
||||||
|
public void areAllPreferencesUnavailable_noControllersShouldAssumeAvailable() {
|
||||||
|
// None of the preferences have controllers, so they are assumed available.
|
||||||
|
assertThat(PreferenceControllerListHelper.areAllPreferencesUnavailable(mContext,
|
||||||
|
mPreferenceManager, R.xml.display_settings)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void filterControllers_noFilter_shouldReturnSameList() {
|
public void filterControllers_noFilter_shouldReturnSameList() {
|
||||||
final List<BasePreferenceController> controllers = new ArrayList<>();
|
final List<BasePreferenceController> controllers = new ArrayList<>();
|
||||||
|
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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.core;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
public class UnavailablePreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
|
public UnavailablePreferenceController(Context context, String preferenceKey) {
|
||||||
|
super(context, preferenceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvailabilityStatus() {
|
||||||
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user