Merge "Reloading launcher whenever there is an external update to contentprovider, irrespective of the uri" into ub-launcher3-burnaby
diff --git a/res/layout/all_apps_search_bar.xml b/res/layout/all_apps_search_bar.xml
index 0c183ea..69a66c8 100644
--- a/res/layout/all_apps_search_bar.xml
+++ b/res/layout/all_apps_search_bar.xml
@@ -38,7 +38,7 @@
             android:contentDescription="@string/all_apps_button_label"
             android:src="@drawable/ic_arrow_back_grey" />
 
-        <com.android.launcher3.allapps.AllAppsSearchEditView
+        <com.android.launcher3.ExtendedEditText
             android:id="@+id/search_box_input"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
diff --git a/res/layout/user_folder.xml b/res/layout/user_folder.xml
index ecf7def..275840d 100644
--- a/res/layout/user_folder.xml
+++ b/res/layout/user_folder.xml
@@ -53,7 +53,7 @@
         android:paddingLeft="8dp"
         android:paddingRight="8dp" >
 
-        <com.android.launcher3.FolderEditText
+        <com.android.launcher3.ExtendedEditText
             android:id="@+id/folder_name"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
diff --git a/src/com/android/launcher3/allapps/AllAppsSearchEditView.java b/src/com/android/launcher3/ExtendedEditText.java
similarity index 74%
rename from src/com/android/launcher3/allapps/AllAppsSearchEditView.java
rename to src/com/android/launcher3/ExtendedEditText.java
index b7dcd66..c7b64ec 100644
--- a/src/com/android/launcher3/allapps/AllAppsSearchEditView.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.launcher3.allapps;
+package com.android.launcher3;
 
 import android.content.Context;
 import android.util.AttributeSet;
@@ -22,28 +22,28 @@
 
 
 /**
- * The edit text for the search container
+ * The edit text that reports back when the back key has been pressed.
  */
