Added suggestions for gestures.

Bug: 30986021
Test: manual + make RunSettingsRoboTests + adb shell am instrument -w
com.android.settings.tests.unit /android.support.test.runner.AndroidJUnitRunner
Change-Id: I7337a141cb21e5a1399aaca05ec1facd8629577b
Merged-In: I7aed110c81ca2fb6b90e2f359b4bb941c02bc1c3
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 485a233..1b99566 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -3149,7 +3149,7 @@
         <activity
             android:name=".Settings$CameraLiftTriggerSuggestionActivity"
             android:label="@string/camera_lift_trigger_title"
-            android:icon="@drawable/ic_settings_camera"
+            android:icon="@drawable/ic_suggestion_gesture"
             android:enabled="@bool/config_cameraLiftTriggerAvailable">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -3160,7 +3160,7 @@
                 <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
             </intent-filter>
             <meta-data android:name="com.android.settings.dismiss"
-                       android:value="3,7,30" />
+                       android:value="4,8,30" />
             <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
                        android:value="com.android.settings.gestures.CameraLiftTriggerSettings"/>
             <meta-data android:name="com.android.settings.title"
@@ -3169,6 +3169,117 @@
                        android:resource="@string/camera_lift_trigger_suggestion_summary" />
         </activity>
 
+        <activity
+            android:name=".Settings$DoubleTapPowerSuggestionActivity"
+            android:label="@string/double_tap_power_for_camera_title"
+            android:icon="@drawable/ic_suggestion_gesture">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.GESTURE" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss"
+                       android:value="4,8,30" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.gestures.DoubleTapPowerSettings"/>
+            <meta-data android:name="com.android.settings.title"
+                       android:resource="@string/double_tap_power_for_camera_suggestion_title" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/double_tap_power_for_camera_suggestion_summary" />
+        </activity>
+
+        <activity
+            android:name=".Settings$DoubleTwistSuggestionActivity"
+            android:label="@string/double_twist_for_camera_mode_title"
+            android:icon="@drawable/ic_suggestion_gesture">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.GESTURE" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss"
+                       android:value="4,8,30" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.gestures.DoubleTwistGestureSettings"/>
+            <meta-data android:name="com.android.settings.title"
+                       android:resource="@string/double_twist_for_camera_suggestion_title" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/double_twist_for_camera_suggestion_summary" />
+        </activity>
+
+        <activity
+            android:name=".Settings$AmbientDisplaySuggestionActivity"
+            android:label="@string/ambient_display_title"
+            android:icon="@drawable/ic_suggestion_gesture">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.GESTURE" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss"
+                       android:value="9,13,30" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.gestures.DoubleTapScreenSettings"/>
+            <meta-data android:name="com.android.settings.title"
+                       android:resource="@string/ambient_display_title" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/ambient_display_suggestion_summary" />
+        </activity>
+
+        <activity
+            android:name=".Settings$AmbientDisplayPickupSuggestionActivity"
+            android:label="@string/ambient_display_pickup_title"
+            android:icon="@drawable/ic_suggestion_gesture">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.GESTURE" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss"
+                       android:value="9,13,30" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.gestures.PickupGestureSettings"/>
+            <meta-data android:name="com.android.settings.title"
+                       android:resource="@string/ambient_display_pickup_title" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/ambient_display_pickup_suggestion_summary" />
+        </activity>
+
+        <activity
+            android:name=".Settings$SwipeToNotificationSuggestionActivity"
+            android:label="@string/fingerprint_swipe_for_notifications_title"
+            android:icon="@drawable/ic_suggestion_gesture">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.GESTURE" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="com.android.settings.suggested.category.FIRST_IMPRESSION" />
+            </intent-filter>
+            <meta-data android:name="com.android.settings.dismiss"
+                       android:value="9,13,30" />
+            <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+                       android:value="com.android.settings.gestures.SwipeToNotificationSettings"/>
+            <meta-data android:name="com.android.settings.title"
+                       android:resource="@string/fingerprint_swipe_for_notifications_suggestion_title" />
+            <meta-data android:name="com.android.settings.summary"
+                       android:resource="@string/fingerprint_swipe_for_notifications_suggestion_summary" />
+        </activity>
+        <!-- End activities for moves/gestures suggestions -->
+
         <activity android:name=".applications.autofill.AutofillPickerActivity"
                 android:excludeFromRecents="true"
                 android:launchMode="singleInstance"
