Merge "Import translations. DO NOT MERGE"
diff --git a/res/layout/search_panel.xml b/res/layout/search_panel.xml
new file mode 100644
index 0000000..22f2b52
--- /dev/null
+++ b/res/layout/search_panel.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/dashboard"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+    <LinearLayout android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:layout_gravity="center"
+            android:orientation="vertical">
+
+        <LinearLayout android:id="@+id/layout_suggestions"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:orientation="vertical">
+
+            <TextView android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:singleLine="true"
+                      android:ellipsize="marquee"
+                      android:fadingEdge="horizontal"
+                      android:textAppearance="?android:attr/textAppearanceMedium"
+                      android:text="@string/search_recents_queries_label"/>
+
+            <ListView android:id="@+id/list_suggestions"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent" />
+
+            <ImageView android:src="?android:attr/dividerHorizontal"
+                       android:layout_width="fill_parent"
+                       android:layout_height="wrap_content"
+                       android:scaleType="fitXY"
+                       android:paddingBottom="2dp"
+                       android:paddingTop="2dp" />
+
+        </LinearLayout>
+
+        <LinearLayout android:id="@+id/layout_results"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                android:orientation="vertical"
+                android:layout_weight="1" >
+
+            <TextView android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:singleLine="true"
+                      android:ellipsize="marquee"
+                      android:fadingEdge="horizontal"
+                      android:textAppearance="?android:attr/textAppearanceMedium"
+                      android:text="@string/search_results_label"/>
+
+            <ListView android:id="@+id/list_results"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    />
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</FrameLayout>
diff --git a/res/layout/search_results.xml b/res/layout/search_results.xml
deleted file mode 100644
index a833404..0000000
--- a/res/layout/search_results.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/dashboard"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout android:layout_width="match_parent"
-                  android:layout_height="match_parent"
-                  android:layout_gravity="center"
-                  android:orientation="vertical">
-
-        <ListView android:id="@+id/list_results"
-                      android:layout_width="match_parent"
-                      android:layout_height="match_parent"/>
-
-    </LinearLayout>
-
-</FrameLayout>
diff --git a/res/layout/search_suggestion_item.xml b/res/layout/search_suggestion_item.xml
new file mode 100644
index 0000000..c099892
--- /dev/null
+++ b/res/layout/search_suggestion_item.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:minHeight="?android:attr/listPreferredItemHeight"
+              android:gravity="center_vertical"
+              android:paddingStart="@*android:dimen/preference_item_padding_side"
+              android:paddingEnd="?android:attr/scrollbarSize">
+
+    <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:gravity="center"
+            android:minWidth="@*android:dimen/preference_icon_minWidth"
+            android:orientation="horizontal">
+
+        <ImageView
+                android:id="@+id/icon"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
+                android:layout_gravity="center"
+                android:minWidth="48dp"
+                android:scaleType="centerInside"
+                android:layout_marginEnd="@*android:dimen/preference_item_padding_inner"
+                />
+
+    </LinearLayout>
+
+    <RelativeLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:paddingEnd="@*android:dimen/preference_item_padding_inner"
+            android:paddingTop="6dip"
+            android:paddingBottom="6dip">
+
+        <TextView android:id="@+id/title"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:singleLine="true"
+                  android:textAppearance="?android:attr/textAppearanceMedium"
+                  android:ellipsize="marquee"
+                  android:fadingEdge="horizontal" />
+
+    </RelativeLayout>
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index dd980f9..4db22e3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5024,21 +5024,26 @@
     <!-- Text used as a search hint into the search box -->
     <string name="query_hint_text">Search settings</string>
 
+    <!-- Text used to identify the search query suggestions / recent searches -->
+    <string name="search_recents_queries_label">Recent searches</string>
+    <!-- Text used to identify the search results -->
+    <string name="search_results_label">Results</string>
+
     <!--Search Keywords-->
     <string name="keywords_wifi">wifi wi-fi network connection</string>
 
     <!-- Notifications on lockscreen -->
     <!-- Label for checkbox controlling the contents of notifications shown on
          the secure lockscreen [CHAR LIMIT=25] -->
-    <string name="lock_screen_notifications">Show on lock screen</string>
+    <string name="lock_screen_notifications">When device is locked</string>
     <!-- Summary for lock_screen_notifications: sensitive information will be
          hidden or redacted from notifications shown on a secure lock screen
          [CHAR LIMIT=50] -->