-public class AllAppsSearchEditView extends EditText {
+public class ExtendedEditText extends EditText {
 
     /**
      * Implemented by listeners of the back key.
      */
     public interface OnBackKeyListener {
-        public void onBackKey();
+        public boolean onBackKey();
     }
 
     private OnBackKeyListener mBackKeyListener;
 
-    public AllAppsSearchEditView(Context context) {
-        this(context, null);
+    public ExtendedEditText(Context context) {
+        super(context);
     }
 
-    public AllAppsSearchEditView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
+    public ExtendedEditText(Context context, AttributeSet attrs) {
+        super(context, attrs);
     }
 
-    public AllAppsSearchEditView(Context context, AttributeSet attrs, int defStyleAttr) {
+    public ExtendedEditText(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
     }
 
@@ -56,7 +56,7 @@
         // If this is a back key, propagate the key back to the listener
         if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
             if (mBackKeyListener != null) {
-                mBackKeyListener.onBackKey();
+                return mBackKeyListener.onBackKey();
             }
             return false;
         }
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 5e713b2..7b88a88 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -124,7 +124,7 @@
 
     @Thunk FolderPagedView mContent;
     @Thunk View mContentWrapper;
-    FolderEditText mFolderName;
+    ExtendedEditText mFolderName;
 
     private View mFooter;
     private int mFooterHeight;
@@ -196,8 +196,15 @@
         mContent = (FolderPagedView) findViewById(R.id.folder_content);
         mContent.setFolder(this);
 
-        mFolderName = (FolderEditText) findViewById(R.id.folder_name);
-        mFolderName.setFolder(this);
+        mFolderName = (ExtendedEditText) findViewById(R.id.folder_name);
+        mFolderName.setOnBackKeyListener(new ExtendedEditText.OnBackKeyListener() {
+            @Override
+            public boolean onBackKey() {
+                // Close the activity on back key press
+                doneEditingFolderName(true);
+                return false;
+            }
+        });
         mFolderName.setOnFocusChangeListener(this);
 
         // We disable action mode for now since it messes up the view on phones
diff --git a/src/com/android/launcher3/FolderEditText.java b/src/com/android/launcher3/FolderEditText.java
deleted file mode 100644
index c311008..0000000
--- a/src/com/android/launcher3/FolderEditText.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.android.launcher3;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.KeyEvent;
-import android.widget.EditText;
-
-public class FolderEditText extends EditText {
-
-    private Folder mFolder;
-
-    public FolderEditText(Context context) {
-        super(context);
-    }
-
-    public FolderEditText(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public FolderEditText(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-    }
-
-    public void setFolder(Folder folder) {
-        mFolder = folder;
-    }
-
-    @Override
-    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
-        // Catch the back button on the soft keyboard so that we can just close the activity
-        if (event.getKeyCode() == android.view.KeyEvent.KEYCODE_BACK) {
-            mFolder.doneEditingFolderName(true);
-        }
-        return super.onKeyPreIme(keyCode, event);
-    }
-}
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index de7c610..6c3a1e8 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -95,8 +95,6 @@
     }
 
     protected void onProvidersChanged() {
-        mLauncher.getModel().loadAndBindWidgetsAndShortcuts(mLauncher, mLauncher,
-                true /* refresh */);
         if (!mProviderChangeListeners.isEmpty()) {
             for (Runnable callback : new ArrayList<>(mProviderChangeListeners)) {
                 callback.run();
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index d9b0cd4..397db6d 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -17,6 +17,7 @@
 package com.android.launcher3;
 
 import android.app.SearchManager;
+import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -2864,8 +2865,7 @@
             // Cleanup any data stored for a deleted user.
             ManagedProfileHeuristic.processAllUsers(profiles, mContext);
 
-            loadAndBindWidgetsAndShortcuts(mApp.getContext(), tryGetCallbacks(oldCallbacks),
-                    true /* refresh */);
+            loadAndBindWidgetsAndShortcuts(tryGetCallbacks(oldCallbacks), true /* refresh */);
             if (DEBUG_LOADERS) {
                 Log.d(TAG, "Icons processed in "
                         + (SystemClock.uptimeMillis() - loadTime) + "ms");
@@ -2934,7 +2934,7 @@
         }
 
         // Reload widget list. No need to refresh, as we only want to update the icons and labels.
-        loadAndBindWidgetsAndShortcuts(mApp.getContext(), callbacks, false);
+        loadAndBindWidgetsAndShortcuts(callbacks, false);
     }
 
     void enqueuePackageUpdated(PackageUpdatedTask task) {
@@ -3276,8 +3276,36 @@
                 });
             }
 
-            // onProvidersChanged method (API >= 17) already refreshed the widget list
-            loadAndBindWidgetsAndShortcuts(context, callbacks, Build.VERSION.SDK_INT < 17);
+            // Update widgets
+            if (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE) {
+                // Always refresh for a package event on secondary user
+                boolean needToRefresh = !mUser.equals(UserHandleCompat.myUserHandle());
+
+                // Refresh widget list, if the package already had a widget.
+                synchronized (sBgLock) {
+                    if (sBgWidgetProviders != null) {
+                        HashSet<String> pkgSet = new HashSet<>();
+                        Collections.addAll(pkgSet, mPackages);
+
+                        for (ComponentKey key : sBgWidgetProviders.keySet()) {
+                            needToRefresh |= key.user.equals(mUser) &&
+                                    pkgSet.contains(key.componentName.getPackageName());
+                        }
+                    }
+                }
+
+                if (!needToRefresh && mOp != OP_REMOVE) {
+                    // Refresh widget list, if there is any newly added widget
+                    PackageManager pm = context.getPackageManager();
+                    for (String pkg : mPackages) {
+                        needToRefresh |= !pm.queryBroadcastReceivers(
+                                new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
+                                    .setPackage(pkg), 0).isEmpty();
+                    }
+                }
+
+                loadAndBindWidgetsAndShortcuts(callbacks, needToRefresh);
+            }
 
             // Write all the logs to disk
             mHandler.post(new Runnable() {
@@ -3351,13 +3379,12 @@
         }
     }
 
-    public void loadAndBindWidgetsAndShortcuts(final Context context, final Callbacks callbacks,
-            final boolean refresh) {
+    public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) {
 
         runOnWorkerThread(new Runnable() {
             @Override
             public void run() {
-                updateWidgetsModel(context, refresh);
+                updateWidgetsModel(refresh);
                 final WidgetsModel model = mBgWidgetsModel.clone();
 
                 mHandler.post(new Runnable() {
@@ -3381,10 +3408,10 @@
      *
      * @see #loadAndBindWidgetsAndShortcuts
      */
-    @Thunk void updateWidgetsModel(Context context, boolean refresh) {
-        PackageManager packageManager = context.getPackageManager();
+    @Thunk void updateWidgetsModel(boolean refresh) {
+        PackageManager packageManager = mApp.getContext().getPackageManager();
         final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
-        widgetsAndShortcuts.addAll(getWidgetProviders(context, refresh));
+        widgetsAndShortcuts.addAll(getWidgetProviders(mApp.getContext(), refresh));
         Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
         widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
         mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index 3d50587..3460555 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -105,7 +105,7 @@
      * sizes (landscape vs portrait).
      */
     private static class CacheDb extends SQLiteOpenHelper {
-        private static final int DB_VERSION = 3;
+        private static final int DB_VERSION = 4;
 
         private static final String TABLE_NAME = "shortcut_and_widget_previews";
         private static final String COLUMN_COMPONENT = "componentName";
diff --git a/src/com/android/launcher3/allapps/DefaultAppSearchController.java b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
index e1a2b7f..3169f84 100644
--- a/src/com/android/launcher3/allapps/DefaultAppSearchController.java
+++ b/src/com/android/launcher3/allapps/DefaultAppSearchController.java
@@ -25,6 +25,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.TextView;
+import com.android.launcher3.ExtendedEditText;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.util.Thunk;
@@ -54,7 +55,8 @@
     @Thunk View mSearchBarContainerView;
     private View mSearchButtonView;
     private View mDismissSearchButtonView;
-    @Thunk AllAppsSearchEditView mSearchBarEditView;
+    @Thunk
+    ExtendedEditText mSearchBarEditView;
     @Thunk AllAppsRecyclerView mAppsRecyclerView;
     @Thunk Runnable mFocusRecyclerViewRunnable = new Runnable() {
         @Override
@@ -82,21 +84,23 @@
         mSearchBarContainerView = mSearchView.findViewById(R.id.search_container);
         mDismissSearchButtonView = mSearchBarContainerView.findViewById(R.id.dismiss_search_button);
         mDismissSearchButtonView.setOnClickListener(this);
-        mSearchBarEditView = (AllAppsSearchEditView)
+        mSearchBarEditView = (ExtendedEditText)
                 mSearchBarContainerView.findViewById(R.id.search_box_input);
         mSearchBarEditView.addTextChangedListener(this);
         mSearchBarEditView.setOnEditorActionListener(this);
         mSearchBarEditView.setOnBackKeyListener(
-                new AllAppsSearchEditView.OnBackKeyListener() {
+                new ExtendedEditText.OnBackKeyListener() {
                     @Override
-                    public void onBackKey() {
+                    public boolean onBackKey() {
                         // Only hide the search field if there is no query, or if there
                         // are no filtered results
                         String query = Utilities.trim(
                                 mSearchBarEditView.getEditableText().toString());
                         if (query.isEmpty() || mApps.hasNoFilteredResults()) {
                             hideSearchField(true, mFocusRecyclerViewRunnable);
+                            return true;
                         }
+                        return false;
                     }
                 });
         return mSearchView;