Merge "Deleting the unrestored widget id synchronously" into ub-launcher3-calgary
diff --git a/build.gradle b/build.gradle
index b5eeeb0..6620c10 100644
--- a/build.gradle
+++ b/build.gradle
@@ -40,7 +40,6 @@
 
         androidTest {
             java.srcDirs = ['tests/src']
-            res.srcDirs = ['tests/res']
             manifest.srcFile "tests/AndroidManifest.xml"
         }
     }
diff --git a/src/com/android/launcher3/AllAppsList.java b/src/com/android/launcher3/AllAppsList.java
index f76c185..962396c 100644
--- a/src/com/android/launcher3/AllAppsList.java
+++ b/src/com/android/launcher3/AllAppsList.java
@@ -22,6 +22,7 @@
 import com.android.launcher3.compat.LauncherActivityInfoCompat;
 import com.android.launcher3.compat.LauncherAppsCompat;
 import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.util.FlagOp;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -119,19 +120,15 @@
     }
 
     /**
-     * Suspend the apps for the given apk identified by packageName.
+     * Updates the apps for the given packageName and user based on {@param op}.
      */
-    public void suspendPackage(String packageName, UserHandleCompat user, boolean suspend) {
+    public void updatePackageFlags(String packageName, UserHandleCompat user, FlagOp op) {
         final List<AppInfo> data = this.data;
         for (int i = data.size() - 1; i >= 0; i--) {
             AppInfo info = data.get(i);
             final ComponentName component = info.intent.getComponent();
             if (info.user.equals(user) && packageName.equals(component.getPackageName())) {
-                if (suspend) {
-                    info.isDisabled |= ShortcutInfo.FLAG_DISABLED_SUSPENDED;
-                } else {
-                    info.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_SUSPENDED;
-                }
+                info.isDisabled = op.apply(info.isDisabled);
                 modified.add(info);
             }
         }
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 46b9b7d..921e90c 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -87,7 +87,7 @@
         }
     }
 
-    public static void removeFromInstallQueue(Context context, ArrayList<String> packageNames,
+    public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
             UserHandleCompat user) {
         if (packageNames.isEmpty()) {
             return;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 5a1f99a..36b9ab0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -4322,7 +4322,7 @@
             }
             mWorkspace.removeItemsByComponentName(removedComponents, user);
             // Notify the drag controller
-            mDragController.onAppsRemoved(new ArrayList<String>(), removedComponents);
+            mDragController.onAppsRemoved(new HashSet<String>(), removedComponents);
         }
     }
 
@@ -4346,43 +4346,44 @@
     }
 
     /**
-     * A package was uninstalled.  We take both the super set of packageNames
+     * A package was uninstalled/updated.  We take both the super set of packageNames
      * in addition to specific applications to remove, the reason being that
      * this can be called when a package is updated as well.  In that scenario,
-     * we only remove specific components from the workspace, where as
+     * we only remove specific components from the workspace and hotseat, where as
      * package-removal should clear all items by package name.
-     *
-     * @param reason if non-zero, the icons are not permanently removed, rather marked as disabled.
-     * Implementation of the method from LauncherModel.Callbacks.
      */
     @Override