diff --git a/res/drawable/ic_suggestion_gesture.xml b/res/drawable/ic_suggestion_gesture.xml
new file mode 100644
index 0000000..b90ad94
--- /dev/null
+++ b/res/drawable/ic_suggestion_gesture.xml
@@ -0,0 +1,28 @@
+<!--
+    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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="32.0"
+    android:viewportHeight="32.0"
+    android:autoMirrored="true">
+    <path
+        android:fillColor="@color/material_grey_600"
+        android:pathData="M20,20.2V24H6V5.3h8.7l2.4,-4H7.6c-2.2,0 -4,1.8 -4,4v21.3c0,2.2 1.8,4 4,4h10.7c2.2,0 4,-1.8 4,-4V14.9L20,20.2zM15.6,28h-5.3v-1.3h5.3V28z"/>
+    <path
+        android:fillColor="@color/material_grey_600"
+        android:pathData="M28.5,7l1.1,-2.4L32,3.5l-2.4,-1.1L28.5,0l-1.1,2.4L25,3.5l2.4,1.1L28.5,7zM21,7.4l-2.2,-4.8l-2.2,4.8l-4.8,2.2l4.8,2.2l2.2,4.8l2.2,-4.8l4.8,-2.2L21,7.4zM28.5,12.2l-1.1,2.4L25,15.6l2.4,1.1l1.1,2.4l1.1,-2.4l2.4,-1.1l-2.4,-1.1L28.5,12.2z"/>
+</vector>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 6b8570c..c059ff1 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -147,6 +147,13 @@
     }
     public static class ScreenLockSuggestionActivity extends ChooseLockGeneric { /* empty */ }
     public static class CameraLiftTriggerSuggestionActivity extends SettingsActivity { /* empty */ }
+    public static class DoubleTapPowerSuggestionActivity extends SettingsActivity { /* empty */ }
+    public static class DoubleTwistSuggestionActivity extends SettingsActivity { /* empty */ }
+    public static class AmbientDisplaySuggestionActivity extends SettingsActivity { /* empty */ }
+    public static class AmbientDisplayPickupSuggestionActivity extends SettingsActivity {
+        /* empty */ }
+    public static class SwipeToNotificationSuggestionActivity extends SettingsActivity {
+        /* empty */ }
     public static class WallpaperSettingsActivity extends SettingsActivity { /* empty */ }
     public static class ManagedProfileSettingsActivity extends SettingsActivity { /* empty */ }
     public static class DeletionHelperActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index 638f85f..d9feae9 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -20,11 +20,24 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.support.annotation.NonNull;
 import android.util.Log;
 
+import com.android.internal.hardware.AmbientDisplayConfiguration;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.Settings.AmbientDisplayPickupSuggestionActivity;
+import com.android.settings.Settings.AmbientDisplaySuggestionActivity;
+import com.android.settings.Settings.DoubleTapPowerSuggestionActivity;
+import com.android.settings.Settings.DoubleTwistSuggestionActivity;
+import com.android.settings.Settings.SwipeToNotificationSuggestionActivity;
 import com.android.settings.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.gestures.DoubleTapPowerPreferenceController;
+import com.android.settings.gestures.DoubleTapScreenPreferenceController;
+import com.android.settings.gestures.DoubleTwistPreferenceController;
+import com.android.settings.gestures.PickupGesturePreferenceController;
+import com.android.settings.gestures.SwipeToNotificationPreferenceController;
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.support.NewDeviceIntroSuggestionActivity;
 import com.android.settingslib.drawer.Tile;
@@ -41,6 +54,7 @@
 
     private final SuggestionRanker mSuggestionRanker;
     private final MetricsFeatureProvider mMetricsFeatureProvider;
+    private final AmbientDisplayConfiguration mAmbientDisplayConfig;
 
     @Override
     public boolean isSmartSuggestionEnabled(Context context) {
@@ -52,6 +66,21 @@
         final String className = component.getClassName();
         if (className.equals(NewDeviceIntroSuggestionActivity.class.getName())) {
             return NewDeviceIntroSuggestionActivity.isSuggestionComplete(context);
+        } else if (className.equals(DoubleTapPowerSuggestionActivity.class.getName())) {
+            return DoubleTapPowerPreferenceController
+                    .isSuggestionComplete(context, getSharedPrefs(context));
+        } else if (className.equals(DoubleTwistSuggestionActivity.class.getName())) {
+            return DoubleTwistPreferenceController
+                    .isSuggestionComplete(context, getSharedPrefs(context));
+        } else if (className.equals(AmbientDisplaySuggestionActivity.class.getName())) {
+            return DoubleTapScreenPreferenceController
+                    .isSuggestionComplete(context, getSharedPrefs(context));
+        } else if (className.equals(AmbientDisplayPickupSuggestionActivity.class.getName())) {
+            return PickupGesturePreferenceController
+                    .isSuggestionComplete(context, getSharedPrefs(context));
+        } else if (className.equals(SwipeToNotificationSuggestionActivity.class.getName())) {
+            return SwipeToNotificationPreferenceController
+                    .isSuggestionComplete(context, getSharedPrefs(context));
         }
         return false;
     }