-    <string name="lock_screen_notifications_summary_off">Unless content is sensitive</string>
+    <string name="lock_screen_notifications_summary_hide">Hide sensitive notification content</string>
     <!-- Summary for lock_screen_notifications: all information will be
          shown in notifications shown on a secure lock screen
          [CHAR LIMIT=50] -->
-    <string name="lock_screen_notifications_summary_on">All notifications</string>
+    <string name="lock_screen_notifications_summary_show">Show all notification content</string>
 
     <!-- [CHAR LIMIT=30] Notification settings screen, setting option name -->
     <string name="title_zen_mode">Do not disturb</string>
diff --git a/res/xml/notification_settings.xml b/res/xml/notification_settings.xml
index 51b153e..8cc1069 100644
--- a/res/xml/notification_settings.xml
+++ b/res/xml/notification_settings.xml
@@ -36,11 +36,9 @@
             android:title="@string/heads_up_enabled_title"
             android:persistent="false" />
 
-    <CheckBoxPreference
+    <com.android.settings.notification.DropDownPreference
             android:key="toggle_lock_screen_notifications"
             android:title="@string/lock_screen_notifications"
-            android:summaryOff="@string/lock_screen_notifications_summary_off"
-            android:summaryOn="@string/lock_screen_notifications_summary_on"
             android:persistent="false" />
 
     <PreferenceScreen
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 964c444..4c3e2bc 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -1280,6 +1280,7 @@
             mSearchResultsFragment = (SearchResultsSummary) switchToFragment(
                     SearchResultsSummary.class.getName(), null, false, true, title, true);
         }
+        mSearchResultsFragment.setSearchView(mSearchView);
         mSearchMenuItemExpanded = true;
     }
 
diff --git a/src/com/android/settings/dashboard/SearchResultsSummary.java b/src/com/android/settings/dashboard/SearchResultsSummary.java
index a7076ea..89e33f6 100644
--- a/src/com/android/settings/dashboard/SearchResultsSummary.java
+++ b/src/com/android/settings/dashboard/SearchResultsSummary.java
@@ -28,7 +28,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
 import android.os.Bundle;
-import android.os.Handler;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.LayoutInflater;
@@ -38,6 +37,7 @@
 import android.widget.BaseAdapter;
 import android.widget.ImageView;
 import android.widget.ListView;
+import android.widget.SearchView;
 import android.widget.TextView;
 import com.android.settings.R;
 import com.android.settings.SettingsActivity;
@@ -54,17 +54,23 @@
 
     private static final String LOG_TAG = "SearchResultsSummary";
 
+    private static final String EMPTY_QUERY = "";
     private static char ELLIPSIS = '\u2026';
 
-    private ListView mListView;
+    private SearchView mSearchView;
 
-    private SearchResultsAdapter mAdapter;
+    private ListView mResultsListView;
+    private SearchResultsAdapter mResultsAdapter;
     private UpdateSearchResultsTask mUpdateSearchResultsTask;
 
-    private String mQuery;
-    private SaveSearchQueryTask mSaveSearchQueryTask;
+    private ListView mSuggestionsListView;
+    private SuggestionsAdapter mSuggestionsAdapter;
+    private UpdateSuggestionsTask mUpdateSuggestionsTask;
 
-    private static long MAX_SAVED_SEARCH_QUERY = 5;
+    private ViewGroup mLayoutSuggestions;
+    private ViewGroup mLayoutResults;
+
+    private String mQuery;
 
     /**
      * A basic AsyncTask for updating the query results cursor
@@ -78,7 +84,7 @@
         @Override
         protected void onPostExecute(Cursor cursor) {
             if (!isCancelled()) {
-                setCursor(cursor);
+                setResultsCursor(cursor);
             } else if (cursor != null) {
                 cursor.close();
             }
@@ -86,37 +92,21 @@
     }
 
     /**
-     * A basic AsynTask for saving the Search query into the database
+     * A basic AsyncTask for updating the suggestions cursor
      */
