diff --git a/res/raw/gesture_ambient_lift.mp4 b/res/raw/gesture_ambient_lift.mp4 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/res/values/strings.xml b/res/values/strings.xml index 0be96bdee16..e7943989af1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2229,7 +2229,7 @@ Ambient display - Wake screen when you double-tap it or get new notifications. See how + Wake screen when you receive notifications Font size @@ -7762,11 +7762,25 @@ - - Quick screen check + + Quick screen check - Double Tap - - To check your phone without waking it up fully, double-tap it or pick it up + + To check your phone without waking it up fully, double-tap it + + To check your tablet without waking it up fully, double-tap it + + To check your device without waking it up fully, double-tap it + + + Quick screen check - Pickup notifications + + + To check your phone without waking it up fully, pick it up + + To check your tablet without waking it up fully, pick it up + + To check your device without waking it up fully, pick it up Swipe for notifications diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml index e797b4f7d13..b5e2848e5b8 100644 --- a/res/xml/display_settings.xml +++ b/res/xml/display_settings.xml @@ -79,19 +79,10 @@ android:key="lift_to_wake" android:title="@string/lift_to_wake_title" /> - - - - - - + android:title="@string/doze_title" + android:summary="@string/doze_summary" /> + android:key="gesture_swipe_down_fingerprint" + android:title="@string/fingerprint_swipe_for_notifications_title" + android:summary="@string/fingerprint_swipe_for_notifications_summary" + settings:animation="@raw/gesture_fingerprint_swipe"/> + + \ No newline at end of file diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index 87634fc1a56..f7b94433c25 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -41,7 +41,6 @@ import android.support.v7.preference.DropDownPreference; import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.support.v7.preference.Preference.OnPreferenceChangeListener; -import android.support.v7.preference.PreferenceScreen; import android.text.TextUtils; import android.util.Log; @@ -97,10 +96,10 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private ListPreference mNightModePreference; private Preference mScreenSaverPreference; private SwitchPreference mLiftToWakePreference; + private SwitchPreference mDozePreference; private SwitchPreference mTapToWakePreference; private SwitchPreference mAutoBrightnessPreference; private SwitchPreference mCameraGesturePreference; - private PreferenceScreen mDozePreference; @Override protected int getMetricsCategory() { @@ -144,10 +143,11 @@ public class DisplaySettings extends SettingsPreferenceFragment implements removePreference(KEY_LIFT_TO_WAKE); } - if (!isDozeAvailable(activity)) { - removePreference(KEY_DOZE); + if (isDozeAvailable(activity)) { + mDozePreference = (SwitchPreference) findPreference(KEY_DOZE); + mDozePreference.setOnPreferenceChangeListener(this); } else { - mDozePreference = (PreferenceScreen) findPreference(KEY_DOZE); + removePreference(KEY_DOZE); } if (isTapToWakeAvailable(getResources())) { @@ -360,6 +360,12 @@ public class DisplaySettings extends SettingsPreferenceFragment implements mTapToWakePreference.setChecked(value != 0); } + // Update doze if it is available. + if (mDozePreference != null) { + int value = Settings.Secure.getInt(getContentResolver(), DOZE_ENABLED, 1); + mDozePreference.setChecked(value != 0); + } + // Update camera gesture #1 if it is available. if (mCameraGesturePreference != null) { int value = Settings.Secure.getInt(getContentResolver(), CAMERA_GESTURE_DISABLED, 0); @@ -407,6 +413,10 @@ public class DisplaySettings extends SettingsPreferenceFragment implements boolean value = (Boolean) objValue; Settings.Secure.putInt(getContentResolver(), WAKE_GESTURE_ENABLED, value ? 1 : 0); } + if (preference == mDozePreference) { + boolean value = (Boolean) objValue; + Settings.Secure.putInt(getContentResolver(), DOZE_ENABLED, value ? 1 : 0); + } if (preference == mTapToWakePreference) { boolean value = (Boolean) objValue; Settings.Secure.putInt(getContentResolver(), DOUBLE_TAP_TO_WAKE, value ? 1 : 0); diff --git a/src/com/android/settings/gestures/GestureSettings.java b/src/com/android/settings/gestures/GestureSettings.java index a44c7812ead..88a7bb45084 100644 --- a/src/com/android/settings/gestures/GestureSettings.java +++ b/src/com/android/settings/gestures/GestureSettings.java @@ -52,16 +52,16 @@ public class GestureSettings extends SettingsPreferenceFragment implements private static final String TAG = "GestureSettings"; private static final String PREF_KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power"; private static final String PREF_KEY_DOUBLE_TWIST = "gesture_double_twist"; - private static final String PREF_KEY_PICK_UP_AND_NUDGE = "gesture_pick_up_and_nudge"; + private static final String PREF_KEY_PICK_UP = "gesture_pick_up"; private static final String PREF_KEY_SWIPE_DOWN_FINGERPRINT = "gesture_swipe_down_fingerprint"; + private static final String PREF_KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen"; private static final String DEBUG_DOZE_COMPONENT = "debug.doze.component"; - private static final String ARG_SCROLL_TO_PREFERENCE = "gesture_scroll_to_preference"; private static final int PREF_ID_DOUBLE_TAP_POWER = 0; private static final int PREF_ID_DOUBLE_TWIST = 1; - private static final int PREF_ID_PICK_UP_AND_NUDG = 2; + private static final int PREF_ID_PICK_UP = 2; private static final int PREF_ID_SWIPE_DOWN_FINGERPRINT = 3; + private static final int PREF_ID_DOUBLE_TAP_SCREEN = 4; - private int mScrollPosition = -1; private List mPreferences; @Override @@ -82,16 +82,19 @@ public class GestureSettings extends SettingsPreferenceFragment implements // Ambient Display if (isDozeAvailable(context)) { - int dozeEnabled = Secure.getInt(getContentResolver(), Secure.DOZE_ENABLED, 1); - addPreference(PREF_KEY_PICK_UP_AND_NUDGE, dozeEnabled != 0, PREF_ID_DOUBLE_TWIST); + int pickup = Secure.getInt(getContentResolver(), Secure.DOZE_PULSE_ON_PICK_UP, 1); + addPreference(PREF_KEY_PICK_UP, pickup != 0, PREF_ID_PICK_UP); + int doubleTap = Secure.getInt(getContentResolver(), Secure.DOZE_PULSE_ON_DOUBLE_TAP, 1); + addPreference(PREF_KEY_DOUBLE_TAP_SCREEN, doubleTap != 0, PREF_ID_DOUBLE_TAP_SCREEN); } else { - removePreference(PREF_KEY_PICK_UP_AND_NUDGE); + removePreference(PREF_KEY_PICK_UP); + removePreference(PREF_KEY_DOUBLE_TAP_SCREEN); } // Fingerprint slide for notifications if (isSystemUINavigationAvailable(context)) { addPreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT, isSystemUINavigationEnabled(context), - PREF_ID_PICK_UP_AND_NUDG); + PREF_ID_SWIPE_DOWN_FINGERPRINT); } else { removePreference(PREF_KEY_SWIPE_DOWN_FINGERPRINT); } @@ -100,23 +103,11 @@ public class GestureSettings extends SettingsPreferenceFragment implements if (isDoubleTwistAvailable(context)) { int doubleTwistEnabled = Secure.getInt( getContentResolver(), Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1); - addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0, - PREF_ID_SWIPE_DOWN_FINGERPRINT); + addPreference(PREF_KEY_DOUBLE_TWIST, doubleTwistEnabled != 0, PREF_ID_DOUBLE_TWIST); } else { removePreference(PREF_KEY_DOUBLE_TWIST); } - if (savedInstanceState == null) { - final Bundle args = getArguments(); - if (args != null && args.containsKey(ARG_SCROLL_TO_PREFERENCE)) { - String prefKey = args.getString(ARG_SCROLL_TO_PREFERENCE); - GesturePreference pref = (GesturePreference) findPreference(prefKey); - if (pref != null) { - mScrollPosition = pref.getOrder(); - } - } - } - } @Override @@ -124,9 +115,6 @@ public class GestureSettings extends SettingsPreferenceFragment implements Bundle savedInstanceState) { View view = super.onCreateView(inflater, container, savedInstanceState); RecyclerView listview = getListView(); - if (mScrollPosition >= 0) { - listview.scrollToPosition(mScrollPosition); - } listview.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { @@ -163,8 +151,10 @@ public class GestureSettings extends SettingsPreferenceFragment implements if (PREF_KEY_DOUBLE_TAP_POWER.equals(key)) { Secure.putInt(getContentResolver(), Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, enabled ? 0 : 1); - } else if (PREF_KEY_PICK_UP_AND_NUDGE.equals(key)) { - Secure.putInt(getContentResolver(), Secure.DOZE_ENABLED, enabled ? 1 : 0); + } else if (PREF_KEY_PICK_UP.equals(key)) { + Secure.putInt(getContentResolver(), Secure.DOZE_PULSE_ON_PICK_UP, enabled ? 1 : 0); + } else if (PREF_KEY_DOUBLE_TAP_SCREEN.equals(key)) { + Secure.putInt(getContentResolver(), Secure.DOZE_PULSE_ON_DOUBLE_TAP, enabled ? 1 : 0); } else if (PREF_KEY_SWIPE_DOWN_FINGERPRINT.equals(key)) { Secure.putInt(getContentResolver(), Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, enabled ? 1 : 0); @@ -255,7 +245,8 @@ public class GestureSettings extends SettingsPreferenceFragment implements result.add(PREF_KEY_DOUBLE_TAP_POWER); } if (!isDozeAvailable(context)) { - result.add(PREF_KEY_PICK_UP_AND_NUDGE); + result.add(PREF_KEY_PICK_UP); + result.add(PREF_KEY_DOUBLE_TAP_SCREEN); } if (!isSystemUINavigationAvailable(context)) { result.add(PREF_KEY_SWIPE_DOWN_FINGERPRINT); @@ -267,4 +258,4 @@ public class GestureSettings extends SettingsPreferenceFragment implements } }; -} \ No newline at end of file +} diff --git a/tests/app/Android.mk b/tests/app/Android.mk index a6416480bcc..979c27d93a5 100644 --- a/tests/app/Android.mk +++ b/tests/app/Android.mk @@ -7,15 +7,13 @@ LOCAL_CERTIFICATE := platform LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle -LOCAL_STATIC_ANDROID_LIBRARIES := \ - android-support-v4 - LOCAL_STATIC_JAVA_LIBRARIES := \ android-support-test \ mockito-target \ espresso-core \ - espresso-contrib \ - espresso-intents + espresso-contrib-nodep \ + espresso-intents-nodep \ + ub-uiautomator # Include all test java files. LOCAL_SRC_FILES := $(call all-java-files-under, src) diff --git a/tests/app/src/com/android/settings/gesture/GestureSettingsTest.java b/tests/app/src/com/android/settings/gesture/GestureSettingsTest.java new file mode 100644 index 00000000000..4f3a5247092 --- /dev/null +++ b/tests/app/src/com/android/settings/gesture/GestureSettingsTest.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2016 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.gesture; + +import android.content.Context; +import android.content.Intent; +import android.provider.Settings.Secure; +import android.support.test.filters.MediumTest; +import android.support.test.uiautomator.UiDevice; +import android.support.test.uiautomator.UiObject; +import android.support.test.uiautomator.UiSelector; +import android.support.test.uiautomator.UiScrollable; +import android.test.InstrumentationTestCase; +import android.util.Log; +import android.widget.RelativeLayout; +import android.widget.Switch; + +import com.android.settings.R; + +import java.io.BufferedReader; +import java.io.InputStreamReader; + +import org.junit.Test; + +/** + * Test for Gesture preferences. + */ +@MediumTest +public class GestureSettingsTest extends InstrumentationTestCase { + + private static final String TAG = "GestureSettingsTest"; + + private UiDevice mDevice; + private Context mTargetContext; + private String mTargetPackage; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mDevice = UiDevice.getInstance(getInstrumentation()); + mTargetContext = getInstrumentation().getTargetContext(); + mTargetPackage = mTargetContext.getPackageName(); + } + + @Test + public void testAmbientDisplaySwitchPreference() throws Exception { + launchSettings(); + UiObject dozeSwitch = getDozeSwitch(); + assertNotNull(dozeSwitch); + assertTrue(dozeSwitch.exists()); + assertToggleStateMatchesSettingValue(dozeSwitch, Secure.DOZE_ENABLED, 1, 1); + } + + @Test + public void testGestureSettingsExists() throws Exception { + launchMoves(); + UiObject titleObj = mDevice.findObject(new UiSelector().text( + mTargetContext.getResources().getString(R.string.gesture_preference_title))); + assertNotNull(titleObj); + assertTrue(titleObj.exists()); + } + + @Test + public void testCameraDoubleTapToggle() throws Exception { + assertSwitchToggle(mTargetContext.getResources().getString( + R.string.double_tap_power_for_camera_title), + Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0, 0); + } + + @Test + public void testCameraDoubleTwistToggle() throws Exception { + assertSwitchToggle(mTargetContext.getResources().getString( + R.string.double_twist_for_camera_mode_title), + Secure.CAMERA_DOUBLE_TWIST_TO_FLIP_ENABLED, 1, 1); + } + + @Test + public void testFingerprintSwipeToggle() throws Exception { + assertSwitchToggle(mTargetContext.getResources().getString( + R.string.fingerprint_swipe_for_notifications_title), + Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, 1); + } + + @Test + public void testDozeDoubleTapToggle() throws Exception { + assertSwitchToggle(mTargetContext.getResources().getString( + R.string.ambient_display_title), + Secure.DOZE_PULSE_ON_DOUBLE_TAP, 1, 1); + } + + @Test + public void testDozePickupToggle() throws Exception { + assertSwitchToggle(mTargetContext.getResources().getString( + R.string.ambient_display_pickup_title), + Secure.DOZE_PULSE_ON_PICK_UP, 1, 1); + } + + private void launchSettings() { + Intent settingsIntent = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .setPackage(mTargetPackage) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + getInstrumentation().getContext().startActivity(settingsIntent); + } + + private void launchMoves() throws Exception { + launchSettings(); + UiScrollable settings = new UiScrollable( + new UiSelector().packageName(mTargetPackage).scrollable(true)); + String titleMoves = + mTargetContext.getResources().getString(R.string.gesture_preference_title); + settings.scrollTextIntoView(titleMoves); + mDevice.findObject(new UiSelector().text(titleMoves)).click(); + } + + private void navigateToMovesSetting(String title) throws Exception { + launchMoves(); + UiScrollable moves = new UiScrollable( + new UiSelector().packageName(mTargetPackage).scrollable(true)); + moves.scrollTextIntoView(title); + } + + private UiScrollable navigateToAmbientDisplay() throws Exception { + UiScrollable settings = new UiScrollable( + new UiSelector().packageName(mTargetPackage).scrollable(true)); + String titleDisplay = + mTargetContext.getResources().getString(R.string.display_settings_title); + settings.scrollTextIntoView(titleDisplay); + mDevice.findObject(new UiSelector().text(titleDisplay)).click(); + settings.scrollTextIntoView(mTargetContext.getResources().getString(R.string.doze_title)); + return settings; + } + + private UiObject getGestureSwitch(String title) throws Exception { + UiObject titleView = mDevice.findObject(new UiSelector().text(title)); + UiObject gestureSwitch = + titleView.getFromParent(new UiSelector().className(Switch.class.getName())); + assertNotNull(gestureSwitch); + assertTrue(gestureSwitch.exists()); + return gestureSwitch; + } + + private UiObject getDozeSwitch() throws Exception { + UiScrollable settings = navigateToAmbientDisplay(); + UiObject dozeSwitch = null; + UiSelector relativeLayoutSelector = + new UiSelector().className(RelativeLayout.class.getName()); + String titleDoze = mTargetContext.getResources().getString(R.string.doze_title); + for (int i = 0; i <= settings.getChildCount(relativeLayoutSelector); i++) { + UiObject relativeLayout = settings.getChild(relativeLayoutSelector.instance(i)); + if (relativeLayout.getChildCount() != 2) { + continue; + } + UiObject obj1 = relativeLayout.getChild(new UiSelector().index(0)); + if (obj1.getText() == titleDoze) { + return relativeLayout.getFromParent( + new UiSelector().className(Switch.class.getName())); + } + } + return null; + } + + private void assertSwitchToggle(String title, String key, int defaultVal, int enabledVal) + throws Exception { + navigateToMovesSetting(title); + assertToggleStateMatchesSettingValue(getGestureSwitch(title), key, defaultVal, enabledVal); + } + + private void assertToggleStateMatchesSettingValue ( + UiObject testSwitch, String key, int defaultVal, int enabledVal) throws Exception { + // check initial state + int currentValue = Secure.getInt(mTargetContext.getContentResolver(), key, defaultVal); + boolean enabled = currentValue == enabledVal; + assertEquals(enabled, testSwitch.isChecked()); + // toggle the preference + testSwitch.click(); + assertEquals(!enabled, testSwitch.isChecked()); + int newValue = currentValue == 1 ? 0 : 1; + assertEquals(newValue, Secure.getInt(mTargetContext.getContentResolver(), key, defaultVal)); + } + +}