Adds Edge to Edge option in gesture settings page

Bug: 125489141
Test: Manual test on device
Test: make RunSettingsRoboTests ROBOTEST_FILTER=SystemNavigationLegacyPreferenceControllerTest
Test: make RunSettingsRoboTests ROBOTEST_FILTER=SystemNavigationSwipeUpPreferenceControllerTest
Test: make RunSettingsRoboTests ROBOTEST_FILTER=SystemNavigationEdgeToEdgePreferenceControllerTest
Change-Id: I1b274cc053de8235d0c664150cabe5dadc618419
This commit is contained in:
Mehdi Alizadeh
2019-02-27 15:24:48 -08:00
parent 1795e0323c
commit 43502549a3
13 changed files with 788 additions and 135 deletions

View File

@@ -9795,8 +9795,11 @@
<!-- Title for settings suggestion for double twist for camera [CHAR LIMIT=60] --> <!-- Title for settings suggestion for double twist for camera [CHAR LIMIT=60] -->
<string name="double_twist_for_camera_suggestion_title">Take selfies faster</string> <string name="double_twist_for_camera_suggestion_title">Take selfies faster</string>
<!-- Title text for swipe up to switch apps [CHAR LIMIT=60] --> <!-- Title text for system navigation [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
<string name="swipe_up_to_switch_apps_title">Swipe up on Home button</string> <string name="system_navigation_title" translatable="false">System navigation</string>
<!-- Title text for swipe up to switch apps [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
<string name="swipe_up_to_switch_apps_title" translatable="false">2-button navigation</string>
<!-- Summary text for swipe up to switch apps [CHAR LIMIT=250] --> <!-- Summary text for swipe up to switch apps [CHAR LIMIT=250] -->
<string name="swipe_up_to_switch_apps_summary">To switch apps, swipe up on the Home button. Swipe up again to see all apps. Works from any screen. Youll no longer have an Overview button on the bottom right of your screen.</string> <string name="swipe_up_to_switch_apps_summary">To switch apps, swipe up on the Home button. Swipe up again to see all apps. Works from any screen. Youll no longer have an Overview button on the bottom right of your screen.</string>
<!-- Title for settings suggestion for swipe up to switch apps [CHAR LIMIT=60] --> <!-- Title for settings suggestion for swipe up to switch apps [CHAR LIMIT=60] -->
@@ -9804,6 +9807,16 @@
<!-- Summary for settings suggestion for swipe up to switch apps [CHAR LIMIT=60] --> <!-- Summary for settings suggestion for swipe up to switch apps [CHAR LIMIT=60] -->
<string name="swipe_up_to_switch_apps_suggestion_summary">Turn on the new gesture to switch apps</string> <string name="swipe_up_to_switch_apps_suggestion_summary">Turn on the new gesture to switch apps</string>
<!-- Title text for edge to edge navigation [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
<string name="edge_to_edge_navigation_title" translatable="false">Fully gestural navigation</string>
<!-- Summary text for edge to edge navigation [CHAR LIMIT=None] [DO NOT TRANSLATE] -->
<string name="edge_to_edge_navigation_summary" translatable="false">To go Home, swipe up from the bottom of the screen. To go Back, swipe from either the left or right edge of the screen. To switch apps, start swiping up from the bottom of the screen and hold before releasing.</string>
<!-- Title text for 3-button navigation [CHAR LIMIT=60] [DO NOT TRANSLATE] -->
<string name="legacy_navigation_title" translatable="false">3-button navigation</string>
<!-- Summary text for 3-button navigation [CHAR LIMIT=250] [DO NOT TRANSLATE] -->
<string name="legacy_navigation_summary" translatable="false">Classic Android navigation mode where going Home, switching apps, and going Back are accessible via buttons.</string>
<!-- Preference and settings suggestion title text for ambient display double tap (phone) [CHAR LIMIT=60]--> <!-- Preference and settings suggestion title text for ambient display double tap (phone) [CHAR LIMIT=60]-->
<string name="ambient_display_title" product="default">Double-tap to check phone</string> <string name="ambient_display_title" product="default">Double-tap to check phone</string>
<!-- Preference and settings suggestion title text for ambient display double tap (tablet) [CHAR LIMIT=60]--> <!-- Preference and settings suggestion title text for ambient display double tap (tablet) [CHAR LIMIT=60]-->

View File

@@ -52,10 +52,10 @@
settings:controller="com.android.settings.gestures.DoubleTwistPreferenceController" /> settings:controller="com.android.settings.gestures.DoubleTwistPreferenceController" />
<Preference <Preference
android:key="gesture_swipe_up_input_summary" android:key="gesture_system_navigation_input_summary"
android:title="@string/swipe_up_to_switch_apps_title" android:title="@string/system_navigation_title"
android:fragment="com.android.settings.gestures.SwipeUpGestureSettings" android:fragment="com.android.settings.gestures.SystemNavigationGestureSettings"
settings:controller="com.android.settings.gestures.SwipeUpPreferenceController" /> settings:controller="com.android.settings.gestures.SystemNavigationLegacyPreferenceController" />
<Preference <Preference
android:key="gesture_tap_screen_input_summary" android:key="gesture_tap_screen_input_summary"

View File

@@ -18,20 +18,34 @@
<PreferenceScreen <PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:key="gesture_swipe_up_screen" android:key="gesture_system_navigation_screen"
android:title="@string/swipe_up_to_switch_apps_title"> android:title="@string/system_navigation_title">
<com.android.settings.widget.VideoPreference <com.android.settings.widget.VideoPreference
android:key="gesture_swipe_up_video" android:key="gesture_swipe_up_video"
app:animation="@raw/gesture_swipe_up" app:animation="@raw/gesture_swipe_up"
app:preview="@drawable/gesture_swipe_up" /> app:preview="@drawable/gesture_swipe_up" />
<SwitchPreference <com.android.settings.widget.RadioButtonPreference
android:key="gesture_edge_to_edge"
android:title="@string/edge_to_edge_navigation_title"
android:summary="@string/edge_to_edge_navigation_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController"
app:allowDividerAbove="true" />
<com.android.settings.widget.RadioButtonPreference
android:key="gesture_swipe_up" android:key="gesture_swipe_up"
android:title="@string/swipe_up_to_switch_apps_title" android:title="@string/swipe_up_to_switch_apps_title"
android:summary="@string/swipe_up_to_switch_apps_summary" android:summary="@string/swipe_up_to_switch_apps_summary"
app:keywords="@string/keywords_gesture" app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.SwipeUpPreferenceController" app:controller="com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController" />
app:allowDividerAbove="true" />
<com.android.settings.widget.RadioButtonPreference
android:key="gesture_legacy"
android:title="@string/legacy_navigation_title"
android:summary="@string/legacy_navigation_summary"
app:keywords="@string/keywords_gesture"
app:controller="com.android.settings.gestures.SystemNavigationLegacyPreferenceController" />
</PreferenceScreen> </PreferenceScreen>

View File

@@ -82,7 +82,7 @@ import com.android.settings.gestures.DoubleTapScreenSettings;
import com.android.settings.gestures.DoubleTwistGestureSettings; import com.android.settings.gestures.DoubleTwistGestureSettings;
import com.android.settings.gestures.PickupGestureSettings; import com.android.settings.gestures.PickupGestureSettings;
import com.android.settings.gestures.SwipeToNotificationSettings; import com.android.settings.gestures.SwipeToNotificationSettings;
import com.android.settings.gestures.SwipeUpGestureSettings; import com.android.settings.gestures.SystemNavigationGestureSettings;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment; import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.KeyboardLayoutPickerFragment; import com.android.settings.inputmethod.KeyboardLayoutPickerFragment;
import com.android.settings.inputmethod.PhysicalKeyboardFragment; import com.android.settings.inputmethod.PhysicalKeyboardFragment;
@@ -201,7 +201,7 @@ public class SettingsGateway {
DoubleTapScreenSettings.class.getName(), DoubleTapScreenSettings.class.getName(),
PickupGestureSettings.class.getName(), PickupGestureSettings.class.getName(),
DoubleTwistGestureSettings.class.getName(), DoubleTwistGestureSettings.class.getName(),
SwipeUpGestureSettings.class.getName(), SystemNavigationGestureSettings.class.getName(),
CryptKeeperSettings.class.getName(), CryptKeeperSettings.class.getName(),
DataUsageSummary.class.getName(), DataUsageSummary.class.getName(),
DreamSettings.class.getName(), DreamSettings.class.getName(),

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2018 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 android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import com.android.internal.R;
public class SwipeUpPreferenceController extends GesturePreferenceController {
private final int ON = 1;
private final int OFF = 0;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
private static final String PREF_KEY_VIDEO = "gesture_swipe_up_video";
private final UserManager mUserManager;
public SwipeUpPreferenceController(Context context, String key) {
super(context, key);
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
}
static boolean isGestureAvailable(Context context) {
if (!context.getResources().getBoolean(R.bool.config_swipe_up_gesture_setting_available)) {
return false;
}
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(R.string.config_recentsComponentName));
if (recentsComponentName == null) {
return false;
}
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
if (context.getPackageManager().resolveService(quickStepIntent,
PackageManager.MATCH_SYSTEM_ONLY) == null) {
return false;
}
return true;
}
@Override
public int getAvailabilityStatus() {
return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isSliceable() {
return TextUtils.equals(getPreferenceKey(), "gesture_swipe_up");
}
@Override
protected String getVideoPrefKey() {
return PREF_KEY_VIDEO;
}
@Override
public boolean setChecked(boolean isChecked) {
setSwipeUpPreference(mContext, mUserManager, isChecked ? ON : OFF);
return true;
}
public static void setSwipeUpPreference(Context context, UserManager userManager,
int enabled) {
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, enabled);
}
@Override
public boolean isChecked() {
final int defaultValue = mContext.getResources()
.getBoolean(R.bool.config_swipe_up_gesture_default) ? ON : OFF;
final int swipeUpEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultValue);
return swipeUpEnabled != OFF;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2019 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 android.content.Context;
import android.text.TextUtils;
import com.android.settings.widget.RadioButtonPreference;
public class SystemNavigationEdgeToEdgePreferenceController extends
SystemNavigationPreferenceController {
static final String PREF_KEY_EDGE_TO_EDGE = "gesture_edge_to_edge";
public SystemNavigationEdgeToEdgePreferenceController(Context context, String key) {
super(context, key);
}
@Override
public boolean isSliceable() {
return TextUtils.equals(PREF_KEY_EDGE_TO_EDGE, getPreferenceKey());
}
@Override
public void onRadioButtonClicked(RadioButtonPreference preference) {
setSwipeUpEnabled(mContext, true);
setEdgeToEdgeGestureEnabled(mContext, true);
selectRadioButtonInGroup(PREF_KEY_EDGE_TO_EDGE, mPreferenceScreen);
}
@Override
public boolean isChecked() {
return isEdgeToEdgeEnabled(mContext);
}
}

View File

@@ -32,12 +32,12 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
@SearchIndexable @SearchIndexable
public class SwipeUpGestureSettings extends DashboardFragment { public class SystemNavigationGestureSettings extends DashboardFragment {
private static final String TAG = "SwipeUpGesture"; private static final String TAG = "SystemNavigationGesture";
public static final String PREF_KEY_SUGGESTION_COMPLETE = public static final String PREF_KEY_SUGGESTION_COMPLETE =
"pref_swipe_up_suggestion_complete"; "pref_system_navigation_suggestion_complete";
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
@@ -60,7 +60,7 @@ public class SwipeUpGestureSettings extends DashboardFragment {
@Override @Override
protected int getPreferenceScreenResId() { protected int getPreferenceScreenResId() {
return R.xml.swipe_up_gesture_settings; return R.xml.system_navigation_gesture_settings;
} }
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
@@ -69,13 +69,13 @@ public class SwipeUpGestureSettings extends DashboardFragment {
public List<SearchIndexableResource> getXmlResourcesToIndex( public List<SearchIndexableResource> getXmlResourcesToIndex(
Context context, boolean enabled) { Context context, boolean enabled) {
final SearchIndexableResource sir = new SearchIndexableResource(context); final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.swipe_up_gesture_settings; sir.xmlResId = R.xml.system_navigation_gesture_settings;
return Arrays.asList(sir); return Arrays.asList(sir);
} }
@Override @Override
protected boolean isPageSearchEnabled(Context context) { protected boolean isPageSearchEnabled(Context context) {
return SwipeUpPreferenceController.isGestureAvailable(context); return SystemNavigationPreferenceController.isGestureAvailable(context);
} }
}; };
} }

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2019 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 android.content.Context;
import android.text.TextUtils;
import com.android.settings.widget.RadioButtonPreference;
public class SystemNavigationLegacyPreferenceController extends
SystemNavigationPreferenceController {
static final String PREF_KEY_LEGACY = "gesture_legacy";
public SystemNavigationLegacyPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public boolean isSliceable() {
return TextUtils.equals(PREF_KEY_LEGACY, getPreferenceKey());
}
@Override
public void onRadioButtonClicked(RadioButtonPreference preference) {
setEdgeToEdgeGestureEnabled(mContext, false);
setSwipeUpEnabled(mContext, false);
selectRadioButtonInGroup(PREF_KEY_LEGACY, mPreferenceScreen);
}
@Override
public boolean isChecked() {
return !isEdgeToEdgeEnabled(mContext) && !isSwipeUpEnabled(mContext);
}
}

View File

@@ -0,0 +1,207 @@
/*
* Copyright (C) 2019 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.os.UserHandle.USER_SYSTEM;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.om.IOverlayManager;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.widget.RadioButtonPreference;
public abstract class SystemNavigationPreferenceController extends GesturePreferenceController
implements RadioButtonPreference.OnClickListener {
private static final int OFF = 0;
private static final int ON = 1;
private static final String HIDE_BACK_BUTTON = "quickstepcontroller_hideback";
private static final String HIDE_HOME_BUTTON = "quickstepcontroller_hidehome";
private static final String HIDE_NAVBAR_DIVIDER = "hide_navigationbar_divider";
private static final String SHOW_HANDLE = "quickstepcontroller_showhandle";
private static final String ENABLE_CLICK_THROUGH = "quickstepcontroller_clickthrough";
private static final String ENABLE_LAUNCHER_SWIPE_TO_HOME = "SWIPE_HOME";
private static final String ENABLE_COLOR_ADAPT_FOR_HANDLE = "navbar_color_adapt_enable";
private static final String ENABLE_ASSISTANT_GESTURE = "ENABLE_ASSISTANT_GESTURE";
private static final String PROTOTYPE_ENABLED = "prototype_enabled";
private static final int EDGE_SENSITIVITY_WIDTH = 32;
private static final String EDGE_SENSITIVITY_KEY = "quickstepcontroller_edge_width_sensitivity";
private static final String GESTURES_MATCH_MAP_OFF = "000000";
private static final String GESTURES_MATCH_MAP_ON = "071133";
private static final String GESTURES_MATCH_MAP_KEY = "quickstepcontroller_gesture_match_map";
private static final String OVERLAY_NAVBAR_TYPE_INSET =
"com.android.internal.experiment.navbar.type.inset";
private static final String OVERLAY_NAVBAR_TYPE_FLOATING =
"com.android.internal.experiment.navbar.type.floating";
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
private static final String PREF_KEY_VIDEO = "gesture_swipe_up_video";
private static final String[] RADIO_BUTTONS_IN_GROUP = {
SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY,
SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP,
SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE,
};
protected PreferenceScreen mPreferenceScreen;
public SystemNavigationPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceScreen = screen;
Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null && preference instanceof RadioButtonPreference) {
RadioButtonPreference radioPreference = (RadioButtonPreference) preference;
radioPreference.setOnClickListener(this);
radioPreference.setAppendixVisibility(View.GONE);
}
}
@Override
public boolean setChecked(boolean isChecked) {
if (!isChecked || mPreferenceScreen == null) {
return false;
}
Preference preference = mPreferenceScreen.findPreference(getPreferenceKey());
if (preference != null && preference instanceof RadioButtonPreference) {
onRadioButtonClicked((RadioButtonPreference) preference);
}
return true;
}
@Override
public CharSequence getSummary() {
if (isEdgeToEdgeEnabled(mContext)) {
return mContext.getText(R.string.edge_to_edge_navigation_title);
} else if (isSwipeUpEnabled(mContext)) {
return mContext.getText(R.string.swipe_up_to_switch_apps_title);
} else {
return mContext.getText(R.string.legacy_navigation_title);
}
}
@Override
protected String getVideoPrefKey() {
return PREF_KEY_VIDEO;
}
static boolean isGestureAvailable(Context context) {
if (!context.getResources().getBoolean(
com.android.internal.R.bool.config_swipe_up_gesture_setting_available)) {
return false;
}
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
context.getString(com.android.internal.R.string.config_recentsComponentName));
if (recentsComponentName == null) {
return false;
}
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
if (context.getPackageManager().resolveService(quickStepIntent,
PackageManager.MATCH_SYSTEM_ONLY) == null) {
return false;
}
return true;
}
static void selectRadioButtonInGroup(String preferenceKey, PreferenceScreen screen) {
if (screen == null) {
return;
}
for (String key : RADIO_BUTTONS_IN_GROUP) {
((RadioButtonPreference) screen.findPreference(key)).setChecked(
TextUtils.equals(key, preferenceKey));
}
}
static void setEdgeToEdgeGestureEnabled(Context context, boolean enable) {
// TODO(b/127366543): replace all of this with a single switch
setBooleanGlobalSetting(context, HIDE_BACK_BUTTON, enable);
setBooleanGlobalSetting(context, HIDE_HOME_BUTTON, enable);
setBooleanGlobalSetting(context, HIDE_NAVBAR_DIVIDER, enable);
setBooleanGlobalSetting(context, SHOW_HANDLE, enable);
setBooleanGlobalSetting(context, ENABLE_CLICK_THROUGH, enable);
setBooleanGlobalSetting(context, ENABLE_LAUNCHER_SWIPE_TO_HOME, enable);
setBooleanGlobalSetting(context, ENABLE_COLOR_ADAPT_FOR_HANDLE, enable);
setBooleanGlobalSetting(context, ENABLE_ASSISTANT_GESTURE, enable);
setBooleanGlobalSetting(context, PROTOTYPE_ENABLED, enable);
Settings.Global.putInt(context.getContentResolver(), EDGE_SENSITIVITY_KEY,
EDGE_SENSITIVITY_WIDTH);
Settings.Global.putString(context.getContentResolver(), GESTURES_MATCH_MAP_KEY,
enable ? GESTURES_MATCH_MAP_ON : GESTURES_MATCH_MAP_OFF);
IOverlayManager overlayManager = IOverlayManager.Stub
.asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE));
if (overlayManager != null) {
try {
overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_FLOATING, false, USER_SYSTEM);
overlayManager.setEnabled(OVERLAY_NAVBAR_TYPE_INSET, enable, USER_SYSTEM);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
static void setBooleanGlobalSetting(Context context, String name, boolean flag) {
Settings.Global.putInt(context.getContentResolver(), name, flag ? ON : OFF);
}
static void setSwipeUpEnabled(Context context, boolean enabled) {
Settings.Secure.putInt(context.getContentResolver(),
Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, enabled ? ON : OFF);
}
static boolean isSwipeUpEnabled(Context context) {
if (isEdgeToEdgeEnabled(context)) {
return false;
}
final int defaultSwipeUpValue = context.getResources()
.getBoolean(com.android.internal.R.bool.config_swipe_up_gesture_default) ? ON : OFF;
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.SWIPE_UP_TO_SWITCH_APPS_ENABLED, defaultSwipeUpValue) == ON;
}
static boolean isEdgeToEdgeEnabled(Context context) {
return Settings.Global.getInt(context.getContentResolver(), PROTOTYPE_ENABLED, OFF) == ON;
}
}

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2019 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 android.content.Context;
import android.text.TextUtils;
import com.android.settings.widget.RadioButtonPreference;
public class SystemNavigationSwipeUpPreferenceController extends
SystemNavigationPreferenceController {
static final String PREF_KEY_SWIPE_UP = "gesture_swipe_up";
public SystemNavigationSwipeUpPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public boolean isSliceable() {
return TextUtils.equals(PREF_KEY_SWIPE_UP, getPreferenceKey());
}
@Override
public void onRadioButtonClicked(RadioButtonPreference preference) {
setEdgeToEdgeGestureEnabled(mContext, false);
setSwipeUpEnabled(mContext, true);
selectRadioButtonInGroup(PREF_KEY_SWIPE_UP, mPreferenceScreen);
}
@Override
public boolean isChecked() {
return isSwipeUpEnabled(mContext);
}
}

View File

@@ -0,0 +1,174 @@
/*
* Copyright (C) 2019 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.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE;
import static com.android.settings.gestures.SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY;
import static com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.widget.RadioButtonPreference;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class)
public class SystemNavigationEdgeToEdgePreferenceControllerTest {
private Context mContext;
private ShadowPackageManager mPackageManager;
private SystemNavigationEdgeToEdgePreferenceController mController;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
@Before
public void setUp() {
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
true);
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, true);
mContext = RuntimeEnvironment.application;
Settings.Global.putInt(mContext.getContentResolver(), "prototype_enabled", 1);
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new SystemNavigationEdgeToEdgePreferenceController(mContext,
PREF_KEY_EDGE_TO_EDGE);
}
@After
public void tearDown() {
SettingsShadowResources.reset();
}
@Test
public void testIsGestureAvailable_matchingServiceExists_shouldReturnTrue() {
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
mContext.getString(com.android.internal.R.string.config_recentsComponentName));
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
final ResolveInfo info = new ResolveInfo();
info.serviceInfo = new ServiceInfo();
info.resolvePackageName = recentsComponentName.getPackageName();
info.serviceInfo.packageName = info.resolvePackageName;
info.serviceInfo.name = recentsComponentName.getClassName();
info.serviceInfo.applicationInfo = new ApplicationInfo();
info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
mPackageManager.addResolveInfoForIntent(quickStepIntent, info);
assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext))
.isTrue();
}
@Test
public void testIsGestureAvailable_overlayDisabled_matchingServiceExists_shouldReturnFalse() {
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
false);
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
mContext.getString(com.android.internal.R.string.config_recentsComponentName));
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext))
.isFalse();
}
@Test
public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
assertThat(SystemNavigationEdgeToEdgePreferenceController.isGestureAvailable(mContext))
.isFalse();
}
@Test
public void testIsChecked_defaultIsTrue_shouldReturnTrue() {
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testIsChecked_defaultIsFalse_shouldReturnFalse() {
Settings.Global.putInt(mContext.getContentResolver(), "prototype_enabled", 0);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void testIsChecked_radioButtonClicked_shouldReturnTrue() {
// Set the setting to be enabled.
mController.onRadioButtonClicked(null);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testOnRadioButtonClicked_setsCorrectRadioButtonChecked() {
RadioButtonPreference radioLegacy = mock(RadioButtonPreference.class);
RadioButtonPreference radioSwipeUp = mock(RadioButtonPreference.class);
RadioButtonPreference radioEdgeToEdge = mock(RadioButtonPreference.class);
PreferenceScreen screen = mock(PreferenceScreen.class);
when(screen.findPreference(PREF_KEY_LEGACY)).thenReturn(radioLegacy);
when(screen.findPreference(PREF_KEY_SWIPE_UP)).thenReturn(radioSwipeUp);
when(screen.findPreference(PREF_KEY_EDGE_TO_EDGE)).thenReturn(radioEdgeToEdge);
mController.displayPreference(screen);
mController.onRadioButtonClicked(radioEdgeToEdge);
verify(radioLegacy, times(1)).setChecked(false);
verify(radioSwipeUp, times(1)).setChecked(false);
verify(radioEdgeToEdge, times(1)).setChecked(true);
}
@Test
public void isSliceableCorrectKey_returnsTrue() {
assertThat(mController.isSliceable()).isTrue();
}
@Test
public void isSliceableIncorrectKey_returnsFalse() {
final SystemNavigationEdgeToEdgePreferenceController controller =
new SystemNavigationEdgeToEdgePreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}

View File

@@ -0,0 +1,171 @@
/*
* Copyright (C) 2019 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.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE;
import static com.android.settings.gestures.SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY;
import static com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.R;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.widget.RadioButtonPreference;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class)
public class SystemNavigationLegacyPreferenceControllerTest {
private Context mContext;
private ShadowPackageManager mPackageManager;
private SystemNavigationLegacyPreferenceController mController;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
@Before
public void setUp() {
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
true);
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, false);
mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new SystemNavigationLegacyPreferenceController(mContext, PREF_KEY_LEGACY);
}
@After
public void tearDown() {
SettingsShadowResources.reset();
}
@Test
public void testIsGestureAvailable_matchingServiceExists_shouldReturnTrue() {
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
mContext.getString(com.android.internal.R.string.config_recentsComponentName));
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
final ResolveInfo info = new ResolveInfo();
info.serviceInfo = new ServiceInfo();
info.resolvePackageName = recentsComponentName.getPackageName();
info.serviceInfo.packageName = info.resolvePackageName;
info.serviceInfo.name = recentsComponentName.getClassName();
info.serviceInfo.applicationInfo = new ApplicationInfo();
info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
mPackageManager.addResolveInfoForIntent(quickStepIntent, info);
assertThat(SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext))
.isTrue();
}
@Test
public void testIsGestureAvailable_overlayDisabled_matchingServiceExists_shouldReturnFalse() {
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_setting_available,
false);
final ComponentName recentsComponentName = ComponentName.unflattenFromString(
mContext.getString(com.android.internal.R.string.config_recentsComponentName));
final Intent quickStepIntent = new Intent(ACTION_QUICKSTEP)
.setPackage(recentsComponentName.getPackageName());
mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
assertThat(
SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext)).isFalse();
}
@Test
public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
assertThat(
SystemNavigationLegacyPreferenceController.isGestureAvailable(mContext)).isFalse();
}
@Test
public void testIsChecked_defaultIsTrue_shouldReturnTrue() {
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testIsChecked_defaultIsFalse_shouldReturnFalse() {
// Turn on the Swipe Up mode (2-buttons)
SettingsShadowResources.overrideResource(R.bool.config_swipe_up_gesture_default, true);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void testIsChecked_radioButtonClicked_shouldReturnTrue() {
// Set the setting to be enabled.
mController.onRadioButtonClicked(null);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void testOnRadioButtonClicked_setsCorrectRadioButtonChecked() {
RadioButtonPreference radioLegacy = mock(RadioButtonPreference.class);
RadioButtonPreference radioSwipeUp = mock(RadioButtonPreference.class);
RadioButtonPreference radioEdgeToEdge = mock(RadioButtonPreference.class);
PreferenceScreen screen = mock(PreferenceScreen.class);
when(screen.findPreference(PREF_KEY_LEGACY)).thenReturn(radioLegacy);
when(screen.findPreference(PREF_KEY_SWIPE_UP)).thenReturn(radioSwipeUp);
when(screen.findPreference(PREF_KEY_EDGE_TO_EDGE)).thenReturn(radioEdgeToEdge);
mController.displayPreference(screen);
mController.onRadioButtonClicked(radioLegacy);
verify(radioLegacy, times(1)).setChecked(true);
verify(radioSwipeUp, times(1)).setChecked(false);
verify(radioEdgeToEdge, times(1)).setChecked(false);
}
@Test
public void isSliceableCorrectKey_returnsTrue() {
assertThat(mController.isSliceable()).isTrue();
}
@Test
public void isSliceableIncorrectKey_returnsFalse() {
final SystemNavigationLegacyPreferenceController controller =
new SystemNavigationLegacyPreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse();
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2018 The Android Open Source Project * Copyright (C) 2019 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,8 +16,17 @@
package com.android.settings.gestures; package com.android.settings.gestures;
import static com.android.settings.gestures.SystemNavigationEdgeToEdgePreferenceController.PREF_KEY_EDGE_TO_EDGE;
import static com.android.settings.gestures.SystemNavigationLegacyPreferenceController.PREF_KEY_LEGACY;
import static com.android.settings.gestures.SystemNavigationSwipeUpPreferenceController.PREF_KEY_SWIPE_UP;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@@ -25,8 +34,12 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.R; import com.android.internal.R;
import com.android.settings.testutils.shadow.SettingsShadowResources; import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.widget.RadioButtonPreference;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@@ -40,14 +53,14 @@ import org.robolectric.shadows.ShadowPackageManager;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class) @Config(shadows = SettingsShadowResources.class)
public class SwipeUpPreferenceControllerTest { public class SystemNavigationSwipeUpPreferenceControllerTest {
private Context mContext; private Context mContext;
private ShadowPackageManager mPackageManager; private ShadowPackageManager mPackageManager;
private SwipeUpPreferenceController mController;
private SystemNavigationSwipeUpPreferenceController mController;
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE"; private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
private static final String KEY_SWIPE_UP = "gesture_swipe_up";
@Before @Before
public void setUp() { public void setUp() {
@@ -57,7 +70,8 @@ public class SwipeUpPreferenceControllerTest {
mContext = RuntimeEnvironment.application; mContext = RuntimeEnvironment.application;
mPackageManager = Shadows.shadowOf(mContext.getPackageManager()); mPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mController = new SwipeUpPreferenceController(mContext, KEY_SWIPE_UP);
mController = new SystemNavigationSwipeUpPreferenceController(mContext, PREF_KEY_SWIPE_UP);
} }
@After @After
@@ -80,7 +94,8 @@ public class SwipeUpPreferenceControllerTest {
info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM; info.serviceInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
mPackageManager.addResolveInfoForIntent(quickStepIntent, info); mPackageManager.addResolveInfoForIntent(quickStepIntent, info);
assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isTrue(); assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext))
.isTrue();
} }
@Test @Test
@@ -94,12 +109,14 @@ public class SwipeUpPreferenceControllerTest {
.setPackage(recentsComponentName.getPackageName()); .setPackage(recentsComponentName.getPackageName());
mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo()); mPackageManager.addResolveInfoForIntent(quickStepIntent, new ResolveInfo());
assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse(); assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext))
.isFalse();
} }
@Test @Test
public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() { public void testIsGestureAvailable_noMatchingServiceExists_shouldReturnFalse() {
assertThat(SwipeUpPreferenceController.isGestureAvailable(mContext)).isFalse(); assertThat(SystemNavigationSwipeUpPreferenceController.isGestureAvailable(mContext))
.isFalse();
} }
@Test @Test
@@ -114,30 +131,40 @@ public class SwipeUpPreferenceControllerTest {
} }
@Test @Test
public void testIsChecked_setCheckedTrue_shouldReturnTrue() { public void testIsChecked_radioButtonClicked_shouldReturnTrue() {
// Set the setting to be enabled. // Set the setting to be enabled.
mController.setChecked(true); mController.onRadioButtonClicked(null);
assertThat(mController.isChecked()).isTrue(); assertThat(mController.isChecked()).isTrue();
} }
@Test @Test
public void testIsChecked_setCheckedFalse_shouldReturnFalse() { public void testOnRadioButtonClicked_setsCorrectRadioButtonChecked() {
// Set the setting to be disabled. RadioButtonPreference radioLegacy = mock(RadioButtonPreference.class);
mController.setChecked(false); RadioButtonPreference radioSwipeUp = mock(RadioButtonPreference.class);
assertThat(mController.isChecked()).isFalse(); RadioButtonPreference radioEdgeToEdge = mock(RadioButtonPreference.class);
PreferenceScreen screen = mock(PreferenceScreen.class);
when(screen.findPreference(PREF_KEY_LEGACY)).thenReturn(radioLegacy);
when(screen.findPreference(PREF_KEY_SWIPE_UP)).thenReturn(radioSwipeUp);
when(screen.findPreference(PREF_KEY_EDGE_TO_EDGE)).thenReturn(radioEdgeToEdge);
mController.displayPreference(screen);
mController.onRadioButtonClicked(radioSwipeUp);
verify(radioLegacy, times(1)).setChecked(false);
verify(radioSwipeUp, times(1)).setChecked(true);
verify(radioEdgeToEdge, times(1)).setChecked(false);
} }
@Test @Test
public void isSliceableCorrectKey_returnsTrue() { public void isSliceableCorrectKey_returnsTrue() {
final SwipeUpPreferenceController controller = assertThat(mController.isSliceable()).isTrue();
new SwipeUpPreferenceController(mContext, "gesture_swipe_up");
assertThat(controller.isSliceable()).isTrue();
} }
@Test @Test
public void isSliceableIncorrectKey_returnsFalse() { public void isSliceableIncorrectKey_returnsFalse() {
final SwipeUpPreferenceController controller = final SystemNavigationSwipeUpPreferenceController controller =
new SwipeUpPreferenceController(mContext, "bad_key"); new SystemNavigationSwipeUpPreferenceController(mContext, "bad_key");
assertThat(controller.isSliceable()).isFalse(); assertThat(controller.isSliceable()).isFalse();
} }
} }