diff options
6 files changed, 111 insertions, 52 deletions
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index 056facba5..d2f25a4a0 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -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); - } + static void flushInstallQueue(Context context) { + 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; + } + } } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index c70a47595..3daa2c30f 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -84,6 +84,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; @@ -261,9 +262,16 @@ public class LauncherModel extends BroadcastReceiver /** * 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)); } /** diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index 986e163e6..97335cb25 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -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); } - } diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java index 78b7a3eee..817a38ad5 100644 --- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java +++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java @@ -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(); diff --git a/src/com/android/launcher3/util/Provider.java b/src/com/android/launcher3/util/Provider.java new file mode 100644 index 000000000..1cdd8d6aa --- /dev/null +++ b/src/com/android/launcher3/util/Provider.java @@ -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; + } + }; + } +} diff --git a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java index ecb3782fc..b2f0cbbbc 100644 --- a/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java +++ b/tests/src/com/android/launcher3/model/AddWorkspaceItemsTaskTest.java @@ -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, |