-    private class SaveSearchQueryTask extends AsyncTask<String, Void, Long> {
+    private class UpdateSuggestionsTask extends AsyncTask<String, Void, Cursor> {
+        @Override
+        protected Cursor doInBackground(String... params) {
+            return Index.getInstance(getActivity()).getSuggestions(params[0]);
+        }
 
         @Override
-        protected Long doInBackground(String... params) {
-            final long now = new Date().getTime();
-
-            final ContentValues values = new ContentValues();
-            values.put(SavedQueriesColums.QUERY, params[0]);
-            values.put(SavedQueriesColums.TIME_STAMP, now);
-
-            SQLiteDatabase database = IndexDatabaseHelper.getInstance(
-                    getActivity()).getWritableDatabase();
-
-            long lastInsertedRowId = -1;
-            try {
-                lastInsertedRowId =
-                        database.insert(Tables.TABLE_SAVED_QUERIES, null, values);
-
-                final long delta = lastInsertedRowId - MAX_SAVED_SEARCH_QUERY;
-                if (delta > 0) {
-                    int count = database.delete(Tables.TABLE_SAVED_QUERIES, "rowId <= ?",
-                            new String[] { Long.toString(delta) });
-                    Log.d(LOG_TAG, "Deleted '" + count + "' saved Search query(ies)");
-                }
-            } catch (Exception e) {
-                Log.d(LOG_TAG, "Cannot update saved Search queries", e);
+        protected void onPostExecute(Cursor cursor) {
+            if (!isCancelled()) {
+                setSuggestionsCursor(cursor);
+            } else if (cursor != null) {
+                cursor.close();
             }
-
-            return lastInsertedRowId;
         }
     }
 
@@ -124,22 +114,30 @@
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
-        mAdapter = new SearchResultsAdapter(getActivity());
+        mResultsAdapter = new SearchResultsAdapter(getActivity());
+        mSuggestionsAdapter = new SuggestionsAdapter(getActivity());
     }
 
     @Override
     public void onStop() {
         super.onStop();
 
+        clearSuggestions();
         clearResults();
     }
 
     @Override
     public void onDestroy() {
-        mListView = null;
-        mAdapter = null;
+        mResultsListView = null;
+        mResultsAdapter = null;
         mUpdateSearchResultsTask = null;
 
+        mSuggestionsListView = null;
+        mSuggestionsAdapter = null;
+        mUpdateSuggestionsTask = null;
+
+        mSearchView = null;
+
         super.onDestroy();
     }
 
@@ -147,14 +145,17 @@
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                              Bundle savedInstanceState) {
 
-        final View view = inflater.inflate(R.layout.search_results, container, false);
+        final View view = inflater.inflate(R.layout.search_panel, container, false);
 
-        mListView = (ListView) view.findViewById(R.id.list_results);
-        mListView.setAdapter(mAdapter);
-        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+        mLayoutSuggestions = (ViewGroup) view.findViewById(R.id.layout_suggestions);
+        mLayoutResults = (ViewGroup) view.findViewById(R.id.layout_results);
+
+        mResultsListView = (ListView) view.findViewById(R.id.list_results);
+        mResultsListView.setAdapter(mResultsAdapter);
+        mResultsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             @Override
             public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
-                final Cursor cursor = mAdapter.mCursor;
+                final Cursor cursor = mResultsAdapter.mCursor;
                 cursor.moveToPosition(position);
 
                 final String className = cursor.getString(Index.COLUMN_INDEX_CLASS_NAME);
@@ -192,33 +193,85 @@
             }
         });
 
+        mSuggestionsListView = (ListView) view.findViewById(R.id.list_suggestions);
+        mSuggestionsListView.setAdapter(mSuggestionsAdapter);
+        mSuggestionsListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                final Cursor cursor = mSuggestionsAdapter.mCursor;
+                cursor.moveToPosition(position);
+
+                mQuery = cursor.getString(0);
+                mSearchView.setQuery(mQuery, false);
+                setSuggestionsVisibility(false);
+            }
+        });
+
         return view;
     }
 
