Merge "Moving ShortcutInfo creation in InstallShortcutReceiver to background thread" into ub-launcher3-master

This commit is contained in:
Sunny Goyal 2016-11-30 16:42:30 +00:00 committed by Android (Google) Code Review
commit b7f5431232
6 changed files with 111 additions and 52 deletions

View File

@ -33,6 +33,8 @@ import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.Thunk;
import org.json.JSONException;
@ -44,6 +46,7 @@ import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class InstallShortcutReceiver extends BroadcastReceiver {
@ -76,11 +79,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
String encoded = info.encodeToString();
if (encoded != null) {
Set<String> strings = sharedPrefs.getStringSet(APPS_PENDING_INSTALL, null);
if (strings == null) {
strings = new HashSet<String>(1);
} else {
strings = new HashSet<String>(strings);
}
strings = (strings != null) ? new HashSet<>(strings) : new HashSet<String>(1);
strings.add(encoded);
sharedPrefs.edit().putStringSet(APPS_PENDING_INSTALL, strings).apply();
}
@ -115,16 +114,15 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
}
private static ArrayList<PendingInstallShortcutInfo> getAndClearInstallQueue(
SharedPreferences sharedPrefs, Context context) {
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 new ArrayList<PendingInstallShortcutInfo>();
return infos;
}
ArrayList<PendingInstallShortcutInfo> infos =
new ArrayList<PendingInstallShortcutInfo>();
for (String encoded : strings) {
PendingInstallShortcutInfo info = decode(encoded, context);
if (info != null) {
@ -212,36 +210,12 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
mUseInstallQueue = false;
flushInstallQueue(context);
}
static void flushInstallQueue(Context context) {
SharedPreferences sp = Utilities.getPrefs(context);
ArrayList<PendingInstallShortcutInfo> installQueue = getAndClearInstallQueue(sp, context);
if (!installQueue.isEmpty()) {
Iterator<PendingInstallShortcutInfo> iter = installQueue.iterator();
ArrayList<ItemInfo> addShortcuts = new ArrayList<ItemInfo>();
while (iter.hasNext()) {
final PendingInstallShortcutInfo pendingInfo = iter.next();
// If the intent specifies a package, make sure the package exists
String packageName = pendingInfo.getTargetPackage();
if (!TextUtils.isEmpty(packageName)) {
UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
if (!LauncherAppsCompat.getInstance(context)
.isPackageEnabledForProfile(packageName, myUserHandle)) {
if (DBG) Log.d(TAG, "Ignoring shortcut for absent package: "
+ pendingInfo.launchIntent);
continue;
}
}
// Generate a shortcut info to add into the model
addShortcuts.add(pendingInfo.getShortcutInfo());
}
// Add the new apps to the model and bind them
if (!addShortcuts.isEmpty()) {
LauncherAppState app = LauncherAppState.getInstance();
app.getModel().addAndBindAddedWorkspaceItems(addShortcuts);
}
ArrayList<PendingInstallShortcutInfo> items = getAndClearInstallQueue(context);
if (!items.isEmpty()) {
LauncherAppState.getInstance().getModel().addAndBindAddedWorkspaceItems(
new LazyShortcutsProvider(context.getApplicationContext(), items));
}
}
@ -445,4 +419,40 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
// Ignore any conflicts in the label name, as that can change based on locale.
return new PendingInstallShortcutInfo(info, original.mContext);
}
private static class LazyShortcutsProvider extends Provider<List<ItemInfo>> {
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<ItemInfo> get() {
Preconditions.assertNonUiThread();
ArrayList<ItemInfo> 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 = pendingInfo.getTargetPackage();
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.getShortcutInfo());
}
return installQueue;
}
}
}

View File