-    public void bindComponentsRemoved(final ArrayList<String> packageNames,
-            final ArrayList<AppInfo> appInfos, final UserHandleCompat user, final int reason) {
+    public void bindWorkspaceComponentsRemoved(
+            final HashSet<String> packageNames, final HashSet<ComponentName> components,
+            final UserHandleCompat user) {
         Runnable r = new Runnable() {
             public void run() {
-                bindComponentsRemoved(packageNames, appInfos, user, reason);
+                bindWorkspaceComponentsRemoved(packageNames, components, user);
             }
         };
         if (waitUntilResume(r)) {
             return;
         }
+        if (!packageNames.isEmpty()) {
+            mWorkspace.removeItemsByPackageName(packageNames, user);
+        }
+        if (!components.isEmpty()) {
+            mWorkspace.removeItemsByComponentName(components, user);
+        }
+        // Notify the drag controller
+        mDragController.onAppsRemoved(packageNames, components);
 
-        if (reason == 0) {
-            HashSet<ComponentName> removedComponents = new HashSet<ComponentName>();
-            for (AppInfo info : appInfos) {
-                removedComponents.add(info.componentName);
-            }
-            if (!packageNames.isEmpty()) {
-                mWorkspace.removeItemsByPackageName(packageNames, user);
-            }
-            if (!removedComponents.isEmpty()) {
-                mWorkspace.removeItemsByComponentName(removedComponents, user);
-            }
-            // Notify the drag controller
-            mDragController.onAppsRemoved(packageNames, removedComponents);
+    }
 
-        } else {
-            mWorkspace.disableShortcutsByPackageName(packageNames, user, reason);
+    @Override
+    public void bindAppInfosRemoved(final ArrayList<AppInfo> appInfos) {
+        Runnable r = new Runnable() {
+            public void run() {
+                bindAppInfosRemoved(appInfos);
+            }
+        };
+        if (waitUntilResume(r)) {
+            return;
         }
 
         // Update AllApps
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 3877b94..4c2dec5 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -60,6 +60,7 @@
 import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.CursorIconInfo;
+import com.android.launcher3.util.FlagOp;
 import com.android.launcher3.util.LongArrayMap;
 import com.android.launcher3.util.ManagedProfileHeuristic;
 import com.android.launcher3.util.Thunk;
@@ -195,8 +196,10 @@
                 ArrayList<ShortcutInfo> removed, UserHandleCompat user);
         public void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets);
         public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
-        public void bindComponentsRemoved(ArrayList<String> packageNames,
-                        ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
+        public void bindWorkspaceComponentsRemoved(
+                HashSet<String> packageNames, HashSet<ComponentName> components,
+                UserHandleCompat user);
+        public void bindAppInfosRemoved(ArrayList<AppInfo> appInfos);
         public void notifyWidgetProvidersChanged();
         public void bindWidgetsModel(WidgetsModel model);
         public void bindSearchProviderChanged();
@@ -2928,6 +2931,7 @@
 
             final String[] packages = mPackages;
             final int N = packages.length;
+            FlagOp flagOp = FlagOp.NO_OP;
             switch (mOp) {
                 case OP_ADD: {
                     for (int i=0; i<N; i++) {
@@ -2949,6 +2953,8 @@
                         mBgAllAppsList.updatePackage(context, packages[i], mUser);
                         mApp.getWidgetCache().removePackage(packages[i], mUser);
                     }
+                    // Since package was just updated, the target must be available now.
+                    flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
                     break;
                 case OP_REMOVE: {
                     ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
@@ -2967,14 +2973,16 @@
                         mBgAllAppsList.removePackage(packages[i], mUser);
                         mApp.getWidgetCache().removePackage(packages[i], mUser);
                     }
+                    flagOp = FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
                     break;
                 case OP_SUSPEND:
                 case OP_UNSUSPEND:
-                    boolean suspend = mOp == OP_SUSPEND;
+                    flagOp = mOp == OP_SUSPEND ?
+                            FlagOp.addFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED) :
+                                    FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_SUSPENDED);
                     for (int i=0; i<N; i++) {
-                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.suspendPackage "
-                                + suspend + " " + packages[i]);
-                        mBgAllAppsList.suspendPackage(packages[i], mUser, suspend);
+                        if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.(un)suspend " + packages[i]);
+                        mBgAllAppsList.updatePackageFlags(packages[i], mUser, flagOp);
                     }
                     break;
             }
