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
diff --git a/res/values/strings.xml b/res/values/strings.xml
index e7a0535..4532646 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8071,6 +8071,9 @@
<!-- Summary text for the assist gesture [CHAR LIMIT=160]-->
<string name="assist_gesture_summary"></string>
+ <!-- Title text for the assist gesture sensitivity setting [CHAR LIMIT=NONE]-->
+ <string name="assist_gesture_sensitivity_title">Sensitivity</string>
+
<!-- Switch text for each gesture setting state -->
<string name="gesture_setting_on">On</string>
<string name="gesture_setting_off">Off</string>
diff --git a/res/xml/assist_gesture_settings.xml b/res/xml/assist_gesture_settings.xml
index c0a3810..52ee247 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" />
+ <com.android.settings.SeekBarPreference
+ android:key="gesture_assist_sensitivity"
+ android:title="@string/assist_gesture_sensitivity_title"
+ android:defaultValue="2"
+ android:max="4" />
+
</PreferenceScreen>
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 bd85a03..0000000
--- 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 a54f0ff..824c0b1 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.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 @@
Lifecycle lifecycle) {
final List<PreferenceController> 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 99d38b6..f0ba888 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
@@ -53,17 +114,28 @@
}
@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<Uri> 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 0000000..5334e62
--- /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 7778720..238b8b6 100644
--- a/src/com/android/settings/gestures/AssistGestureSettings.java
+++ b/src/com/android/settings/gestures/AssistGestureSettings.java
@@ -58,6 +58,7 @@
Lifecycle lifecycle) {
final List<PreferenceController> 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 624a01f..0000000
--- 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 0000000..229ef49
--- /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();
+ }
+}
+