diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c23b93ed34c..27a6abd3131 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3932,6 +3932,25 @@
android:value="true" />
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 77121a31f9b..3008965e79a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -11789,6 +11789,11 @@
Swipe up from a bottom corner to invoke digital assistant app.
+
+ Hold Home to invoke assistant
+
+ Press and hold the Home button to invoke digital assistant app.
+
Information
@@ -11811,9 +11816,15 @@
Gesture Navigation Sensitivity
+
+ Button navigation
+
gesture navigation, back sensitivity, back gesture
+
+ navigation, home button
+
Double-tap to check phone
diff --git a/res/xml/button_navigation_settings.xml b/res/xml/button_navigation_settings.xml
new file mode 100644
index 00000000000..d42f020d140
--- /dev/null
+++ b/res/xml/button_navigation_settings.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 231a1496421..4de795c41b5 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -243,6 +243,8 @@ public class Settings extends SettingsActivity {
public static class AutomaticStorageManagerSettingsActivity extends SettingsActivity { /* empty */ }
public static class GamesStorageActivity extends SettingsActivity { /* empty */ }
public static class GestureNavigationSettingsActivity extends SettingsActivity { /* empty */ }
+ /** Activity to manage 2-/3-button navigation configuration. */
+ public static class ButtonNavigationSettingsActivity extends SettingsActivity { /* empty */ }
public static class InteractAcrossProfilesSettingsActivity extends SettingsActivity {
/* empty */
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 1adf199fd39..3c594a714c0 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -94,6 +94,7 @@ import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleSettings;
import com.android.settings.fuelgauge.batterysaver.BatterySaverSettings;
import com.android.settings.gestures.AssistGestureSettings;
+import com.android.settings.gestures.ButtonNavigationSettingsFragment;
import com.android.settings.gestures.DoubleTapPowerSettings;
import com.android.settings.gestures.DoubleTapScreenSettings;
import com.android.settings.gestures.DoubleTwistGestureSettings;
@@ -312,6 +313,7 @@ public class SettingsGateway {
DarkModeSettingsFragment.class.getName(),
BugReportHandlerPicker.class.getName(),
GestureNavigationSettingsFragment.class.getName(),
+ ButtonNavigationSettingsFragment.class.getName(),
InteractAcrossProfilesSettings.class.getName(),
InteractAcrossProfilesDetails.class.getName(),
MediaControlsSettings.class.getName(),
diff --git a/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java b/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java
new file mode 100644
index 00000000000..6ecf7b119f7
--- /dev/null
+++ b/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java
@@ -0,0 +1,61 @@
+/*
+ * 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.settings.gestures;
+
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * Configures behaviour of long press home button to invoke assistant app gesture.
+ */
+public class ButtonNavigationSettingsAssistController extends TogglePreferenceController {
+
+ public ButtonNavigationSettingsAssistController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public boolean isChecked() {
+ boolean onByDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, onByDefault ? 1 : 0) == 1;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, isChecked ? 1 : 0);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (SystemNavigationPreferenceController.isOverlayPackageAvailable(mContext,
+ NAV_BAR_MODE_2BUTTON_OVERLAY)
+ || SystemNavigationPreferenceController.isOverlayPackageAvailable(mContext,
+ NAV_BAR_MODE_3BUTTON_OVERLAY)) {
+ return AVAILABLE;
+ }
+
+ return UNSUPPORTED_ON_DEVICE;
+ }
+}
diff --git a/src/com/android/settings/gestures/ButtonNavigationSettingsFragment.java b/src/com/android/settings/gestures/ButtonNavigationSettingsFragment.java
new file mode 100644
index 00000000000..af75e788c2b
--- /dev/null
+++ b/src/com/android/settings/gestures/ButtonNavigationSettingsFragment.java
@@ -0,0 +1,69 @@
+/*
+ * 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.settings.gestures;
+
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+/**
+ * A fragment that includes settings for 2- and 3-button navigation modes.
+ */
+@SearchIndexable(forTarget = SearchIndexable.MOBILE)
+public class ButtonNavigationSettingsFragment extends DashboardFragment {
+
+ private static final String TAG = "ButtonNavigationSettingsFragment";
+
+ public static final String BUTTON_NAVIGATION_SETTINGS =
+ "com.android.settings.BUTTON_NAVIGATION_SETTINGS";
+
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_BUTTON_NAV_DLG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.button_navigation_settings;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.button_navigation_settings) {
+
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return SystemNavigationPreferenceController.isOverlayPackageAvailable(context,
+ NAV_BAR_MODE_2BUTTON_OVERLAY)
+ || SystemNavigationPreferenceController.isOverlayPackageAvailable(
+ context,
+ NAV_BAR_MODE_3BUTTON_OVERLAY);
+ }
+ };
+}
diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
index 1ef8dec5abd..7f0d7c338d0 100644
--- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
+++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java
@@ -41,6 +41,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityGestureNavigationTutorial;
+import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -150,10 +151,19 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment i
pref.setSummary(((CandidateInfoExtra) info).loadSummary());
- if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL) {
+ if (KEY_SYSTEM_NAV_GESTURAL.equals(info.getKey())) {
pref.setExtraWidgetOnClickListener((v) -> startActivity(new Intent(
GestureNavigationSettingsFragment.GESTURE_NAVIGATION_SETTINGS)));
}
+
+ if (KEY_SYSTEM_NAV_2BUTTONS.equals(info.getKey()) || KEY_SYSTEM_NAV_3BUTTONS.equals(
+ info.getKey())) {
+ pref.setExtraWidgetOnClickListener((v) ->
+ new SubSettingLauncher(getContext())
+ .setDestination(ButtonNavigationSettingsFragment.class.getName())
+ .setSourceMetricsCategory(SettingsEnums.SETTINGS_GESTURE_SWIPE_UP)
+ .launch());
+ }
}
@Override
diff --git a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java
new file mode 100644
index 00000000000..d961cdf161d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.settings.gestures;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class ButtonNavigationSettingsAssistControllerTest {
+
+ private static final String KEY_LONG_PRESS_HOME_FOR_ASSIST =
+ "assistant_long_press_home_gesture";
+
+ private Context mContext;
+ private Resources mResources;
+ private ButtonNavigationSettingsAssistController mController;
+
+ @Before
+ public void setUp() {
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mResources = mock(Resources.class);
+ when(mContext.getResources()).thenReturn(mResources);
+
+ mController = new ButtonNavigationSettingsAssistController(
+ mContext, KEY_LONG_PRESS_HOME_FOR_ASSIST);
+ }
+
+ @Test
+ public void isChecked_valueUnknownDefaultTrue_shouldReturnTrue() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault)).thenReturn(
+ true);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_valueUnknownDefaultFalse_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault)).thenReturn(
+ true);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_valueTrue_shouldReturnTrue() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, 1);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_valueFalse_shouldReturnFalse() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, 0);
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void setChecked_valueFalse_shouldSetFalse() {
+ mController.setChecked(false);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, -1)).isEqualTo(0);
+ }
+
+ @Test
+ public void setChecked_valueTrue_shouldSetTrue() {
+ mController.setChecked(true);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, -1)).isEqualTo(1);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java
new file mode 100644
index 00000000000..b014076ed57
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsFragmentTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.settings.gestures;
+
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowPackageManager;
+
+@RunWith(RobolectricTestRunner.class)
+public class ButtonNavigationSettingsFragmentTest {
+
+ @Test
+ public void getNonIndexableKeys_twoAndThreeButtonNavigationNotAvailable_allKeysNonIndexable() {
+ assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+ ApplicationProvider.getApplicationContext())).isNotEmpty();
+ }
+
+ @Test
+ public void getNonIndexableKeys_twoButtonNavigationAvailable_allKeysIndexable() {
+ addPackageToPackageManager(ApplicationProvider.getApplicationContext(),
+ NAV_BAR_MODE_2BUTTON_OVERLAY);
+ assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+ ApplicationProvider.getApplicationContext())).isEmpty();
+ }
+
+ @Test
+ public void getNonIndexableKeys_threeButtonNavigationAvailable_allKeysIndexable() {
+ addPackageToPackageManager(ApplicationProvider.getApplicationContext(),
+ NAV_BAR_MODE_3BUTTON_OVERLAY);
+ assertThat(ButtonNavigationSettingsFragment.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(
+ ApplicationProvider.getApplicationContext())).isEmpty();
+ }
+
+ private static void addPackageToPackageManager(Context context, String pkg) {
+ ShadowPackageManager shadowPm = shadowOf(context.getPackageManager());
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = pkg;
+ shadowPm.installPackage(pi);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java
index fa97754491c..5637e961c4e 100644
--- a/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/LongPressPowerButtonPreferenceControllerTest.java
@@ -152,9 +152,6 @@ public class LongPressPowerButtonPreferenceControllerTest {
assertThat(Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.KEY_CHORD_POWER_VOLUME_UP, -1)).isEqualTo(
LongPressPowerButtonPreferenceController.KEY_CHORD_POWER_VOLUME_UP_GLOBAL_ACTIONS);
- verify(mController.mAssistSwitch).setSummary(
- getString(
- R.string.power_menu_summary_long_press_for_assist_enabled));
}
@Test