summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2017-10-05 15:57:40 -0700
committerSunny Goyal <sunnygoyal@google.com>2017-10-06 11:33:43 -0700
commit91498abf7552f15624283366be86f91304ad92a2 (patch)
tree13b54a20cde6998dfc6f893cb3531e8c4c43586b
parent22b92df30f5a1ec319180cb705175e7563727a36 (diff)
downloadandroid_packages_apps_Trebuchet-91498abf7552f15624283366be86f91304ad92a2.tar.gz
android_packages_apps_Trebuchet-91498abf7552f15624283366be86f91304ad92a2.tar.bz2
android_packages_apps_Trebuchet-91498abf7552f15624283366be86f91304ad92a2.zip
Moving install queue updates to worker thread.
This avoids acquiring a lock for upating the sharedPrefs during onResume as all the logic runs on a single thread. Bug: 67305604 Change-Id: I1bbea382da9fafb403b4e9508f393f78db28478d
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java187
-rw-r--r--src/com/android/launcher3/LauncherModel.java5
-rw-r--r--src/com/android/launcher3/model/AddWorkspaceItemsTask.java14
-rw-r--r--tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java2
4 files changed, 96 insertions, 112 deletions
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 0370777d1..df1eec661 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -27,7 +27,9 @@ import android.content.pm.LauncherActivityInfo;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.os.Handler;
import android.os.Looper;
+import android.os.Message;
import android.os.Parcelable;
import android.os.Process;
import android.os.UserHandle;
@@ -61,6 +63,9 @@ import java.util.Set;
public class InstallShortcutReceiver extends BroadcastReceiver {
+ private static final int MSG_ADD_TO_QUEUE = 1;
+ private static final int MSG_FLUSH_QUEUE = 2;
+
public static final int FLAG_ACTIVITY_PAUSED = 1;
public static final int FLAG_LOADER_RUNNING = 2;
public static final int FLAG_DRAG_AND_DROP = 4;
@@ -93,73 +98,98 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
public static final int NEW_SHORTCUT_STAGGER_DELAY = 85;
- private static final Object sLock = new Object();
-
- private static void addToInstallQueue(
- SharedPreferences sharedPrefs, PendingInstallShortcutInfo info) {
- synchronized(sLock) {
- String encoded = info.encodeToString();
- if (encoded != null) {
- Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
- strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
- strings.add(encoded);
- sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
+ private static final Handler sHandler = new Handler(LauncherModel.getWorkerLooper()) {
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ADD_TO_QUEUE: {
+ Pair<Context, PendingInstallShortcutInfo> pair =
+ (Pair<Context, PendingInstallShortcutInfo>) msg.obj;
+ String encoded = pair.second.encodeToString();
+ SharedPreferences prefs = Utilities.getPrefs(pair.first);
+ Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
+ strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
+ strings.add(encoded);
+ prefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
+ return;
+ }
+ case MSG_FLUSH_QUEUE: {
+ Context context = (Context) msg.obj;
+ LauncherModel model = LauncherAppState.getInstance(context).getModel();
+ if (model.getCallback() == null) {
+ // Launcher not loaded
+ return;
+ }
+
+ ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
+ SharedPreferences prefs = Utilities.getPrefs(context);
+ Set<String> strings = prefs.getStringSet(APPS_PENDING_INSTALL, null);
+ if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
+ if (strings == null) {
+ return;
+ }
+
+ LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(context);
+ for (String encoded : strings) {
+ PendingInstallShortcutInfo info = decode(encoded, context);
+ if (info == null) {
+ continue;
+ }
+
+ String pkg = getIntentPackage(info.launchIntent);
+ if (!TextUtils.isEmpty(pkg)
+ && !launcherApps.isPackageEnabledForProfile(pkg, info.user)) {
+ if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
+ + info.launchIntent);
+ continue;
+ }
+
+ // Generate a shortcut info to add into the model
+ installQueue.add(info.getItemInfo());
+ }
+ prefs.edit().remove(APPS_PENDING_INSTALL).apply();
+ if (!installQueue.isEmpty()) {
+ model.addAndBindAddedWorkspaceItems(installQueue);
+ }
+ return;
+ }
}
}
- }
+ };
public static void removeFromInstallQueue(Context context, HashSet<String> packageNames,
UserHandle user) {
if (packageNames.isEmpty()) {
return;
}
+ Preconditions.assertWorkerThread();
+
SharedPreferences sp = Utilities.getPrefs(context);
- synchronized(sLock) {
- Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) {
- Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
- + ", removing packages: " + packageNames);
- }
- if (Utilities.isEmpty(strings)) {
- return;
- }
- Set<String> newStrings = new HashSet<>(strings);
- Iterator<String> newStringsIter = newStrings.iterator();
- while (newStringsIter.hasNext()) {
- String encoded = newStringsIter.next();
- try {
- Decoder decoder = new Decoder(encoded, context);
- if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) &&
- user.equals(decoder.user)) {
- newStringsIter.remove();
- }
- } catch (JSONException | URISyntaxException e) {
- Log.d(TAG, "Exception reading shortcut to add: " + e);
- newStringsIter.remove();
- }
- }
- sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
+ Set<String> strings = sp.getStringSet(APPS_PENDING_INSTALL, null);
+ if (DBG) {
+ Log.d(TAG, "APPS_PENDING_INSTALL: " + strings
+ + ", removing packages: " + packageNames);
}
- }
-
- private static ArrayList<PendingInstallShortcutInfo> getAndClearInstallQueue(Context context) {
- SharedPreferences sharedPrefs = Utilities.getPrefs(context);
- synchronized(sLock) {
- ArrayList<PendingInstallShortcutInfo> infos = new ArrayList<>();
- Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
- if (DBG) Log.d(TAG, "Getting and clearing APPS_PENDING_INSTALL: " + strings);
- if (strings == null) {
- return infos;
- }
- for (String encoded : strings) {
- PendingInstallShortcutInfo info = decode(encoded, context);
- if (info != null) {
- infos.add(info);
+ if (Utilities.isEmpty(strings)) {
+ return;
+ }
+ Set<String> newStrings = new HashSet<>(strings);
+ Iterator<String> newStringsIter = newStrings.iterator();
+ while (newStringsIter.hasNext()) {
+ String encoded = newStringsIter.next();
+ try {
+ Decoder decoder = new Decoder(encoded, context);
+ if (packageNames.contains(getIntentPackage(decoder.launcherIntent)) &&
+ user.equals(decoder.user)) {
+ newStringsIter.remove();
}
+ } catch (JSONException | URISyntaxException e) {
+ Log.d(TAG, "Exception reading shortcut to add: " + e);
+ newStringsIter.remove();
}
- sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, new HashSet<String>()).apply();
- return infos;
}
+ sp.edit().putStringSet(APPS_PENDING_INSTALL, newStrings).apply();
}
public void onReceive(Context context, Intent data) {
@@ -256,7 +286,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
private static void queuePendingShortcutInfo(PendingInstallShortcutInfo info, Context context) {
// Queue the item up for adding if launcher has not loaded properly yet
- addToInstallQueue(Utilities.getPrefs(context), info);
+ Message.obtain(sHandler, MSG_ADD_TO_QUEUE, Pair.create(context, info)).sendToTarget();
flushInstallQueue(context);
}
@@ -269,17 +299,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
static void flushInstallQueue(Context context) {
- LauncherModel model = LauncherAppState.getInstance(context).getModel();
- boolean launcherNotLoaded = model.getCallback() == null;
- if (sInstallQueueDisabledFlags != 0 || launcherNotLoaded) {
+ if (sInstallQueueDisabledFlags != 0) {
return;
}
-
- ArrayList<PendingInstallShortcutInfo> items = getAndClearInstallQueue(context);
- if (!items.isEmpty()) {
- model.addAndBindAddedWorkspaceItems(
- new LazyShortcutsProvider(context.getApplicationContext(), items));
- }
+ Message.obtain(sHandler, MSG_FLUSH_QUEUE, context.getApplicationContext()).sendToTarget();
}
/**
@@ -601,42 +624,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
return new PendingInstallShortcutInfo(info, original.mContext);
}
- private static class LazyShortcutsProvider extends Provider<List<Pair<ItemInfo, Object>>> {
-
- private final Context mContext;
- private final ArrayList<PendingInstallShortcutInfo> mPendingItems;
-
- public LazyShortcutsProvider(Context context, ArrayList<PendingInstallShortcutInfo> items) {
- mContext = context;
- mPendingItems = items;
- }
-
- /**
- * This must be called on the background thread as this requires multiple calls to
- * packageManager and icon cache.
- */
- @Override
- public ArrayList<Pair<ItemInfo, Object>> get() {
- Preconditions.assertNonUiThread();
- ArrayList<Pair<ItemInfo, Object>> installQueue = new ArrayList<>();
- LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
- for (PendingInstallShortcutInfo pendingInfo : mPendingItems) {
- // If the intent specifies a package, make sure the package exists
- String packageName = getIntentPackage(pendingInfo.launchIntent);
- if (!TextUtils.isEmpty(packageName) && !launcherApps.isPackageEnabledForProfile(
- packageName, pendingInfo.user)) {
- if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
- + pendingInfo.launchIntent);
- continue;
- }
-
- // Generate a shortcut info to add into the model
- installQueue.add(pendingInfo.getItemInfo());
- }
- return installQueue;
- }
- }
-
private static ShortcutInfo createShortcutInfo(Intent data, LauncherAppState app) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 74a5bac99..3e2236682 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -192,9 +192,8 @@ public class LauncherModel extends BroadcastReceiver
/**
* Adds the provided items to the workspace.
*/
- public void addAndBindAddedWorkspaceItems(
- Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
- enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider));
+ public void addAndBindAddedWorkspaceItems(List<Pair<ItemInfo, Object>> itemList) {
+ enqueueModelUpdateTask(new AddWorkspaceItemsTask(itemList));
}
public ModelWriter getWriter(boolean hasVerticalHotseat) {
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 42926fa3e..a33a039c0 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -38,7 +38,6 @@ import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ManagedProfileHeuristic.UserFolderInfo;
-import com.android.launcher3.util.Provider;
import java.util.ArrayList;
import java.util.List;
@@ -47,19 +46,18 @@ import java.util.List;
*/
public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
- private final Provider<List<Pair<ItemInfo, Object>>> mAppsProvider;
+ private final List<Pair<ItemInfo, Object>> mItemList;
/**
- * @param appsProvider items to add on the workspace
+ * @param itemList items to add on the workspace
*/
- public AddWorkspaceItemsTask(Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
- mAppsProvider = appsProvider;
+ public AddWorkspaceItemsTask(List<Pair<ItemInfo, Object>> itemList) {
+ mItemList = itemList;
}
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
- List<Pair<ItemInfo, Object>> workspaceApps = mAppsProvider.get();
- if (workspaceApps.isEmpty()) {
+ if (mItemList.isEmpty()) {
return;
}
Context context = app.getContext();
@@ -75,7 +73,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
synchronized(dataModel) {
List<ItemInfo> filteredItems = new ArrayList<>();
- for (Pair<ItemInfo, Object> entry : workspaceApps) {
+ for (Pair<ItemInfo, Object> entry : mItemList) {
ItemInfo item = entry.first;
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
index 82f34e43d..a486cebc2 100644
--- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
+++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java
@@ -55,7 +55,7 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase {
for (ItemInfo item : items) {
list.add(Pair.create(item, null));
}
- return new AddWorkspaceItemsTask(Provider.of(list)) {
+ return new AddWorkspaceItemsTask(list) {
@Override
protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) { }