@ -85,6 +85,7 @@ import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.Provider;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.ViewOnDrawExecutor;
@ -257,12 +258,19 @@ public class LauncherModel extends BroadcastReceiver
CacheDataUpdatedTask.OP_SESSION_UPDATE, UserHandleCompat.myUserHandle(), packages));
}
/**
* Adds the provided items to the workspace.
*/
public void addAndBindAddedWorkspaceItems(List<ItemInfo> workspaceApps) {
addAndBindAddedWorkspaceItems(Provider.of(workspaceApps));
}
/**
* Adds the provided items to the workspace.
*/
public void addAndBindAddedWorkspaceItems(
final ArrayList<? extends ItemInfo> workspaceApps) {
enqueueModelUpdateTask(new AddWorkspaceItemsTask(workspaceApps));
Provider<List<ItemInfo>> appsProvider) {
enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider));
}
/**

View File

@ -33,26 +33,29 @@ import com.android.launcher3.LauncherSettings;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.Provider;
import java.util.ArrayList;
import java.util.List;
/**
* Task to add auto-created workspace items.
*/
public class AddWorkspaceItemsTask extends ExtendedModelTask {
private final ArrayList<? extends ItemInfo> mWorkspaceApps;
private final Provider<List<ItemInfo>> mAppsProvider;
/**
* @param workspaceApps items to add on the workspace
* @param appsProvider items to add on the workspace
*/
public AddWorkspaceItemsTask(ArrayList<? extends ItemInfo> workspaceApps) {
mWorkspaceApps = workspaceApps;
public AddWorkspaceItemsTask(Provider<List<ItemInfo>> appsProvider) {
mAppsProvider = appsProvider;
}
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
if (mWorkspaceApps.isEmpty()) {
List<ItemInfo> workspaceApps = mAppsProvider.get();
if (workspaceApps.isEmpty()) {
return;
}
Context context = app.getContext();
@ -65,7 +68,7 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask {
// called.
ArrayList<Long> workspaceScreens = LauncherModel.loadWorkspaceScreensDb(context);
synchronized(dataModel) {
for (ItemInfo item : mWorkspaceApps) {
for (ItemInfo item : workspaceApps) {
if (item instanceof ShortcutInfo) {
// Short-circuit this logic if the icon exists somewhere on the workspace
if (shortcutExists(dataModel, item.getIntent(), item.user)) {
@ -258,5 +261,4 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask {
}
return occupied.findVacantCell(xy, spanX, spanY);
}
}

View File

@ -121,7 +121,7 @@ public class ManagedProfileHeuristic {
// getting filled with the managed user apps, when it start with a fresh DB (or after
// a very long time).
if (userAppsExisted && !homescreenApps.isEmpty()) {
mModel.addAndBindAddedWorkspaceItems(homescreenApps);
mModel.addAndBindAddedWorkspaceItems(new ArrayList<ItemInfo>(homescreenApps));
}
}
@ -173,7 +173,7 @@ public class ManagedProfileHeuristic {
}
// Add the item to home screen and DB. This also generates an item id synchronously.
ArrayList<ItemInfo> itemList = new ArrayList<ItemInfo>(1);
ArrayList<ItemInfo> itemList = new ArrayList<>(1);
itemList.add(workFolder);
mModel.addAndBindAddedWorkspaceItems(itemList);
mPrefs.edit().putLong(folderIdKey, workFolder.id).apply();

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2016 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.launcher3.util;
/**
* Utility class to allow lazy initialization of objects.
*/
public abstract class Provider<T> {
/**
* Initializes and returns the object. This may contain expensive operations not suitable
* to UI thread.
*/
public abstract T get();
public static <T> Provider<T> of (final T value) {
return new Provider<T>() {
@Override
public T get() {
return value;
}
};
}
}

View File

@ -15,6 +15,7 @@ import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.config.ProviderConfig;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.Provider;
import org.mockito.ArgumentCaptor;
@ -48,8 +49,8 @@ public class AddWorkspaceItemsTaskTest extends BaseModelUpdateTaskTestCase {
idp.numRows = 5;
}
private <T extends ItemInfo> AddWorkspaceItemsTask newTask(T... items) {
return new AddWorkspaceItemsTask(new ArrayList<>(Arrays.asList(items))) {
private AddWorkspaceItemsTask newTask(ItemInfo... items) {
return new AddWorkspaceItemsTask(Provider.of(Arrays.asList(items))) {
@Override
protected void addItemToDatabase(Context context, ItemInfo item,