@@ -67,6 +96,7 @@
                 new SuggestionFeaturizer(new EventStore(appContext)));
         mMetricsFeatureProvider = FeatureFactory.getFactory(appContext)
                 .getMetricsFeatureProvider();
+        mAmbientDisplayConfig = new AmbientDisplayConfiguration(appContext);
     }
 
     @Override
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java b/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
index fa0da30..ae8c0a6 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionsChecks.java
@@ -130,7 +130,8 @@
 
     private boolean isCameraLiftTriggerEnabled() {
         final int triggerEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED, 0);
+                Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED,
+                Settings.Secure.CAMERA_LIFT_TRIGGER_ENABLED_DEFAULT);
         return triggerEnabled == 1;
     }
 }
diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
index d36ecc4..0cfa007 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java
@@ -17,9 +17,11 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class DoubleTapPowerPreferenceController extends GesturePreferenceController {
@@ -32,10 +34,19 @@
         mDoubleTapPowerKey = key;
     }
 
+    public static boolean isSuggestionComplete(Context context, SharedPreferences prefs) {
+        return !isGestureAvailable(context)
+                || prefs.getBoolean(DoubleTapPowerSettings.PREF_KEY_SUGGESTION_COMPLETE, false);
+    }
+
+    private static boolean isGestureAvailable(Context context) {
+        return context.getResources()
+                .getBoolean(com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
+    }
+
     @Override
     public boolean isAvailable() {
-        return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
+        return isGestureAvailable(mContext);
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettings.java b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
index d38292d..4efe3be 100644
--- a/src/com/android/settings/gestures/DoubleTapPowerSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapPowerSettings.java
@@ -17,12 +17,15 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.SearchIndexableResource;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -35,6 +38,18 @@
     private static final String TAG = "DoubleTapPower";
     private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power";
 
+    public static final String PREF_KEY_SUGGESTION_COMPLETE =
+            "pref_double_tap_power_suggestion_complete";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFactory(context)
+                .getSuggestionFeatureProvider(context);
+        SharedPreferences prefs = suggestionFeatureProvider.getSharedPrefs(context);
+        prefs.edit().putBoolean(PREF_KEY_SUGGESTION_COMPLETE, true).apply();
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_GESTURE_DOUBLE_TAP_POWER;
diff --git a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
index a38e4b6..e671f60 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenPreferenceController.java
@@ -18,10 +18,12 @@
 
 import android.annotation.UserIdInt;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class DoubleTapScreenPreferenceController extends GesturePreferenceController {
@@ -41,6 +43,12 @@
         mDoubleTapScreenPrefKey = key;
     }
 
+    public static boolean isSuggestionComplete(Context context, SharedPreferences prefs) {
+        AmbientDisplayConfiguration ambientConfig = new AmbientDisplayConfiguration(context);
+        return !ambientConfig.pulseOnDoubleTapAvailable()
+                || prefs.getBoolean(DoubleTapScreenSettings.PREF_KEY_SUGGESTION_COMPLETE, false);
+    }
+
     @Override
     public boolean isAvailable() {
         return mAmbientConfig.pulseOnDoubleTapAvailable();
diff --git a/src/com/android/settings/gestures/DoubleTapScreenSettings.java b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
index 4690ead..0cc0365 100644
--- a/src/com/android/settings/gestures/DoubleTapScreenSettings.java
+++ b/src/com/android/settings/gestures/DoubleTapScreenSettings.java
@@ -17,6 +17,7 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.UserHandle;
 import android.provider.SearchIndexableResource;
 
@@ -25,6 +26,8 @@
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -37,6 +40,18 @@
     private static final String TAG = "DoubleTapScreen";
     private static final String KEY_DOUBLE_TAP_SCREEN = "gesture_double_tap_screen";
 
+    public static final String PREF_KEY_SUGGESTION_COMPLETE =
+            "pref_double_tap_screen_suggestion_complete";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFactory(context)
+                .getSuggestionFeatureProvider(context);
+        SharedPreferences prefs = suggestionFeatureProvider.getSharedPrefs(context);
+        prefs.edit().putBoolean(PREF_KEY_SUGGESTION_COMPLETE, true).apply();
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_GESTURE_DOUBLE_TAP_SCREEN;
diff --git a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
index 2b46cce..e5fb9a0 100644
--- a/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
+++ b/src/com/android/settings/gestures/DoubleTwistGestureSettings.java
@@ -17,12 +17,15 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.SearchIndexableResource;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -35,6 +38,18 @@
     private static final String TAG = "DoubleTwistGesture";
     private static final String KEY_DOUBLE_TWIST = "gesture_double_twist";
 
+    public static final String PREF_KEY_SUGGESTION_COMPLETE =
+            "pref_double_twist_suggestion_complete";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFactory(context)
+                .getSuggestionFeatureProvider(context);
+        SharedPreferences prefs = suggestionFeatureProvider.getSharedPrefs(context);
+        prefs.edit().putBoolean(PREF_KEY_SUGGESTION_COMPLETE, true).apply();
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_GESTURE_DOUBLE_TWIST;
diff --git a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
index baf2d31..c07a37b 100644
--- a/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
+++ b/src/com/android/settings/gestures/DoubleTwistPreferenceController.java
@@ -17,6 +17,7 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
@@ -29,6 +30,7 @@
 
 import com.android.settings.R;
 import com.android.settings.Utils;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class DoubleTwistPreferenceController extends GesturePreferenceController {
@@ -43,10 +45,30 @@
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
     }
 
+    public static boolean isSuggestionComplete(Context context, SharedPreferences prefs) {
+        return !isGestureAvailable(context)
+                || prefs.getBoolean(DoubleTwistGestureSettings.PREF_KEY_SUGGESTION_COMPLETE, false);
+    }
+
+    private static boolean isGestureAvailable(Context context) {
+        final Resources resources = context.getResources();
+        final String name = resources.getString(R.string.gesture_double_twist_sensor_name);
+        final String vendor = resources.getString(R.string.gesture_double_twist_sensor_vendor);
+        if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(vendor)) {
+            final SensorManager sensorManager =
+                    (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+            for (Sensor s : sensorManager.getSensorList(Sensor.TYPE_ALL)) {
+                if (name.equals(s.getName()) && vendor.equals(s.getVendor())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
     @Override
     public boolean isAvailable() {
-        return hasSensor(R.string.gesture_double_twist_sensor_name,
-                R.string.gesture_double_twist_sensor_vendor);
+        return isGestureAvailable(mContext);
     }
 
     @Override
@@ -83,20 +105,4 @@
     int getManagedProfileUserId() {
         return Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
     }
-
-    private boolean hasSensor(int nameResId, int vendorResId) {
-        final Resources resources = mContext.getResources();
-        final String name = resources.getString(nameResId);
-        final String vendor = resources.getString(vendorResId);
-        if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(vendor)) {
-            final SensorManager sensorManager =
-                    (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
-            for (Sensor s : sensorManager.getSensorList(Sensor.TYPE_ALL)) {
-                if (name.equals(s.getName()) && vendor.equals(s.getVendor())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
 }
diff --git a/src/com/android/settings/gestures/PickupGesturePreferenceController.java b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
index a6ce1a1..6308b37 100644
--- a/src/com/android/settings/gestures/PickupGesturePreferenceController.java
+++ b/src/com/android/settings/gestures/PickupGesturePreferenceController.java
@@ -18,10 +18,12 @@
 
 import android.annotation.UserIdInt;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
 import com.android.internal.hardware.AmbientDisplayConfiguration;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class PickupGesturePreferenceController extends GesturePreferenceController {
@@ -41,6 +43,12 @@
         mPickUpPrefKey = key;
     }
 
+    public static boolean isSuggestionComplete(Context context, SharedPreferences prefs) {
+        AmbientDisplayConfiguration ambientConfig = new AmbientDisplayConfiguration(context);
+        return !ambientConfig.pulseOnPickupAvailable()
+                || prefs.getBoolean(PickupGestureSettings.PREF_KEY_SUGGESTION_COMPLETE, false);
+    }
+
     @Override
     public boolean isAvailable() {
         return mAmbientConfig.pulseOnPickupAvailable();
diff --git a/src/com/android/settings/gestures/PickupGestureSettings.java b/src/com/android/settings/gestures/PickupGestureSettings.java
index 17d930f..7cc264c 100644
--- a/src/com/android/settings/gestures/PickupGestureSettings.java
+++ b/src/com/android/settings/gestures/PickupGestureSettings.java
@@ -17,6 +17,7 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.os.UserHandle;
 import android.provider.SearchIndexableResource;
 
@@ -25,6 +26,8 @@
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -37,6 +40,18 @@
     private static final String TAG = "PickupGestureSettings";
     private static final String KEY_PICK_UP = "gesture_pick_up";
 
+    public static final String PREF_KEY_SUGGESTION_COMPLETE =
+            "pref_pickup_gesture_suggestion_complete";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFactory(context)
+                .getSuggestionFeatureProvider(context);
+        SharedPreferences prefs = suggestionFeatureProvider.getSharedPrefs(context);
+        prefs.edit().putBoolean(PREF_KEY_SUGGESTION_COMPLETE, true).apply();
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_GESTURE_PICKUP;
diff --git a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
index b760c25..d71c076 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationPreferenceController.java
@@ -17,9 +17,11 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.Settings;
 import android.support.v7.preference.Preference;
 
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
 public class SwipeToNotificationPreferenceController extends GesturePreferenceController {
@@ -33,6 +35,17 @@
         mSwipeDownFingerPrefKey = key;
     }
 
+    public static boolean isSuggestionComplete(Context context, SharedPreferences prefs) {
+        return !isGestureAvailable(context)
+                || prefs.getBoolean(SwipeToNotificationSettings.PREF_KEY_SUGGESTION_COMPLETE,
+                        false);
+    }
+
+    private static boolean isGestureAvailable(Context context) {
+        return context.getResources()
+                .getBoolean(com.android.internal.R.bool.config_supportSystemNavigationKeys);
+    }
+
     @Override
     public String getPreferenceKey() {
         return mSwipeDownFingerPrefKey;
@@ -45,8 +58,7 @@
 
     @Override
     public boolean isAvailable() {
-        return mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_supportSystemNavigationKeys);
+        return isGestureAvailable(mContext);
     }
 
     @Override
diff --git a/src/com/android/settings/gestures/SwipeToNotificationSettings.java b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
index 00d4700..05a1202 100644
--- a/src/com/android/settings/gestures/SwipeToNotificationSettings.java
+++ b/src/com/android/settings/gestures/SwipeToNotificationSettings.java
@@ -17,12 +17,15 @@
 package com.android.settings.gestures;
 
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.provider.SearchIndexableResource;
 
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.settings.R;
 import com.android.settings.core.PreferenceController;
 import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.overlay.FeatureFactory;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 
@@ -36,6 +39,18 @@
 
     private static final String KEY = "gesture_swipe_down_fingerprint";
 
+    public static final String PREF_KEY_SUGGESTION_COMPLETE =
+            "pref_swipe_to_notification_suggestion_complete";
+
+    @Override
+    public void onAttach(Context context) {
+        super.onAttach(context);
+        SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFactory(context)
+                .getSuggestionFeatureProvider(context);
+        SharedPreferences prefs = suggestionFeatureProvider.getSharedPrefs(context);
+        prefs.edit().putBoolean(PREF_KEY_SUGGESTION_COMPLETE, true).apply();
+    }
+
     @Override
     public int getMetricsCategory() {
         return MetricsProto.MetricsEvent.SETTINGS_GESTURE_SWIPE_TO_NOTIFICATION;
diff --git a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
index d5d87b1..78c1d1a 100644
--- a/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImplTest.java
@@ -16,29 +16,6 @@
 
 package com.android.settings.dashboard.suggestions;
 
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-
-import com.android.internal.logging.nano.MetricsProto;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-import com.android.settings.TestConfig;
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.drawer.Tile;
-import com.android.settingslib.suggestions.SuggestionParser;
-
-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 java.util.ArrayList;
-import java.util.List;
-
 import static com.google.common.truth.Truth.assertThat;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
@@ -49,10 +26,46 @@
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.Settings.AmbientDisplaySuggestionActivity;
+import com.android.settings.Settings.AmbientDisplayPickupSuggestionActivity;
+import com.android.settings.Settings.DoubleTapPowerSuggestionActivity;
+import com.android.settings.Settings.DoubleTwistSuggestionActivity;
+import com.android.settings.Settings.SwipeToNotificationSuggestionActivity;
+import com.android.settings.TestConfig;
+import com.android.settings.gestures.DoubleTapPowerSettings;
+import com.android.settings.gestures.DoubleTapScreenSettings;
+import com.android.settings.gestures.PickupGestureSettings;
+import com.android.settings.gestures.SwipeToNotificationSettings;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settingslib.drawer.Tile;
+import com.android.settingslib.suggestions.SuggestionParser;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+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;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SuggestionFeatureProviderImplTest {
 
+    private static final String DOUBLE_TWIST_SENSOR_NAME = "double_twist_sensor_name";
+    private static final String DOUBLE_TWIST_SENSOR_VENDOR = "double_twist_sensor_vendor";
+
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private Context mContext;
     @Mock
@@ -76,6 +89,149 @@
     }
 
     @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_doubleTapPower_trueWhenNotAvailable() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, false);
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        DoubleTapPowerSuggestionActivity.class))).isTrue();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_doubleTapPower_falseWhenNotVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, true);
+        // No stored value in shared preferences if not visited yet.
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        DoubleTapPowerSuggestionActivity.class))).isFalse();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_doubleTapPower_trueWhenVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, true);
+        mProvider.getSharedPrefs(RuntimeEnvironment.application).edit().putBoolean(
+                DoubleTapPowerSettings.PREF_KEY_SUGGESTION_COMPLETE, true).commit();
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        DoubleTapPowerSuggestionActivity.class))).isTrue();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_doubleTwist_trueWhenNotAvailable() {
+        SettingsShadowResources.overrideResource(
+                R.string.gesture_double_twist_sensor_name, "nonexistant name");
+        SettingsShadowResources.overrideResource(
+                R.string.gesture_double_twist_sensor_vendor, "nonexistant vendor");
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        DoubleTwistSuggestionActivity.class))).isTrue();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_ambientDisplay_falseWhenNotVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.string.config_dozeComponent, "foo");
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.string.config_dozeDoubleTapSensorType, "bar");
+        // No stored value in shared preferences if not visited yet.
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        AmbientDisplaySuggestionActivity.class))).isFalse();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_ambientDisplay_trueWhenVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.string.config_dozeComponent, "foo");
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.string.config_dozeDoubleTapSensorType, "bar");
+        mProvider.getSharedPrefs(RuntimeEnvironment.application).edit().putBoolean(
+                DoubleTapScreenSettings.PREF_KEY_SUGGESTION_COMPLETE, true).commit();
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        AmbientDisplaySuggestionActivity.class))).isTrue();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_ambientDisplayPickup_falseWhenNotVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.string.config_dozeComponent, "foo");
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_dozePulsePickup, true);
+        // No stored value in shared preferences if not visited yet.
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        AmbientDisplaySuggestionActivity.class))).isFalse();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_ambientDisplayPickup_trueWhenVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.string.config_dozeComponent, "foo");
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_dozePulsePickup, true);
+        mProvider.getSharedPrefs(RuntimeEnvironment.application).edit().putBoolean(
+                PickupGestureSettings.PREF_KEY_SUGGESTION_COMPLETE, true).commit();
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        AmbientDisplayPickupSuggestionActivity.class))).isTrue();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_swipeToNotification_trueWhenNotAvailable() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_supportSystemNavigationKeys, false);
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        SwipeToNotificationSuggestionActivity.class))).isTrue();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_swipeToNotification_falseWhenNotVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_supportSystemNavigationKeys, true);
+        // No stored value in shared preferences if not visited yet.
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        SwipeToNotificationSuggestionActivity.class))).isFalse();
+    }
+
+    @Test
+    @Config(shadows = SettingsShadowResources.class)
+    public void isSuggestionCompleted_swipeToNotification_trueWhenVisited() {
+        SettingsShadowResources.overrideResource(
+                com.android.internal.R.bool.config_supportSystemNavigationKeys, true);
+        mProvider.getSharedPrefs(RuntimeEnvironment.application).edit().putBoolean(
+                SwipeToNotificationSettings.PREF_KEY_SUGGESTION_COMPLETE, true).commit();
+
+        assertThat(mProvider.isSuggestionCompleted(RuntimeEnvironment.application,
+                new ComponentName(RuntimeEnvironment.application,
+                        SwipeToNotificationSuggestionActivity.class))).isTrue();
+    }
+
+    @Test
     public void dismissSuggestion_noParserOrSuggestion_noop() {
         mProvider.dismissSuggestion(mContext, null, null);
         mProvider.dismissSuggestion(mContext, mSuggestionParser, null);