-    private void saveQueryToDatabase() {
-        if (mSaveSearchQueryTask != null) {
-            mSaveSearchQueryTask.cancel(false);
-            mSaveSearchQueryTask = null;
-        }
-        if (!TextUtils.isEmpty(mQuery)) {
-            mSaveSearchQueryTask = new SaveSearchQueryTask();
-            mSaveSearchQueryTask.execute(mQuery);
+    @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+
+        showSomeSuggestions();
+    }
+
+    public void setSearchView(SearchView searchView) {
+        mSearchView = searchView;
+    }
+
+    private void setSuggestionsVisibility(boolean visible) {
+        if (mLayoutSuggestions != null) {
+            mLayoutSuggestions.setVisibility(visible ? View.VISIBLE : View.GONE);
         }
     }
 
+    private void setResultsVisibility(boolean visible) {
+        if (mLayoutResults != null) {
+            mLayoutResults.setVisibility(visible ? View.VISIBLE : View.GONE);
+        }
+    }
+
+    private void saveQueryToDatabase() {
+        Index.getInstance(getActivity()).addSavedQuery(mQuery);
+    }
+
     public boolean onQueryTextSubmit(String query) {
-        updateSearchResults(query);
+        mQuery = getFilteredQueryString(query);
+        updateSearchResults();
         return true;
     }
 
     public boolean onQueryTextChange(String query) {
-        updateSearchResults(query);
+        mQuery = getFilteredQueryString(query);
+        updateSuggestions();
+        updateSearchResults();
         return true;
     }
 
-    public boolean onClose() {
-        clearResults();
-        return false;
+    public void showSomeSuggestions() {
+        setResultsVisibility(false);
+        mQuery = EMPTY_QUERY;
+        updateSuggestions();
+    }
+
+    private void clearSuggestions() {
+        if (mUpdateSuggestionsTask != null) {
+            mUpdateSuggestionsTask.cancel(false);
+            mUpdateSuggestionsTask = null;
+        }
+        setSuggestionsCursor(null);
+    }
+
+    private void setSuggestionsCursor(Cursor cursor) {
+        if (mSuggestionsAdapter == null) {
+            return;
+        }
+        Cursor oldCursor = mSuggestionsAdapter.swapCursor(cursor);
+        if (oldCursor != null) {
+            oldCursor.close();
+        }
     }
 
     private void clearResults() {
@@ -226,20 +279,23 @@
             mUpdateSearchResultsTask.cancel(false);
             mUpdateSearchResultsTask = null;
         }
-        setCursor(null);
+        setResultsCursor(null);
     }
 
-    private void setCursor(Cursor cursor) {
-        if (mAdapter == null) {
+    private void setResultsCursor(Cursor cursor) {
+        if (mResultsAdapter == null) {
             return;
         }
-        Cursor oldCursor = mAdapter.swapCursor(cursor);
+        Cursor oldCursor = mResultsAdapter.swapCursor(cursor);
         if (oldCursor != null) {
             oldCursor.close();
         }
     }
 
     private String getFilteredQueryString(CharSequence query) {
+        if (query == null) {
+            return null;
+        }
         final StringBuilder filtered = new StringBuilder();
         for (int n = 0; n < query.length(); n++) {
             char c = query.charAt(n);
@@ -251,20 +307,123 @@
         return filtered.toString();
     }
 
-    private void updateSearchResults(CharSequence cs) {
+    private void updateSuggestions() {
+        if (mUpdateSuggestionsTask != null) {
+            mUpdateSuggestionsTask.cancel(false);
+            mUpdateSuggestionsTask = null;
+        }
+        if (mQuery == null) {
+            setSuggestionsCursor(null);
+        } else {
+            setSuggestionsVisibility(true);
+            mUpdateSuggestionsTask = new UpdateSuggestionsTask();
+            mUpdateSuggestionsTask.execute(mQuery);
+        }
+    }
+
+    private void updateSearchResults() {
         if (mUpdateSearchResultsTask != null) {
             mUpdateSearchResultsTask.cancel(false);
             mUpdateSearchResultsTask = null;
         }
-        mQuery = getFilteredQueryString(cs);
         if (TextUtils.isEmpty(mQuery)) {
-            setCursor(null);
+            setResultsVisibility(false);
+            setResultsCursor(null);
         } else {
+            setResultsVisibility(true);
             mUpdateSearchResultsTask = new UpdateSearchResultsTask();
             mUpdateSearchResultsTask.execute(mQuery);
         }
     }
 
+    private static class SuggestionItem {
+        public String query;
+
+        public SuggestionItem(String query) {
+            this.query = query;
+        }
+    }
+
+    private static class SuggestionsAdapter extends BaseAdapter {
+
+        private static final int COLUMN_SUGGESTION_QUERY = 0;
+        private static final int COLUMN_SUGGESTION_TIMESTAMP = 1;
+
+        private Context mContext;
+        private Cursor mCursor;
+        private LayoutInflater mInflater;
+        private boolean mDataValid = false;
+
+        public SuggestionsAdapter(Context context) {
+            mContext = context;
+            mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mDataValid = false;
+        }
+
+        public Cursor swapCursor(Cursor newCursor) {
+            if (newCursor == mCursor) {
+                return null;
+            }
+            Cursor oldCursor = mCursor;
+            mCursor = newCursor;
+            if (newCursor != null) {
+                mDataValid = true;
+                notifyDataSetChanged();
+            } else {
+                mDataValid = false;
+                notifyDataSetInvalidated();
+            }
+            return oldCursor;
+        }
+
+        @Override
+        public int getCount() {
+            if (!mDataValid || mCursor == null || mCursor.isClosed()) return 0;
+            return mCursor.getCount();
+        }
+
+        @Override
+        public Object getItem(int position) {
+            if (mDataValid && mCursor.moveToPosition(position)) {
+                final String query = mCursor.getString(COLUMN_SUGGESTION_QUERY);
+
+                return new SuggestionItem(query);
+            }
+            return null;
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return 0;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (!mDataValid && convertView == null) {
+                throw new IllegalStateException(
+                        "this should only be called when the cursor is valid");
+            }
+            if (!mCursor.moveToPosition(position)) {
+                throw new IllegalStateException("couldn't move cursor to position " + position);
+            }
+
+            View view;
+
+            if (convertView == null) {
+                view = mInflater.inflate(R.layout.search_suggestion_item, parent, false);
+            } else {
+                view = convertView;
+            }
+
+            TextView query = (TextView) view.findViewById(R.id.title);
+
+            SuggestionItem item = (SuggestionItem) getItem(position);
+            query.setText(item.query);
+
+            return view;
+        }
+    }
+
     private static class SearchResult {
         public Context context;
         public String title;
@@ -288,10 +447,10 @@
 
     private static class SearchResultsAdapter extends BaseAdapter {
 
+        private Context mContext;
         private Cursor mCursor;
         private LayoutInflater mInflater;
         private boolean mDataValid;
-        private Context mContext;
         private HashMap<String, Context> mContextMap = new HashMap<String, Context>();
 
         private static final String PERCENT_RECLACE = "%s";
@@ -299,7 +458,7 @@
 
         public SearchResultsAdapter(Context context) {
             mContext = context;
-            mInflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
             mDataValid = false;
         }
 
diff --git a/src/com/android/settings/notification/DropDownPreference.java b/src/com/android/settings/notification/DropDownPreference.java
new file mode 100644
index 0000000..15452a1
--- /dev/null
+++ b/src/com/android/settings/notification/DropDownPreference.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2014 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.notification;
+
+import android.content.Context;
+import android.preference.Preference;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+
+public class DropDownPreference extends Preference {
+    private final Context mContext;
+    private final ArrayAdapter<String> mAdapter;
+    private final Spinner mSpinner;
+
+    private Callback mCallback;
+
+    public DropDownPreference(Context context) {
+        this(context, null);
+    }
+
+    public DropDownPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mContext = context;
+        mAdapter = new ArrayAdapter<String>(mContext,
+                android.R.layout.simple_spinner_dropdown_item);
+
+        mSpinner = new Spinner(mContext);
+
+        mSpinner.setVisibility(View.INVISIBLE);
+        mSpinner.setAdapter(mAdapter);
+        mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
+                setSelectedItem(position);
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+                // noop
+            }
+        });
+        setPersistent(false);
+        setOnPreferenceClickListener(new OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                mSpinner.performClick();
+                return true;
+            }
+        });
+    }
+
+    public void setDropDownWidth(int dimenResId) {
+        mSpinner.setDropDownWidth(mContext.getResources().getDimensionPixelSize(dimenResId));
+    }
+
+    public void setCallback(Callback callback) {
+        mCallback = callback;
+    }
+
+    public void setSelectedItem(int position) {
+        if (mCallback != null && !mCallback.onItemSelected(position)) {
+            return;
+        }
+        mSpinner.setSelection(position);
+        setSummary(mAdapter.getItem(position));
+        final boolean disableDependents = position == 0;
+        notifyDependencyChange(disableDependents);
+    }
+
+    public void addItem(int resId) {
+        mAdapter.add(mContext.getResources().getString(resId));
+    }
+
+    @Override
+    protected void onBindView(View view) {
+        super.onBindView(view);
+        if (view.equals(mSpinner.getParent())) return;
+        if (mSpinner.getParent() != null) {
+            ((ViewGroup)mSpinner.getParent()).removeView(mSpinner);
+        }
+        final ViewGroup vg = (ViewGroup)view;
+        vg.addView(mSpinner, 0);
+        final ViewGroup.LayoutParams lp = mSpinner.getLayoutParams();
+        lp.width = 0;
+        mSpinner.setLayoutParams(lp);
+    }
+
+    public interface Callback {
+        boolean onItemSelected(int pos);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java
index 24863cd..2d613e4 100644
--- a/src/com/android/settings/notification/NotificationSettings.java
+++ b/src/com/android/settings/notification/NotificationSettings.java
@@ -57,7 +57,7 @@
 
     private Preference mNotificationSoundPreference;
     private Preference mNotificationAccess;
-    private TwoStatePreference mLockscreenNotifications;
+    private DropDownPreference mLockscreenNotifications;
     private TwoStatePreference mHeadsUp;
     private TwoStatePreference mNotificationPulse;
 
@@ -113,12 +113,24 @@
         refreshNotificationListeners();
 
         mLockscreenNotifications
-                = (TwoStatePreference) root.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS);
+                = (DropDownPreference) root.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS);
         if (mLockscreenNotifications != null) {
             if (!getDeviceLockscreenNotificationsEnabled()) {
                 root.removePreference(mLockscreenNotifications);
             } else {
-                mLockscreenNotifications.setChecked(getLockscreenAllowPrivateNotifications());
+                mLockscreenNotifications.addItem(R.string.lock_screen_notifications_summary_show);
+                mLockscreenNotifications.addItem(R.string.lock_screen_notifications_summary_hide);
+                final int pos = getLockscreenAllowPrivateNotifications() ? 0 : 1;
+                mLockscreenNotifications.setSelectedItem(pos);
+                mLockscreenNotifications.setCallback(new DropDownPreference.Callback() {
+                    @Override
+                    public boolean onItemSelected(int pos) {
+                        final int val = pos == 0 ? 1 : 0;
+                        Settings.Secure.putInt(getContentResolver(),
+                                Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, val);
+                        return true;
+                    }
+                });
             }
         }
 
@@ -164,11 +176,7 @@
     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
         final String key = preference.getKey();
 
-        if (KEY_LOCK_SCREEN_NOTIFICATIONS.equals(key)) {
-            Settings.Secure.putInt(getContentResolver(),
-                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
-                    mLockscreenNotifications.isChecked() ? 1 : 0);
-        } else if (KEY_HEADS_UP.equals(key)) {
+        if (KEY_HEADS_UP.equals(key)) {
             setHeadsUpMode(getContentResolver(), mHeadsUp.isChecked());
         } else if (KEY_NOTIFICATION_PULSE.equals(key)) {
             Settings.System.putInt(getContentResolver(),
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index d7d25cf..050d2e9 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -47,12 +47,8 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.ArrayAdapter;
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
-import android.widget.Spinner;
 import android.widget.Switch;
 import android.widget.TextView;
 import android.widget.TimePicker;
@@ -144,6 +140,7 @@
         mStarred = new DropDownPreference(mContext);
         mStarred.setEnabled(false);
         mStarred.setTitle(R.string.zen_mode_from);
+        mStarred.setDropDownWidth(R.dimen.zen_mode_dropdown_width);
         mStarred.addItem(R.string.zen_mode_from_anyone);
         mStarred.addItem(R.string.zen_mode_from_starred);
         mStarred.addItem(R.string.zen_mode_from_contacts);
@@ -168,6 +165,7 @@
         mWhen = new DropDownPreference(mContext);
         mWhen.setKey(KEY_WHEN);
         mWhen.setTitle(R.string.zen_mode_when);
+        mWhen.setDropDownWidth(R.dimen.zen_mode_dropdown_width);
         mWhen.addItem(R.string.zen_mode_when_never);
         mWhen.addItem(R.string.zen_mode_when_every_night);
         mWhen.addItem(R.string.zen_mode_when_weeknights);
@@ -462,80 +460,4 @@
             boolean onSetTime(int hour, int minute);
         }
     }
-
-    private static class DropDownPreference extends Preference {
-        private final Context mContext;
-        private final ArrayAdapter<String> mAdapter;
-        private final Spinner mSpinner;
-
-        private Callback mCallback;
-
-        public DropDownPreference(Context context) {
-            super(context);
-            mContext = context;
-            mAdapter = new ArrayAdapter<String>(mContext,
-                    android.R.layout.simple_spinner_dropdown_item);
-
-            mSpinner = new Spinner(mContext);
-            mSpinner.setDropDownWidth(mContext.getResources()
-                    .getDimensionPixelSize(R.dimen.zen_mode_dropdown_width));
-            mSpinner.setVisibility(View.INVISIBLE);
-            mSpinner.setAdapter(mAdapter);
-            mSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
-                @Override
-                public void onItemSelected(AdapterView<?> parent, View v, int position, long id) {
-                    setSelectedItem(position);
-                }
-
-                @Override
-                public void onNothingSelected(AdapterView<?> parent) {
-                    // noop
-                }
-            });
-            setPersistent(false);
-            setOnPreferenceClickListener(new OnPreferenceClickListener() {
-                @Override
-                public boolean onPreferenceClick(Preference preference) {
-                    mSpinner.performClick();
-                    return true;
-                }
-            });
-        }
-
-        public void setCallback(Callback callback) {
-            mCallback = callback;
-        }
-
-        public void setSelectedItem(int position) {
-            if (mCallback != null && !mCallback.onItemSelected(position)) {
-                return;
-            }
-            mSpinner.setSelection(position);
-            setSummary(mAdapter.getItem(position));
-            final boolean disableDependents = position == 0;
-            notifyDependencyChange(disableDependents);
-        }
-
-        public void addItem(int resId) {
-            mAdapter.add(mContext.getResources().getString(resId));
-        }
-
-        @Override
-        protected void onBindView(View view) {
-            super.onBindView(view);
-            if (view.equals(mSpinner.getParent())) return;
-            if (mSpinner.getParent() != null) {
-                ((ViewGroup)mSpinner.getParent()).removeView(mSpinner);
-            }
-            final ViewGroup vg = (ViewGroup)view;
-            vg.addView(mSpinner, 0);
-            final ViewGroup.LayoutParams lp = mSpinner.getLayoutParams();
-            lp.width = 0;
-            mSpinner.setLayoutParams(lp);
-        }
-
-        public interface Callback {
-            boolean onItemSelected(int pos);
-        }
-    }
 }
