From 5473f68cddb239a72f0aa9509f56550b08e02ce0 Mon Sep 17 00:00:00 2001 From: Philip Quinn Date: Mon, 6 Mar 2017 13:37:42 -0800 Subject: [PATCH] Add setting for the assist gesture sensitivity control. The sensitivity control is only visible when the assist gesture itself is enabled. Test: make -j RunSettingsRoboTests; manual test on supported/unsupported configurations. Change-Id: I584975794c5cf9d788e93167292d142ae2faf1c5 --- res/values/strings.xml | 3 + res/xml/assist_gesture_settings.xml | 6 + .../GestureAssistPreferenceController.java | 46 ------ .../applications/assist/ManageAssist.java | 3 +- .../AssistGesturePreferenceController.java | 102 ++++++++++-- ...estureSensitivityPreferenceController.java | 151 ++++++++++++++++++ .../gestures/AssistGestureSettings.java | 1 + ...GestureAssistPreferenceControllerTest.java | 64 -------- ...reSensitivityPreferenceControllerTest.java | 101 ++++++++++++ 9 files changed, 351 insertions(+), 126 deletions(-) delete mode 100644 src/com/android/settings/applications/assist/GestureAssistPreferenceController.java create mode 100644 src/com/android/settings/gestures/AssistGestureSensitivityPreferenceController.java delete mode 100644 tests/robotests/src/com/android/settings/applications/assist/GestureAssistPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index e7a05350101..4532646bf61 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8071,6 +8071,9 @@ + + Sensitivity + On Off diff --git a/res/xml/assist_gesture_settings.xml b/res/xml/assist_gesture_settings.xml index c0a38109701..52ee247970f 100644 --- a/res/xml/assist_gesture_settings.xml +++ b/res/xml/assist_gesture_settings.xml @@ -29,4 +29,10 @@ android:title="@string/assist_gesture_title" android:summary="@string/assist_gesture_summary" /> + + diff --git a/src/com/android/settings/applications/assist/GestureAssistPreferenceController.java b/src/com/android/settings/applications/assist/GestureAssistPreferenceController.java deleted file mode 100644 index bd85a030495..00000000000 --- a/src/com/android/settings/applications/assist/GestureAssistPreferenceController.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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.applications.assist; - -import android.content.Context; - -import com.android.settings.core.PreferenceController; -import com.android.settings.gestures.AssistGestureFeatureProvider; -import com.android.settings.overlay.FeatureFactory; - -public class GestureAssistPreferenceController extends PreferenceController { - - private static final String KEY_ASSIST_GESTURE = "gesture_assist"; - - private AssistGestureFeatureProvider mFeatureProvider; - - public GestureAssistPreferenceController(Context context) { - super(context); - mFeatureProvider = FeatureFactory.getFactory(context) - .getAssistGestureFeatureProvider(); - } - - @Override - public boolean isAvailable() { - return mFeatureProvider.isSupported(mContext); - } - - @Override - public String getPreferenceKey() { - return KEY_ASSIST_GESTURE; - } -} diff --git a/src/com/android/settings/applications/assist/ManageAssist.java b/src/com/android/settings/applications/assist/ManageAssist.java index a54f0ffba6f..824c0b1c5d5 100644 --- a/src/com/android/settings/applications/assist/ManageAssist.java +++ b/src/com/android/settings/applications/assist/ManageAssist.java @@ -24,6 +24,7 @@ import com.android.settings.R; import com.android.settings.core.PreferenceController; import com.android.settings.core.lifecycle.Lifecycle; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.gestures.AssistGesturePreferenceController; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.Indexable; @@ -70,7 +71,7 @@ public class ManageAssist extends DashboardFragment { Lifecycle lifecycle) { final List controllers = new ArrayList<>(); controllers.add(new DefaultAssistPreferenceController(context)); - controllers.add(new GestureAssistPreferenceController(context)); + controllers.add(new AssistGesturePreferenceController(context, lifecycle)); controllers.add(new AssistContextPreferenceController(context, lifecycle)); controllers.add(new AssistScreenshotPreferenceController(context, lifecycle)); controllers.add(new AssistFlashScreenPreferenceController(context, lifecycle)); diff --git a/src/com/android/settings/gestures/AssistGesturePreferenceController.java b/src/com/android/settings/gestures/AssistGesturePreferenceController.java index 99d38b68083..f0ba8883e37 100644 --- a/src/com/android/settings/gestures/AssistGesturePreferenceController.java +++ b/src/com/android/settings/gestures/AssistGesturePreferenceController.java @@ -17,29 +17,90 @@ package com.android.settings.gestures; import android.content.Context; +import android.net.Uri; import android.provider.Settings; import android.support.v7.preference.Preference; -import android.util.ArrayMap; +import android.support.v7.preference.PreferenceScreen; +import com.android.settings.applications.assist.AssistSettingObserver; import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.search2.InlineSwitchPayload; -import com.android.settings.search2.ResultPayload; -public class AssistGesturePreferenceController extends GesturePreferenceController { +import java.util.Arrays; +import java.util.List; + +public class AssistGesturePreferenceController extends GesturePreferenceController + implements OnPause, OnResume { private static final String PREF_KEY_VIDEO = "gesture_assist_video"; private static final String PREF_KEY_ASSIST_GESTURE = "gesture_assist"; + private final AssistGestureFeatureProvider mFeatureProvider; + private final SettingObserver mSettingObserver; + private boolean mWasAvailable; + + private PreferenceScreen mScreen; + private Preference mPreference; + public AssistGesturePreferenceController(Context context, Lifecycle lifecycle) { super(context, lifecycle); + mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider(); + mSettingObserver = new SettingObserver(); + mWasAvailable = isAvailable(); } @Override public boolean isAvailable() { - AssistGestureFeatureProvider provider = - FeatureFactory.getFactory(mContext).getAssistGestureFeatureProvider(); - return provider.isSupported(mContext); + return mFeatureProvider.isSupported(mContext); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + mScreen = screen; + mPreference = screen.findPreference(getPreferenceKey()); + // Call super last or AbstractPreferenceController might remove the preference from the + // screen (if !isAvailable()) before we can save a reference to it. + super.displayPreference(screen); + } + + @Override + public void onResume() { + mSettingObserver.register(mContext.getContentResolver(), true /* register */); + if (mWasAvailable != isAvailable()) { + // Only update the preference visibility if the availability has changed -- otherwise + // the preference may be incorrectly added to screens with collapsed sections. + updatePreference(); + mWasAvailable = isAvailable(); + } + } + + @Override + public void onPause() { + mSettingObserver.register(mContext.getContentResolver(), false /* register */); + } + + private void updatePreference() { + if (mPreference == null) { + return; + } + + if (isAvailable()) { + if (mScreen.findPreference(getPreferenceKey()) == null) { + mScreen.addPreference(mPreference); + } + } else { + mScreen.removePreference(mPreference); + } + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean enabled = (boolean) newValue; + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_ENABLED, enabled ? 1 : 0); + return true; } @Override @@ -52,18 +113,29 @@ public class AssistGesturePreferenceController extends GesturePreferenceControll return PREF_KEY_ASSIST_GESTURE; } - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean enabled = (boolean) newValue; - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.ASSIST_GESTURE_ENABLED, enabled ? 1 : 0); - return true; - } - @Override protected boolean isSwitchPrefEnabled() { final int assistGestureEnabled = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.ASSIST_GESTURE_ENABLED, 1); return assistGestureEnabled != 0; } + + class SettingObserver extends AssistSettingObserver { + + private final Uri ASSIST_GESTURE_ENABLED_URI = + Settings.Secure.getUriFor(Settings.Secure.ASSIST_GESTURE_ENABLED); + + @Override + protected List getSettingUris() { + return Arrays.asList(ASSIST_GESTURE_ENABLED_URI); + } + + @Override + public void onSettingChange() { + if (mWasAvailable != isAvailable()) { + updatePreference(); + mWasAvailable = isAvailable(); + } + } + } } diff --git a/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceController.java b/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceController.java new file mode 100644 index 00000000000..5334e62e8b4 --- /dev/null +++ b/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceController.java @@ -0,0 +1,151 @@ +/* + * 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.gestures; + +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.provider.Settings; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.SeekBarPreference; +import com.android.settings.core.PreferenceController; +import com.android.settings.core.lifecycle.Lifecycle; +import com.android.settings.core.lifecycle.LifecycleObserver; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; +import com.android.settings.overlay.FeatureFactory; + +public class AssistGestureSensitivityPreferenceController extends PreferenceController + implements Preference.OnPreferenceChangeListener, LifecycleObserver, OnPause, OnResume { + + private static final String PREF_KEY_ASSIST_GESTURE_SENSITIVITY = "gesture_assist_sensitivity"; + + private final AssistGestureFeatureProvider mFeatureProvider; + private final SettingObserver mSettingObserver; + + private PreferenceScreen mScreen; + private SeekBarPreference mPreference; + + public AssistGestureSensitivityPreferenceController(Context context, Lifecycle lifecycle) { + super(context); + mFeatureProvider = FeatureFactory.getFactory(context).getAssistGestureFeatureProvider(); + mSettingObserver = new SettingObserver(); + + if (lifecycle != null) { + lifecycle.addObserver(this); + } + } + + @Override + public void onResume() { + mSettingObserver.register(mContext.getContentResolver(), true /* register */); + updatePreference(); + } + + @Override + public void onPause() { + mSettingObserver.register(mContext.getContentResolver(), false /* register */); + } + + @Override + public boolean isAvailable() { + // The sensitivity control is contingent on the assist gesture being supported and the + // gesture being enabled. + final int gestureEnabled = Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_ENABLED, + 1); + return (gestureEnabled == 1) && mFeatureProvider.isSupported(mContext); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + mScreen = screen; + mPreference = (SeekBarPreference) screen.findPreference(getPreferenceKey()); + // Call super last or AbstractPreferenceController might remove the preference from the + // screen (if !isAvailable()) before we can save a reference to it. + super.displayPreference(screen); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + updatePreference(); + } + + private void updatePreference() { + if (mPreference == null) { + return; + } + + if (isAvailable()) { + if (mScreen.findPreference(getPreferenceKey()) == null) { + mScreen.addPreference(mPreference); + } + } else { + mScreen.removePreference(mPreference); + } + + final int sensitivity = Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_SENSITIVITY, + mPreference.getProgress()); + mPreference.setProgress(sensitivity); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final int sensitivity = (int) newValue; + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_SENSITIVITY, sensitivity); + return true; + } + + @Override + public String getPreferenceKey() { + return PREF_KEY_ASSIST_GESTURE_SENSITIVITY; + } + + class SettingObserver extends ContentObserver { + + private final Uri ASSIST_GESTURE_ENABLED_URI = + Settings.Secure.getUriFor(Settings.Secure.ASSIST_GESTURE_ENABLED); + private final Uri ASSIST_GESTURE_SENSITIVITY_URI = + Settings.Secure.getUriFor(Settings.Secure.ASSIST_GESTURE_SENSITIVITY); + + public SettingObserver() { + super(null /* handler */); + } + + public void register(ContentResolver cr, boolean register) { + if (register) { + cr.registerContentObserver(ASSIST_GESTURE_ENABLED_URI, false, this); + cr.registerContentObserver(ASSIST_GESTURE_SENSITIVITY_URI, false, this); + } else { + cr.unregisterContentObserver(this); + } + } + + @Override + public void onChange(boolean selfChange) { + updatePreference(); + } + } +} diff --git a/src/com/android/settings/gestures/AssistGestureSettings.java b/src/com/android/settings/gestures/AssistGestureSettings.java index 77787201e10..238b8b62bd9 100644 --- a/src/com/android/settings/gestures/AssistGestureSettings.java +++ b/src/com/android/settings/gestures/AssistGestureSettings.java @@ -58,6 +58,7 @@ public class AssistGestureSettings extends DashboardFragment { Lifecycle lifecycle) { final List controllers = new ArrayList<>(); controllers.add(new AssistGesturePreferenceController(context, lifecycle)); + controllers.add(new AssistGestureSensitivityPreferenceController(context, lifecycle)); return controllers; } diff --git a/tests/robotests/src/com/android/settings/applications/assist/GestureAssistPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/assist/GestureAssistPreferenceControllerTest.java deleted file mode 100644 index 624a01ff28d..00000000000 --- a/tests/robotests/src/com/android/settings/applications/assist/GestureAssistPreferenceControllerTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.applications.assist; - -import android.content.Context; - -import com.android.settings.SettingsRobolectricTestRunner; -import com.android.settings.TestConfig; -import com.android.settings.testutils.FakeFeatureFactory; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Answers; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.annotation.Config; - -import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.when; - -@RunWith(SettingsRobolectricTestRunner.class) -@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) -public class GestureAssistPreferenceControllerTest { - - @Mock(answer = Answers.RETURNS_DEEP_STUBS) - private Context mContext; - private FakeFeatureFactory mFeatureFactory; - private GestureAssistPreferenceController mController; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - FakeFeatureFactory.setupForTest(mContext); - mFeatureFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); - mController = new GestureAssistPreferenceController(mContext); - } - - @Test - public void isAvailable_shouldReturnFeatureProviderValue() { - when(mFeatureFactory.assistGestureFeatureProvider.isSupported(any(Context.class))) - .thenReturn(true); - assertThat(mController.isAvailable()).isTrue(); - - when(mFeatureFactory.assistGestureFeatureProvider.isSupported(any(Context.class))) - .thenReturn(false); - assertThat(mController.isAvailable()).isFalse(); - } -} diff --git a/tests/robotests/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceControllerTest.java new file mode 100644 index 00000000000..229ef496884 --- /dev/null +++ b/tests/robotests/src/com/android/settings/gestures/AssistGestureSensitivityPreferenceControllerTest.java @@ -0,0 +1,101 @@ +/* + * 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.gestures; + +import android.content.Context; +import android.provider.Settings; + +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.testutils.FakeFeatureFactory; + +import com.android.settings.search2.InlineSwitchPayload; +import com.android.settings.search2.ResultPayload; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import java.util.ArrayList; +import java.util.List; + +import static android.provider.Settings.Secure.ASSIST_GESTURE_ENABLED; +import static android.provider.Settings.Secure.ASSIST_GESTURE_SENSITIVITY; +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class AssistGestureSensitivityPreferenceControllerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private Context mContext; + private FakeFeatureFactory mFactory; + private AssistGestureSensitivityPreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + FakeFeatureFactory.setupForTest(mContext); + mFactory = (FakeFeatureFactory) FakeFeatureFactory.getFactory(mContext); + mController = new AssistGestureSensitivityPreferenceController(mContext, null); + } + + @Test + public void isAvailable_whenSupportedAndEnabled_shouldReturnTrue() { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_ENABLED, 1); + when(mFactory.assistGestureFeatureProvider.isSupported(mContext)).thenReturn(true); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_whenSupportedAndDisabled_shouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_ENABLED, 0); + when(mFactory.assistGestureFeatureProvider.isSupported(mContext)).thenReturn(true); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_whenUnsupportedAndEnabled_shouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_ENABLED, 1); + when(mFactory.assistGestureFeatureProvider.isSupported(mContext)).thenReturn(false); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_whenUnsupportedAndDisabled_shouldReturnFalse() { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ASSIST_GESTURE_ENABLED, 0); + when(mFactory.assistGestureFeatureProvider.isSupported(mContext)).thenReturn(false); + + assertThat(mController.isAvailable()).isFalse(); + } +} +