@@ -2984,11 +2992,11 @@
             final ArrayList<AppInfo> removedApps = new ArrayList<AppInfo>();
 
             if (mBgAllAppsList.added.size() > 0) {
-                added = new ArrayList<AppInfo>(mBgAllAppsList.added);
+                added = new ArrayList<>(mBgAllAppsList.added);
                 mBgAllAppsList.added.clear();
             }
             if (mBgAllAppsList.modified.size() > 0) {
-                modified = new ArrayList<AppInfo>(mBgAllAppsList.modified);
+                modified = new ArrayList<>(mBgAllAppsList.modified);
                 mBgAllAppsList.modified.clear();
             }
             if (mBgAllAppsList.removed.size() > 0) {
@@ -2996,14 +3004,7 @@
                 mBgAllAppsList.removed.clear();
             }
 
-            final Callbacks callbacks = getCallback();
-            if (callbacks == null) {
-                Log.w(TAG, "Nobody to tell about the new app.  Launcher is probably loading.");
-                return;
-            }
-
-            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps =
-                    new HashMap<ComponentName, AppInfo>();
+            final HashMap<ComponentName, AppInfo> addedOrUpdatedApps = new HashMap<>();
 
             if (added != null) {
                 addAppsToAllApps(context, added);
@@ -3013,6 +3014,7 @@
             }
 
             if (modified != null) {
+                final Callbacks callbacks = getCallback();
                 final ArrayList<AppInfo> modifiedFinal = modified;
                 for (AppInfo ai : modified) {
                     addedOrUpdatedApps.put(ai.componentName, ai);
@@ -3029,7 +3031,7 @@
             }
 
             // Update shortcut infos
-            if (mOp == OP_ADD || mOp == OP_UPDATE || mOp == OP_UNSUSPEND) {
+            if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
                 final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<ShortcutInfo>();
                 final ArrayList<ShortcutInfo> removedShortcuts = new ArrayList<ShortcutInfo>();
                 final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<LauncherAppWidgetInfo>();
@@ -3042,11 +3044,6 @@
                             boolean infoUpdated = false;
                             boolean shortcutUpdated = false;
 
-                            if (mOp == OP_UNSUSPEND) {
-                                si.isDisabled &= ~ ShortcutInfo.FLAG_DISABLED_SUSPENDED;
-                                infoUpdated = true;
-                            }
-
                             // Update shortcuts which use iconResource.
                             if ((si.iconResource != null)
                                     && packageSet.contains(si.iconResource.packageName)) {
@@ -3109,9 +3106,9 @@
                                     infoUpdated = true;
                                 }
 
-                                if ((si.isDisabled & ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE) != 0) {
-                                    // Since package was just updated, the target must be available now.
-                                    si.isDisabled &= ~ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
+                                int oldDisabledFlags = si.isDisabled;
+                                si.isDisabled = flagOp.apply(si.isDisabled);
+                                if (si.isDisabled != oldDisabledFlags) {
                                     shortcutUpdated = true;
                                 }
                             }
@@ -3144,6 +3141,7 @@
                 }
 
                 if (!updatedShortcuts.isEmpty() || !removedShortcuts.isEmpty()) {
+                    final Callbacks callbacks = getCallback();
                     mHandler.post(new Runnable() {
 
                         public void run() {
@@ -3159,6 +3157,7 @@
                     }
                 }
                 if (!widgets.isEmpty()) {
+                    final Callbacks callbacks = getCallback();
                     mHandler.post(new Runnable() {
                         public void run() {
                             Callbacks cb = getCallback();
@@ -3170,48 +3169,60 @@
                 }
             }
 
-            final ArrayList<String> removedPackageNames =
-                    new ArrayList<String>();
-            if (mOp == OP_REMOVE || mOp == OP_UNAVAILABLE || mOp == OP_SUSPEND) {
+            final HashSet<String> removedPackages = new HashSet<>();
+            final HashSet<ComponentName> removedComponents = new HashSet<>();
+            if (mOp == OP_REMOVE) {
                 // Mark all packages in the broadcast to be removed
-                removedPackageNames.addAll(Arrays.asList(packages));
+                Collections.addAll(removedPackages, packages);
+
+                // No need to update the removedComponents as
+                // removedPackages is a super-set of removedComponents
             } else if (mOp == OP_UPDATE) {
                 // Mark disabled packages in the broadcast to be removed
                 for (int i=0; i<N; i++) {
                     if (isPackageDisabled(context, packages[i], mUser)) {
-                        removedPackageNames.add(packages[i]);
+                        removedPackages.add(packages[i]);
                     }
                 }
+
+                // Update removedComponents as some components can get removed during package update
+                for (AppInfo info : removedApps) {
+                    removedComponents.add(info.componentName);
+                }
             }
 
-            if (!removedPackageNames.isEmpty() || !removedApps.isEmpty()) {
-                final int removeReason;
-                if (mOp == OP_UNAVAILABLE) {
-                    removeReason = ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE;
-                } else if (mOp == OP_SUSPEND) {
-                    removeReason = ShortcutInfo.FLAG_DISABLED_SUSPENDED;
-                } else {
-                    // Remove all the components associated with this package
-                    for (String pn : removedPackageNames) {
-                        deletePackageFromDatabase(context, pn, mUser);
-                    }
-                    // Remove all the specific components
-                    for (AppInfo a : removedApps) {
-                        ArrayList<ItemInfo> infos = getItemInfoForComponentName(a.componentName, mUser);
-                        deleteItemsFromDatabase(context, infos);
-                    }
-                    removeReason = 0;
+            if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
+                for (String pn : removedPackages) {
+                    deletePackageFromDatabase(context, pn, mUser);
+                }
+                for (ComponentName cn : removedComponents) {
+                    deleteItemsFromDatabase(context, getItemInfoForComponentName(cn, mUser));
                 }
 
                 // Remove any queued items from the install queue
-                InstallShortcutReceiver.removeFromInstallQueue(context, removedPackageNames, mUser);
+                InstallShortcutReceiver.removeFromInstallQueue(context, removedPackages, mUser);
+
                 // Call the components-removed callback
+                final Callbacks callbacks = getCallback();
                 mHandler.post(new Runnable() {
                     public void run() {
                         Callbacks cb = getCallback();
                         if (callbacks == cb && cb != null) {
-                            callbacks.bindComponentsRemoved(
-                                    removedPackageNames, removedApps, mUser, removeReason);
+                            callbacks.bindWorkspaceComponentsRemoved(
+                                    removedPackages, removedComponents, mUser);
+                        }
+                    }
+                });
+            }
+
+            if (!removedApps.isEmpty()) {
+                // Remove corresponding apps from All-Apps
+                final Callbacks callbacks = getCallback();
+                mHandler.post(new Runnable() {
+                    public void run() {
+                        Callbacks cb = getCallback();
+                        if (callbacks == cb && cb != null) {
+                            callbacks.bindAppInfosRemoved(removedApps);
                         }
                     }
                 });
@@ -3221,6 +3232,7 @@
             // get widget update signals.
             if (!Utilities.ATLEAST_MARSHMALLOW &&
                     (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE)) {
+                final Callbacks callbacks = getCallback();
                 mHandler.post(new Runnable() {
                     public void run() {
                         Callbacks cb = getCallback();
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 47ceb8c..207121b 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -527,13 +527,8 @@
         private long mMaxScreenId = -1;
 
         DatabaseHelper(Context context, LauncherProvider provider) {
-            super(new NoLocaleSqliteContext(context), LauncherFiles.LAUNCHER_DB,
-                    null, DATABASE_VERSION);
-            mContext = context;
-            mProvider = provider;
-
-            mAppWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID);
-
+            this(context, provider, LauncherFiles.LAUNCHER_DB,
+                    new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID));
             // Table creation sometimes fails silently, which leads to a crash loop.
             // This way, we will try to create a table every time after crash, so the device
             // would eventually be able to recover.
@@ -544,6 +539,21 @@
                 addWorkspacesTable(getWritableDatabase(), true);
             }
 
+            initIds();
+        }
+
+        /**
+         * Constructor used only in tests.
+         */
+        public DatabaseHelper(
+                Context context, LauncherProvider provider, String tableName, AppWidgetHost host) {
+            super(new NoLocaleSqliteContext(context), tableName, null, DATABASE_VERSION);
+            mContext = context;
+            mProvider = provider;
+            mAppWidgetHost = host;
+        }
+
+        protected void initIds() {
             // In the case where neither onCreate nor onUpgrade gets called, we read the maxId from
             // the DB here
             if (mMaxItemId == -1) {
@@ -554,19 +564,6 @@
             }
         }
 
-        /**
-         * Constructor used only in tests.
-         */
-        public DatabaseHelper(Context context, LauncherProvider provider, String tableName) {
-            super(new NoLocaleSqliteContext(context), tableName, null, DATABASE_VERSION);
-            mContext = context;
-            mProvider = provider;
-
-            mAppWidgetHost = null;
-            mMaxItemId = initializeMaxItemId(getWritableDatabase());
-            mMaxScreenId = initializeMaxScreenId(getWritableDatabase());
-        }
-
         private boolean tableExists(String tableName) {
             Cursor c = getReadableDatabase().query(
                     true, "sqlite_master", new String[] {"tbl_name"},
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 44a17cc..89779d5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -3922,41 +3922,10 @@
         });
     }
 
-    public void disableShortcutsByPackageName(final ArrayList<String> packages,
-            final UserHandleCompat user, final int reason) {
-        final HashSet<String> packageNames = new HashSet<String>();
-        packageNames.addAll(packages);
-
-        mapOverItems(MAP_RECURSE, new ItemOperator() {
-            @Override
-            public boolean evaluate(ItemInfo info, View v, View parent) {
-                if (info instanceof ShortcutInfo && v instanceof BubbleTextView) {
-                    ShortcutInfo shortcutInfo = (ShortcutInfo) info;
-                    ComponentName cn = shortcutInfo.getTargetComponent();
-                    if (user.equals(shortcutInfo.user) && cn != null
-                            && packageNames.contains(cn.getPackageName())) {
-                        shortcutInfo.isDisabled |= reason;
-                        BubbleTextView shortcut = (BubbleTextView) v;
-                        shortcut.applyFromShortcutInfo(shortcutInfo, mIconCache);
-
-                        if (parent != null) {
-                            parent.invalidate();
-                        }
-                    }
-                }
-                // process all the shortcuts
-                return false;
-            }
-        });
-    }
-
     // Removes ALL items that match a given package name, this is usually called when a package
     // has been removed and we want to remove all components (widgets, shortcuts, apps) that
     // belong to that package.
-    void removeItemsByPackageName(final ArrayList<String> packages, final UserHandleCompat user) {
-        final HashSet<String> packageNames = new HashSet<String>();
-        packageNames.addAll(packages);
-
+    void removeItemsByPackageName(final HashSet<String> packageNames, final UserHandleCompat user) {
         // Filter out all the ItemInfos that this is going to affect
         final HashSet<ItemInfo> infos = new HashSet<ItemInfo>();
         final HashSet<ComponentName> cns = new HashSet<ComponentName>();
@@ -4138,7 +4107,7 @@
     }
 
     public void removeAbandonedPromise(String packageName, UserHandleCompat user) {
-        ArrayList<String> packages = new ArrayList<String>(1);
+        HashSet<String> packages = new HashSet<>(1);
         packages.add(packageName);
         LauncherModel.deletePackageFromDatabase(mLauncher, packageName, user);
         removeItemsByPackageName(packages, user);
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 80f9e46..7524128 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -314,7 +314,7 @@
         endDrag();
     }
 
-    public void onAppsRemoved(final ArrayList<String> packageNames, HashSet<ComponentName> cns) {
+    public void onAppsRemoved(final HashSet<String> packageNames, HashSet<ComponentName> cns) {
         // Cancel the current drag if we are removing an app that we are dragging
         if (mDragObject != null) {
             Object rawDragInfo = mDragObject.dragInfo;
diff --git a/src/com/android/launcher3/util/FlagOp.java b/src/com/android/launcher3/util/FlagOp.java
new file mode 100644
index 0000000..5e26ed1
--- /dev/null
+++ b/src/com/android/launcher3/util/FlagOp.java
@@ -0,0 +1,30 @@
+package com.android.launcher3.util;
+
+public abstract class FlagOp {
+
+    public static FlagOp NO_OP = new FlagOp() {};
+
+    private FlagOp() {}
+
+    public int apply(int flags) {
+        return flags;
+    }
+
+    public static FlagOp addFlag(final int flag) {
+        return new FlagOp() {
+            @Override
+            public int apply(int flags) {
+                return flags | flag;
+            }
+        };
+    }
+
+    public static FlagOp removeFlag(final int flag) {
+        return new FlagOp() {
+            @Override
+            public int apply(int flags) {
+                return flags & ~flag;
+            }
+        };
+    }
+}
diff --git a/tests/Android.mk b/tests/Android.mk
index d82f0b3..0c4b5ff 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -16,13 +16,10 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-src_dirs := src
 LOCAL_MODULE_TAGS := tests
 LOCAL_STATIC_JAVA_LIBRARIES := android-support-test ub-uiautomator
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dirs))
-LOCAL_AAPT_FLAGS := --auto-add-overlay
 
 LOCAL_SDK_VERSION := 23
 
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 8acc5e9..afe8952 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -20,12 +20,14 @@
 
     <uses-sdk tools:overrideLibrary="android.support.test.uiautomator.v18"/>
 
-    <application>
+    <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
 
     <instrumentation
-        android:name="android.test.InstrumentationTestRunner"
+        android:functionalTest="false"
+        android:handleProfiling="false"
+        android:name="android.support.test.runner.AndroidJUnitRunner"
         android:targetPackage="com.android.launcher3" >
     </instrumentation>
 </manifest>
diff --git a/tests/res/values/string.xml b/tests/res/values/string.xml
deleted file mode 100644
index 3c1ec5c..0000000
--- a/tests/res/values/string.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<!-- Copyright (C) 2015 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.
--->
-
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-
-    <!-- Dummy string for tests. [DO NOT TRANSLATE] -->
-    <string name="dummy" >Dummy string for tests.</string>
-
-</resources>
diff --git a/tests/src/com/android/launcher3/BindWidgetTest.java b/tests/src/com/android/launcher3/BindWidgetTest.java
index 06e1936..4e8881c 100644
--- a/tests/src/com/android/launcher3/BindWidgetTest.java
+++ b/tests/src/com/android/launcher3/BindWidgetTest.java
@@ -109,7 +109,7 @@
     public void testUnboundWidget_removed() throws Exception {
         LauncherAppWidgetProviderInfo info = findWidgetProvider(false);
         LauncherAppWidgetInfo item = createWidgetInfo(info, false);
-        item.appWidgetId = 33;
+        item.appWidgetId = -33;
 
         // Since there is no widget to verify, just wait until the workspace is ready.
         setupAndVerifyContents(item, Workspace.class, null);
@@ -253,6 +253,7 @@
             runTestOnUiThread(new Runnable() {
                 @Override
                 public void run() {
+                    LauncherClings.markFirstRunClingDismissed(mTargetContext);
                     ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mTargetContext);
                     LauncherAppState.getInstance().getModel().resetLoadedState(true, true);
                 }
diff --git a/tests/src/com/android/launcher3/util/TestLauncherProvider.java b/tests/src/com/android/launcher3/util/TestLauncherProvider.java
index aef3240..a11013f 100644
--- a/tests/src/com/android/launcher3/util/TestLauncherProvider.java
+++ b/tests/src/com/android/launcher3/util/TestLauncherProvider.java
@@ -26,7 +26,8 @@
 
     private static class MyDatabaseHelper extends DatabaseHelper {
         public MyDatabaseHelper(Context context, LauncherProvider provider) {
-            super(context, provider, null);
+            super(context, provider, null, null);
+            initIds();
         }
 
         @Override