diff --git a/src/com/android/settings/search/Index.java b/src/com/android/settings/search/Index.java
index 4f5aa2c..60660c1 100644
--- a/src/com/android/settings/search/Index.java
+++ b/src/com/android/settings/search/Index.java
@@ -47,6 +47,7 @@
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -131,6 +132,11 @@
             IndexColumns.DATA_KEYWORDS
     };
 
+    // Max number of saved search queries (who will be used for proposing suggestions)
+    private static long MAX_SAVED_SEARCH_QUERY = 64;
+    // Max number of proposed suggestions
+    private static final int MAX_PROPOSED_SUGGESTIONS = 5;
+
     private static final String EMPTY = "";
     private static final String NON_BREAKING_HYPHEN = "\u2011";
     private static final String HYPHEN = "-";
@@ -144,6 +150,7 @@
 
     private static final List<String> EMPTY_LIST = Collections.<String>emptyList();
 
+
     private static Index sInstance;
     private final AtomicBoolean mIsAvailable = new AtomicBoolean(false);
     private final UpdateData mDataToProcess = new UpdateData();
@@ -198,11 +205,57 @@
     }
 
     public Cursor search(String query) {
-        final String sql = buildSQL(query);
-        Log.d(LOG_TAG, "Query: " + sql);
+        final String sql = buildSearchSQL(query);
+        Log.d(LOG_TAG, "Search query: " + sql);
         return getReadableDatabase().rawQuery(sql, null);
     }
 
+    public Cursor getSuggestions(String query) {
+        final String sql = buildSuggestionsSQL(query);
+        Log.d(LOG_TAG, "Suggestions query: " + sql);
+        return getReadableDatabase().rawQuery(sql, null);
+    }
+
+    private String buildSuggestionsSQL(String query) {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append("SELECT ");
+        sb.append(IndexDatabaseHelper.SavedQueriesColums.QUERY);
+        sb.append(" FROM ");
+        sb.append(Tables.TABLE_SAVED_QUERIES);
+
+        if (TextUtils.isEmpty(query)) {
+            sb.append(" ORDER BY rowId DESC");
+        } else {
+            sb.append(" WHERE ");
+            sb.append(IndexDatabaseHelper.SavedQueriesColums.QUERY);
+            sb.append(" LIKE ");
+            sb.append("'");
+            sb.append(query);
+            sb.append("%");
+            sb.append("'");
+        }
+
+        sb.append(" LIMIT ");
+        sb.append(MAX_PROPOSED_SUGGESTIONS);
+
+        return sb.toString();
+    }
+
+    public long addSavedQuery(String query){
+        final SaveSearchQueryTask task = new SaveSearchQueryTask();
+        task.execute(query);
+        try {
+            return task.get();
+        } catch (InterruptedException e) {
+            Log.e(LOG_TAG, "Cannot insert saved query: " + query, e);
+            return -1 ;
+        } catch (ExecutionException e) {
+            Log.e(LOG_TAG, "Cannot insert saved query: " + query, e);
+            return -1;
+        }
+    }
+
     public boolean update() {
         final Intent intent = new Intent(SearchIndexablesContract.PROVIDER_INTERFACE);
         List<ResolveInfo> list =
@@ -432,10 +485,10 @@
                 mDataToProcess.clear();
                 return result;
             } catch (InterruptedException e) {
-                Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
+                Log.e(LOG_TAG, "Cannot update index", e);
                 return false;
             } catch (ExecutionException e) {
-                Log.e(LOG_TAG, "Cannot update index: " + e.getMessage());
+                Log.e(LOG_TAG, "Cannot update index", e);
                 return false;
             }
         }
@@ -545,15 +598,15 @@
         }
     }
 
-    private String buildSQL(String query) {
+    private String buildSearchSQL(String query) {
         StringBuilder sb = new StringBuilder();
-        sb.append(buildSQLForColumn(query, MATCH_COLUMNS));
+        sb.append(buildSearchSQLForColumn(query, MATCH_COLUMNS));
         sb.append(" ORDER BY ");
         sb.append(IndexColumns.DATA_RANK);
         return sb.toString();
     }
 
-    private String buildSQLForColumn(String query, String[] columnNames) {
+    private String buildSearchSQLForColumn(String query, String[] columnNames) {
         StringBuilder sb = new StringBuilder();
         sb.append("SELECT ");
         for (int n = 0; n < SELECT_COLUMNS.length; n++) {
@@ -565,15 +618,16 @@
         sb.append(" FROM ");
         sb.append(Tables.TABLE_PREFS_INDEX);
         sb.append(" WHERE ");
-        sb.append(buildWhereStringForColumns(query, columnNames));
+        sb.append(buildSearchWhereStringForColumns(query, columnNames));
 
         return sb.toString();
     }
 
-    private String buildWhereStringForColumns(String query, String[] columnNames) {
+    private String buildSearchWhereStringForColumns(String query, String[] columnNames) {
         final StringBuilder sb = new StringBuilder(Tables.TABLE_PREFS_INDEX);
         sb.append(" MATCH ");
-        DatabaseUtils.appendEscapedSQLString(sb, buildMatchStringForColumns(query, columnNames));
+        DatabaseUtils.appendEscapedSQLString(sb,
+                buildSearchMatchStringForColumns(query, columnNames));
         sb.append(" AND ");
         sb.append(IndexColumns.LOCALE);
         sb.append(" = ");
@@ -584,7 +638,7 @@
         return sb.toString();
     }
 
-    private String buildMatchStringForColumns(String query, String[] columnNames) {
+    private String buildSearchMatchStringForColumns(String query, String[] columnNames) {
         final String value = query + "*";
         StringBuilder sb = new StringBuilder();
         final int count = columnNames.length;
@@ -1144,4 +1198,38 @@
             return result;
         }
     }
+
+    /**
+     * A basic AsynTask for saving a Search query into the database
+     */
+    private class SaveSearchQueryTask extends AsyncTask<String, Void, Long> {
+
+        @Override
+        protected Long doInBackground(String... params) {
+            final long now = new Date().getTime();
+
+            final ContentValues values = new ContentValues();
+            values.put(IndexDatabaseHelper.SavedQueriesColums.QUERY, params[0]);
+            values.put(IndexDatabaseHelper.SavedQueriesColums.TIME_STAMP, now);
+
+            final SQLiteDatabase database = getWritableDatabase();
+
+            long lastInsertedRowId = -1;
+            try {
+                lastInsertedRowId =
+                        database.replaceOrThrow(Tables.TABLE_SAVED_QUERIES, null, values);
+
+                final long delta = lastInsertedRowId - MAX_SAVED_SEARCH_QUERY;
+                if (delta > 0) {
+                    int count = database.delete(Tables.TABLE_SAVED_QUERIES, "rowId <= ?",
+                            new String[] { Long.toString(delta) });
+                    Log.d(LOG_TAG, "Deleted '" + count + "' saved Search query(ies)");
+                }
+            } catch (Exception e) {
+                Log.d(LOG_TAG, "Cannot update saved Search queries", e);
+            }
+
+            return lastInsertedRowId;
+        }
+    }
 }