summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSunny Goyal <sunnygoyal@google.com>2017-05-04 16:47:11 -0700
committerSunny Goyal <sunnygoyal@google.com>2017-05-22 13:31:04 -0700
commita474a9bcf5d533ac942c58409e45e5ec6d8b4893 (patch)
tree86bc1eea564da58343b1d64e414ccd2e8bec2f03 /src
parent998dbecf5397162f13acb8a84cfe71c2ed4d8741 (diff)
downloadandroid_packages_apps_Trebuchet-a474a9bcf5d533ac942c58409e45e5ec6d8b4893.tar.gz
android_packages_apps_Trebuchet-a474a9bcf5d533ac942c58409e45e5ec6d8b4893.tar.bz2
android_packages_apps_Trebuchet-a474a9bcf5d533ac942c58409e45e5ec6d8b4893.zip
Simplifying logic for managed for icon addition
> Checking for duplicate icons before adding new icons For O and above, icon addition is controlled using SessionCommitReceiver. As long as the Launcher is the default app, it will keep adding icons on the homescreen. Apps installed while launcher was not the default homescreen, no icons will be added. For below O, icons are added based on package event. As long as the Launcher process is running, it will keep adding icons on the homescreen. Apps installed while the launcher app was dead, no icons will be added. Bug: 37528649 Bug: 37082950 Bug: 34112546 Change-Id: Ic99501fa476c00474a479f2a36c24614bfa3f4bf
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java57
-rw-r--r--src/com/android/launcher3/Launcher.java16
-rw-r--r--src/com/android/launcher3/LauncherModel.java61
-rw-r--r--src/com/android/launcher3/SessionCommitReceiver.java17
-rw-r--r--src/com/android/launcher3/Workspace.java5
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompatVL.java4
-rw-r--r--src/com/android/launcher3/model/AddWorkspaceItemsTask.java47
-rw-r--r--src/com/android/launcher3/model/PackageUpdatedTask.java14
-rw-r--r--src/com/android/launcher3/util/CachedPackageTracker.java188
-rw-r--r--src/com/android/launcher3/util/ManagedProfileHeuristic.java277
10 files changed, 235 insertions, 451 deletions
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index ce8557065..b136e7d81 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -34,6 +34,7 @@ import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Log;
+import android.util.Pair;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.UserManagerCompat;
@@ -59,6 +60,16 @@ import java.util.List;
import java.util.Set;
public class InstallShortcutReceiver extends BroadcastReceiver {
+
+ 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;
+ public static final int FLAG_BULK_ADD = 4;
+
+ // Determines whether to defer installing shortcuts immediately until
+ // processAllPendingInstalls() is called.
+ private static int sInstallQueueDisabledFlags = 0;
+
private static final String TAG = "InstallShortcutReceiver";
private static final boolean DBG = false;
@@ -151,10 +162,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
}
- // Determines whether to defer installing shortcuts immediately until
- // processAllPendingInstalls() is called.
- private static boolean mUseInstallQueue = false;
-
public void onReceive(Context context, Intent data) {
if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
return;
@@ -207,7 +214,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
public static ShortcutInfo fromShortcutIntent(Context context, Intent data) {
PendingInstallShortcutInfo info = createPendingInfo(context, data);
- return info == null ? null : (ShortcutInfo) info.getItemInfo();
+ return info == null ? null : (ShortcutInfo) info.getItemInfo().first;
}
public static void queueShortcut(ShortcutInfoCompat info, Context context) {
@@ -245,27 +252,28 @@ 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
- LauncherAppState app = LauncherAppState.getInstance(context);
- boolean launcherNotLoaded = app.getModel().getCallback() == null;
-
addToInstallQueue(Utilities.getPrefs(context), info);
- if (!mUseInstallQueue && !launcherNotLoaded) {
- flushInstallQueue(context);
- }
+ flushInstallQueue(context);
}
- static void enableInstallQueue() {
- mUseInstallQueue = true;
+ public static void enableInstallQueue(int flag) {
+ sInstallQueueDisabledFlags |= flag;
}
- static void disableAndFlushInstallQueue(Context context) {
- mUseInstallQueue = false;
+ public static void disableAndFlushInstallQueue(int flag, Context context) {
+ sInstallQueueDisabledFlags &= ~flag;
flushInstallQueue(context);
}
static void flushInstallQueue(Context context) {
+ LauncherModel model = LauncherAppState.getInstance(context).getModel();
+ boolean launcherNotLoaded = model.getCallback() == null;
+ if (sInstallQueueDisabledFlags != 0 || launcherNotLoaded) {
+ return;
+ }
+
ArrayList<PendingInstallShortcutInfo> items = getAndClearInstallQueue(context);
if (!items.isEmpty()) {
- LauncherAppState.getInstance(context).getModel().addAndBindAddedWorkspaceItems(
+ model.addAndBindAddedWorkspaceItems(
new LazyShortcutsProvider(context.getApplicationContext(), items));
}
}
@@ -439,7 +447,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
}
- public ItemInfo getItemInfo() {
+ public Pair<ItemInfo, Object> getItemInfo() {
if (activityInfo != null) {
AppInfo appInfo = new AppInfo(mContext, activityInfo, user);
final LauncherAppState app = LauncherAppState.getInstance(mContext);
@@ -459,11 +467,11 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
}
});
}
- return si;
+ return Pair.create((ItemInfo) si, (Object) activityInfo);
} else if (shortcutInfo != null) {
ShortcutInfo si = new ShortcutInfo(shortcutInfo, mContext);
si.iconBitmap = LauncherIcons.createShortcutIcon(shortcutInfo, mContext);
- return si;
+ return Pair.create((ItemInfo) si, (Object) shortcutInfo);
} else if (providerInfo != null) {
LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo
.fromProviderInfo(mContext, providerInfo);
@@ -475,9 +483,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
widgetInfo.minSpanY = info.minSpanY;
widgetInfo.spanX = Math.min(info.spanX, idp.numColumns);
widgetInfo.spanY = Math.min(info.spanY, idp.numRows);
- return widgetInfo;
+ return Pair.create((ItemInfo) widgetInfo, (Object) providerInfo);
} else {
- return createShortcutInfo(data, LauncherAppState.getInstance(mContext));
+ ShortcutInfo si = createShortcutInfo(data, LauncherAppState.getInstance(mContext));
+ return Pair.create((ItemInfo) si, null);
}
}
@@ -588,7 +597,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
return new PendingInstallShortcutInfo(info, original.mContext);
}
- private static class LazyShortcutsProvider extends Provider<List<ItemInfo>> {
+ private static class LazyShortcutsProvider extends Provider<List<Pair<ItemInfo, Object>>> {
private final Context mContext;
private final ArrayList<PendingInstallShortcutInfo> mPendingItems;
@@ -603,9 +612,9 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
* packageManager and icon cache.
*/
@Override
- public ArrayList<ItemInfo> get() {
+ public ArrayList<Pair<ItemInfo, Object>> get() {
Preconditions.assertNonUiThread();
- ArrayList<ItemInfo> installQueue = new ArrayList<>();
+ 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
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index b63bbd548..b9b561020 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1036,13 +1036,12 @@ public class Launcher extends BaseActivity
updateInteraction(Workspace.State.NORMAL, mWorkspace.getState());
mWorkspace.onResume();
- if (!isWorkspaceLoading()) {
- // Process any items that were added while Launcher was away.
- InstallShortcutReceiver.disableAndFlushInstallQueue(this);
+ // Process any items that were added while Launcher was away.
+ InstallShortcutReceiver.disableAndFlushInstallQueue(
+ InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED, this);
- // Refresh shortcuts if the permission changed.
- mModel.refreshShortcutsIfRequired();
- }
+ // Refresh shortcuts if the permission changed.
+ mModel.refreshShortcutsIfRequired();
if (shouldShowDiscoveryBounce()) {
mAllAppsController.showDiscoveryBounce();
@@ -1057,7 +1056,7 @@ public class Launcher extends BaseActivity
@Override
protected void onPause() {
// Ensure that items added to Launcher are queued until Launcher returns
- InstallShortcutReceiver.enableInstallQueue();
+ InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_ACTIVITY_PAUSED);
super.onPause();
mPaused = true;
@@ -3655,7 +3654,8 @@ public class Launcher extends BaseActivity
mPendingActivityResult = null;
}
- InstallShortcutReceiver.disableAndFlushInstallQueue(this);
+ InstallShortcutReceiver.disableAndFlushInstallQueue(
+ InstallShortcutReceiver.FLAG_LOADER_RUNNING, this);
NotificationListener.setNotificationsChangedListener(mPopupDataProvider);
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 12789c55a..b5ca301d0 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -40,6 +40,7 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.MutableInt;
+import android.util.Pair;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -138,12 +139,6 @@ public class LauncherModel extends BroadcastReceiver
}
}
- /**
- * Set of runnables to be called on the background thread after the workspace binding
- * is complete.
- */
- static final ArrayList<Runnable> mBindCompleteRunnables = new ArrayList<Runnable>();
-
@Thunk WeakReference<Callbacks> mCallbacks;
// < only access in worker thread >
@@ -251,15 +246,8 @@ 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(
- Provider<List<ItemInfo>> appsProvider) {
+ Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
enqueueModelUpdateTask(new AddWorkspaceItemsTask(appsProvider));
}
@@ -529,7 +517,7 @@ public class LauncherModel extends BroadcastReceiver
*/
public boolean startLoader(int synchronousBindPage) {
// Enable queue before starting loader. It will get disabled in Launcher#finishBindingItems
- InstallShortcutReceiver.enableInstallQueue();
+ InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_LOADER_RUNNING);
synchronized (mLock) {
// Don't bother to start the thread if we know it's not going to do anything
if (mCallbacks != null && mCallbacks.get() != null) {
@@ -607,7 +595,6 @@ public class LauncherModel extends BroadcastReceiver
private Context mContext;
private int mPageToBindFirst;
- @Thunk boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
LoaderTask(Context context, int pageToBindFirst) {
@@ -675,8 +662,6 @@ public class LauncherModel extends BroadcastReceiver
try {
long now = 0;
if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
- // Set to false in bindWorkspace()
- mIsLoadingAndBindingWorkspace = true;
loadWorkspace();
verifyNotStopped();
@@ -1584,18 +1569,6 @@ public class LauncherModel extends BroadcastReceiver
callbacks.finishBindingItems();
}
- mIsLoadingAndBindingWorkspace = false;
-
- // Run all the bind complete runnables after workspace is bound.
- if (!mBindCompleteRunnables.isEmpty()) {
- synchronized (mBindCompleteRunnables) {
- for (final Runnable r : mBindCompleteRunnables) {
- runOnWorkerThread(r);
- }
- mBindCompleteRunnables.clear();
- }
- }
-
// If we're profiling, ensure this is the last thing in the queue.
if (DEBUG_LOADERS) {
Log.d(TAG, "bound workspace in "
@@ -1710,31 +1683,7 @@ public class LauncherModel extends BroadcastReceiver
mBgAllAppsList.add(new AppInfo(app, user, quietMode), app);
}
- final ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(mContext, user);
- if (heuristic != null) {
- final Runnable r = new Runnable() {
-
- @Override
- public void run() {
- heuristic.processUserApps(apps);
- }
- };
- mUiExecutor.execute(new Runnable() {
-
- @Override
- public void run() {
- // Check isLoadingWorkspace on the UI thread, as it is updated on
- // the UI thread.
- if (mIsLoadingAndBindingWorkspace) {
- synchronized (mBindCompleteRunnables) {
- mBindCompleteRunnables.add(r);
- }
- } else {
- runOnWorkerThread(r);
- }
- }
- });
- }
+ ManagedProfileHeuristic.onAllAppsLoaded(mContext, apps, user);
}
if (FeatureFlags.LAUNCHER3_PROMISE_APPS_IN_ALL_APPS) {
@@ -1768,8 +1717,6 @@ public class LauncherModel extends BroadcastReceiver
}
}
});
- // Cleanup any data stored for a deleted user.
- ManagedProfileHeuristic.processAllUsers(profiles, mContext);
if (DEBUG_LOADERS) {
Log.d(TAG, "Icons processed in "
+ (SystemClock.uptimeMillis() - loadTime) + "ms");
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 61bcc178c..8caba75cd 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -67,18 +67,19 @@ public class SessionCommitReceiver extends BroadcastReceiver {
SessionInfo info = intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
- if (TextUtils.isEmpty(info.getAppPackageName()) ||
- info.getInstallReason() != PackageManager.INSTALL_REASON_USER) {
- return;
+ if (Process.myUserHandle().equals(user)) {
+ if (TextUtils.isEmpty(info.getAppPackageName()) ||
+ info.getInstallReason() != PackageManager.INSTALL_REASON_USER) {
+ return;
+ }
}
- if (!Process.myUserHandle().equals(user)) {
- // Managed profile is handled using ManagedProfileHeuristic
- return;
- }
+ queueAppIconAddition(context, info.getAppPackageName(), user);
+ }
+ public static void queueAppIconAddition(Context context, String packageName, UserHandle user) {
List<LauncherActivityInfo> activities = LauncherAppsCompat.getInstance(context)
- .getActivityList(info.getAppPackageName(), user);
+ .getActivityList(packageName, user);
if (activities == null || activities.isEmpty()) {
// no activity found
return;
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b3dd7ac60..672203cc5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -451,7 +451,7 @@ public class Workspace extends PagedView
mLauncher.lockScreenOrientation();
mLauncher.onInteractionBegin();
// Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
- InstallShortcutReceiver.enableInstallQueue();
+ InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_DRAG_AND_DROP);
// Do not add a new page if it is a accessible drag which was not started by the workspace.
// We do not support accessibility drag from other sources and instead provide a direct
@@ -504,7 +504,8 @@ public class Workspace extends PagedView
mLauncher.unlockScreenOrientation(false);
// Re-enable any Un/InstallShortcutReceiver and now process any queued items
- InstallShortcutReceiver.disableAndFlushInstallQueue(getContext());
+ InstallShortcutReceiver.disableAndFlushInstallQueue(
+ InstallShortcutReceiver.FLAG_DRAG_AND_DROP, getContext());
mOutlineProvider = null;
mDragInfo = null;
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index 45525f521..c7f88f63d 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -22,8 +22,8 @@ import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.os.UserManager;
-import com.android.launcher3.Utilities;
import com.android.launcher3.util.LongArrayMap;
+import com.android.launcher3.util.ManagedProfileHeuristic;
import java.util.ArrayList;
import java.util.Collections;
@@ -122,7 +122,7 @@ public class UserManagerCompatVL extends UserManagerCompat {
@Override
public long getUserCreationTime(UserHandle user) {
- SharedPreferences prefs = Utilities.getPrefs(mContext);
+ SharedPreferences prefs = ManagedProfileHeuristic.prefs(mContext);
String key = USER_CREATION_TIME_KEY + getSerialNumberForUser(user);
if (!prefs.contains(key)) {
prefs.edit().putLong(key, System.currentTimeMillis()).apply();
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index 10fb5828c..2e8e15bf7 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -17,6 +17,8 @@ package com.android.launcher3.model;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.LauncherActivityInfo;
+import android.os.Process;
import android.os.UserHandle;
import android.util.LongSparseArray;
import android.util.Pair;
@@ -35,9 +37,11 @@ import com.android.launcher3.LauncherSettings;
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.HashMap;
import java.util.List;
/**
@@ -45,18 +49,18 @@ import java.util.List;
*/
public class AddWorkspaceItemsTask extends ExtendedModelTask {
- private final Provider<List<ItemInfo>> mAppsProvider;
+ private final Provider<List<Pair<ItemInfo, Object>>> mAppsProvider;
/**
* @param appsProvider items to add on the workspace
*/
- public AddWorkspaceItemsTask(Provider<List<ItemInfo>> appsProvider) {
+ public AddWorkspaceItemsTask(Provider<List<Pair<ItemInfo, Object>>> appsProvider) {
mAppsProvider = appsProvider;
}
@Override
public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
- List<ItemInfo> workspaceApps = mAppsProvider.get();
+ List<Pair<ItemInfo, Object>> workspaceApps = mAppsProvider.get();
if (workspaceApps.isEmpty()) {
return;
}
@@ -64,13 +68,17 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask {
final ArrayList<ItemInfo> addedItemsFinal = new ArrayList<>();
final ArrayList<Long> addedWorkspaceScreensFinal = new ArrayList<>();
+ HashMap<UserHandle, UserFolderInfo> userFolderMap = new HashMap<>();
// Get the list of workspace screens. We need to append to this list and
// can not use sBgWorkspaceScreens because loadWorkspace() may not have been
// called.
ArrayList<Long> workspaceScreens = LauncherModel.loadWorkspaceScreensDb(context);
synchronized(dataModel) {
- for (ItemInfo item : workspaceApps) {
+
+ List<ItemInfo> filteredItems = new ArrayList<>();
+ for (Pair<ItemInfo, Object> entry : workspaceApps) {
+ ItemInfo item = entry.first;
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
// Short-circuit this logic if the icon exists somewhere on the workspace
@@ -79,6 +87,32 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask {
}
}
+ if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
+ if (item instanceof AppInfo) {
+ item = ((AppInfo) item).makeShortcut();
+ }
+
+ if (!Process.myUserHandle().equals(item.user)) {
+ // Check if this belongs to a work folder.
+ if (!(entry.second instanceof LauncherActivityInfo)) {
+ continue;
+ }
+
+ UserFolderInfo userFolderInfo = userFolderMap.get(item.user);
+ if (userFolderInfo == null) {
+ userFolderInfo = new UserFolderInfo(context, item.user, dataModel);
+ userFolderMap.put(item.user, userFolderInfo);
+ }
+ item = userFolderInfo.convertToWorkspaceItem(
+ (ShortcutInfo) item, (LauncherActivityInfo) entry.second);
+ }
+ }
+ if (item != null) {
+ filteredItems.add(item);
+ }
+ }
+
+ for (ItemInfo item : filteredItems) {
// Find appropriate space for the item.
Pair<Long, int[]> coords = findSpaceForItem(app, dataModel, workspaceScreens,
addedWorkspaceScreensFinal, item.spanX, item.spanY);
@@ -130,6 +164,10 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask {
}
});
}
+
+ for (UserFolderInfo userFolderInfo : userFolderMap.values()) {
+ userFolderInfo.applyPendingState(getModelWriter());
+ }
}
protected void updateScreens(Context context, ArrayList<Long> workspaceScreens) {
@@ -276,4 +314,5 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask {
}
return occupied.findVacantCell(xy, spanX, spanY);
}
+
}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index b58efb647..8380f0136 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -35,6 +35,7 @@ import com.android.launcher3.LauncherModel.CallbackTask;
import com.android.launcher3.LauncherModel.Callbacks;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -43,7 +44,6 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.util.FlagOp;
import com.android.launcher3.util.ItemInfoMatcher;
-import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
@@ -100,11 +100,11 @@ public class PackageUpdatedTask extends ExtendedModelTask {
appsList.removePackage(packages[i], Process.myUserHandle());
}
appsList.addPackage(context, packages[i], mUser);
- }
- ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
- if (heuristic != null) {
- heuristic.processPackageAdd(mPackages);
+ // Automatically add homescreen icon for work profile apps for below O device.
+ if (!Utilities.isAtLeastO() && !Process.myUserHandle().equals(mUser)) {
+ SessionCommitReceiver.queueAppIconAddition(context, packages[i], mUser);
+ }
}
break;
}
@@ -119,10 +119,6 @@ public class PackageUpdatedTask extends ExtendedModelTask {
flagOp = FlagOp.removeFlag(ShortcutInfo.FLAG_DISABLED_NOT_AVAILABLE);
break;
case OP_REMOVE: {
- ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
- if (heuristic != null) {
- heuristic.processPackageRemoved(mPackages);
- }
for (int i = 0; i < N; i++) {
iconCache.removeIconsForPkg(packages[i], mUser);
}
diff --git a/src/com/android/launcher3/util/CachedPackageTracker.java b/src/com/android/launcher3/util/CachedPackageTracker.java
deleted file mode 100644
index 314b4c0ed..000000000
--- a/src/com/android/launcher3/util/CachedPackageTracker.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.pm.LauncherActivityInfo;
-import android.os.UserHandle;
-
-import com.android.launcher3.Utilities;
-import com.android.launcher3.compat.LauncherAppsCompat;
-import com.android.launcher3.compat.LauncherAppsCompat.OnAppsChangedCallbackCompat;
-import com.android.launcher3.compat.UserManagerCompat;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Utility class to track list of installed packages. It persists the list so that apps
- * installed/uninstalled while Launcher was dead can also be handled properly.
- */
-public abstract class CachedPackageTracker implements OnAppsChangedCallbackCompat {
-
- protected static final String INSTALLED_PACKAGES_PREFIX = "installed_packages_for_user_";
-
- protected final SharedPreferences mPrefs;
- protected final UserManagerCompat mUserManager;
- protected final LauncherAppsCompat mLauncherApps;
-
- public CachedPackageTracker(Context context, String preferenceFileName) {
- mPrefs = context.getSharedPreferences(preferenceFileName, Context.MODE_PRIVATE);
- mUserManager = UserManagerCompat.getInstance(context);
- mLauncherApps = LauncherAppsCompat.getInstance(context);
- }
-
- /**
- * Checks the list of user apps, and generates package event accordingly.
- * {@see #onLauncherAppsAdded}, {@see #onLauncherPackageRemoved}
- */
- public void processUserApps(List<LauncherActivityInfo> apps, UserHandle user) {
- String prefKey = INSTALLED_PACKAGES_PREFIX + mUserManager.getSerialNumberForUser(user);
- HashSet<String> oldPackageSet = new HashSet<>();
- final boolean userAppsExisted = getUserApps(oldPackageSet, prefKey);
-
- HashSet<String> packagesRemoved = new HashSet<>(oldPackageSet);
- HashSet<String> newPackageSet = new HashSet<>();
- ArrayList<LauncherActivityInstallInfo> packagesAdded = new ArrayList<>();
-
- for (LauncherActivityInfo info : apps) {
- String packageName = info.getComponentName().getPackageName();
- newPackageSet.add(packageName);
- packagesRemoved.remove(packageName);
-
- if (!oldPackageSet.contains(packageName)) {
- oldPackageSet.add(packageName);
- packagesAdded.add(new LauncherActivityInstallInfo(
- info, info.getFirstInstallTime()));
- }
- }
-
- if (!packagesAdded.isEmpty() || !packagesRemoved.isEmpty()) {
- mPrefs.edit().putStringSet(prefKey, newPackageSet).apply();
-
- if (!packagesAdded.isEmpty()) {
- Collections.sort(packagesAdded);
- onLauncherAppsAdded(packagesAdded, user, userAppsExisted);
- }
-
- if (!packagesRemoved.isEmpty()) {
- for (String pkg : packagesRemoved) {
- onLauncherPackageRemoved(pkg, user);
- }
- }
- }
- }
-
- /**
- * Reads the list of user apps which have already been processed.
- * @return false if the list didn't exist, true otherwise
- */
- private boolean getUserApps(HashSet<String> outExistingApps, String prefKey) {
- Set<String> userApps = mPrefs.getStringSet(prefKey, null);
- if (userApps == null) {
- return false;
- } else {
- outExistingApps.addAll(userApps);
- return true;
- }
- }
-
- @Override
- public void onPackageRemoved(String packageName, UserHandle user) {
- String prefKey = INSTALLED_PACKAGES_PREFIX + mUserManager.getSerialNumberForUser(user);
- HashSet<String> packageSet = new HashSet<>();
- if (getUserApps(packageSet, prefKey) && packageSet.remove(packageName)) {
- mPrefs.edit().putStringSet(prefKey, packageSet).apply();
- }
-
- onLauncherPackageRemoved(packageName, user);
- }
-
- @Override
- public void onPackageAdded(String packageName, UserHandle user) {
- String prefKey = INSTALLED_PACKAGES_PREFIX + mUserManager.getSerialNumberForUser(user);
- HashSet<String> packageSet = new HashSet<>();
- final boolean userAppsExisted = getUserApps(packageSet, prefKey);
- if (!packageSet.contains(packageName)) {
- List<LauncherActivityInfo> activities =
- mLauncherApps.getActivityList(packageName, user);
- if (!activities.isEmpty()) {
- LauncherActivityInfo activityInfo = activities.get(0);
-
- packageSet.add(packageName);
- mPrefs.edit().putStringSet(prefKey, packageSet).apply();
- onLauncherAppsAdded(Arrays.asList(
- new LauncherActivityInstallInfo(activityInfo, System.currentTimeMillis())),
- user, userAppsExisted);
- }
- }
- }
-
- @Override
- public void onPackageChanged(String packageName, UserHandle user) { }
-
- @Override
- public void onPackagesAvailable(
- String[] packageNames, UserHandle user, boolean replacing) { }
-
- @Override
- public void onPackagesUnavailable(
- String[] packageNames, UserHandle user, boolean replacing) { }
-
- @Override
- public void onPackagesSuspended(String[] packageNames, UserHandle user) { }
-
- @Override
- public void onPackagesUnsuspended(String[] packageNames, UserHandle user) { }
-
- /**
- * Called when new launcher apps are added.
- * @param apps list of newly added activities. Only one entry per package is sent.
- * @param user the user for this event. All activities in {@param apps} will belong to
- * the same user.
- * @param userAppsExisted false if the list was processed for the first time, like in case
- * when Launcher was newly installed or a new user was added.
- */
- protected abstract void onLauncherAppsAdded(List<LauncherActivityInstallInfo> apps,
- UserHandle user, boolean userAppsExisted);
-
- /**
- * Called when apps are removed from the system.
- */
- protected abstract void onLauncherPackageRemoved(String packageName, UserHandle user);
-
- public static class LauncherActivityInstallInfo
- implements Comparable<LauncherActivityInstallInfo> {
- public final LauncherActivityInfo info;
- public final long installTime;
-
- public LauncherActivityInstallInfo(LauncherActivityInfo info, long installTime) {
- this.info = info;
- this.installTime = installTime;
- }
-
- @Override
- public int compareTo(LauncherActivityInstallInfo another) {
- return Utilities.longCompare(installTime, another.installTime);
- }
- }
-}
diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
index ce603c4c2..091dd84bc 100644
--- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java
+++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
@@ -19,23 +19,23 @@ package com.android.launcher3.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.LauncherActivityInfo;
+import android.os.Handler;
import android.os.Process;
import android.os.UserHandle;
-import android.support.v4.os.BuildCompat;
-import com.android.launcher3.AppInfo;
import com.android.launcher3.FolderInfo;
-import com.android.launcher3.IconCache;
+import com.android.launcher3.InstallShortcutReceiver;
import com.android.launcher3.ItemInfo;
-import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.R;
import com.android.launcher3.SessionCommitReceiver;
import com.android.launcher3.ShortcutInfo;
+import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.shortcuts.ShortcutInfoCompat;
+import com.android.launcher3.model.BgDataModel;
+import com.android.launcher3.model.ModelWriter;
import java.util.ArrayList;
import java.util.HashSet;
@@ -47,11 +47,6 @@ import java.util.List;
*/
public class ManagedProfileHeuristic {
- /**
- * Maintain a set of packages installed per user.
- */
- private static final String INSTALLED_PACKAGES_PREFIX = "installed_packages_for_user_";
-
private static final String USER_FOLDER_ID_PREFIX = "user_folder_";
/**
@@ -59,165 +54,154 @@ public class ManagedProfileHeuristic {
*/
private static final long AUTO_ADD_TO_FOLDER_DURATION = 8 * 60 * 60 * 1000;
- public static ManagedProfileHeuristic get(Context context, UserHandle user) {
- if (!Process.myUserHandle().equals(user)) {
- return new ManagedProfileHeuristic(context, user);
+ public static void onAllAppsLoaded(final Context context,
+ List<LauncherActivityInfo> apps, UserHandle user) {
+ if (Process.myUserHandle().equals(user)) {
+ return;
}
- return null;
- }
- private final Context mContext;
- private final LauncherModel mModel;
- private final UserHandle mUser;
- private final IconCache mIconCache;
- private final boolean mAddIconsToHomescreen;
-
- private ManagedProfileHeuristic(Context context, UserHandle user) {
- mContext = context;
- mUser = user;
- mModel = LauncherAppState.getInstance(context).getModel();
- mIconCache = LauncherAppState.getInstance(context).getIconCache();
- mAddIconsToHomescreen =
- !BuildCompat.isAtLeastO() || SessionCommitReceiver.isEnabled(context);
- }
+ UserFolderInfo ufi = new UserFolderInfo(context, user, null);
+ // We only handle folder creation once. Later icon additions are handled using package
+ // or session events.
+ if (ufi.folderAlreadyCreated) {
+ return;
+ }
- public void processPackageRemoved(String[] packages) {
- Preconditions.assertWorkerThread();
- ManagedProfilePackageHandler handler = new ManagedProfilePackageHandler();
- for (String pkg : packages) {
- handler.onPackageRemoved(pkg, mUser);
+ if (Utilities.isAtLeastO() && !SessionCommitReceiver.isEnabled(context)) {
+ // Just mark the folder id preference to avoid new folder creation later.
+ ufi.prefs.edit().putLong(ufi.folderIdKey, ItemInfo.NO_ID).apply();
+ return;
}
- }
- public void processPackageAdd(String[] packages) {
- Preconditions.assertWorkerThread();
- ManagedProfilePackageHandler handler = new ManagedProfilePackageHandler();
- for (String pkg : packages) {
- handler.onPackageAdded(pkg, mUser);
+ InstallShortcutReceiver.enableInstallQueue(InstallShortcutReceiver.FLAG_BULK_ADD);
+ for (LauncherActivityInfo app : apps) {
+ // Queue all items which should go in the work folder.
+ if (app.getFirstInstallTime() < ufi.addIconToFolderTime) {
+ InstallShortcutReceiver.queueActivityInfo(app, context);
+ }
}
+ // Post the queue update on next frame, so that the loader gets finished.
+ new Handler(LauncherModel.getWorkerLooper()).post(new Runnable() {
+ @Override
+ public void run() {
+ InstallShortcutReceiver.disableAndFlushInstallQueue(
+ InstallShortcutReceiver.FLAG_BULK_ADD, context);
+ }
+ });
}
- public void processUserApps(List<LauncherActivityInfo> apps) {
- Preconditions.assertWorkerThread();
- new ManagedProfilePackageHandler().processUserApps(apps, mUser);
- }
- private class ManagedProfilePackageHandler extends CachedPackageTracker {
+ /**
+ * Utility class to help workspace icon addition.
+ */
+ public static class UserFolderInfo {
- private ManagedProfilePackageHandler() {
- super(mContext, LauncherFiles.MANAGED_USER_PREFERENCES_KEY);
- }
+ final ArrayList<ShortcutInfo> pendingShortcuts = new ArrayList<>();
- protected void onLauncherAppsAdded(
- List<LauncherActivityInstallInfo> apps, UserHandle user, boolean userAppsExisted) {
- ArrayList<ShortcutInfo> workFolderApps = new ArrayList<>();
- ArrayList<ShortcutInfo> homescreenApps = new ArrayList<>();
-
- int count = apps.size();
- long folderCreationTime =
- mUserManager.getUserCreationTime(user) + AUTO_ADD_TO_FOLDER_DURATION;
-
- boolean quietModeEnabled = UserManagerCompat.getInstance(mContext)
- .isQuietModeEnabled(user);
- for (int i = 0; i < count; i++) {
- LauncherActivityInstallInfo info = apps.get(i);
- AppInfo appInfo = new AppInfo(info.info, user, quietModeEnabled);
- mIconCache.getTitleAndIcon(appInfo, info.info, false /* useLowResIcon */);
- ShortcutInfo si = appInfo.makeShortcut();
- ((info.installTime <= folderCreationTime) ? workFolderApps : homescreenApps).add(si);
- }
+ final UserHandle user;
- finalizeWorkFolder(user, workFolderApps, homescreenApps);
+ final long userSerial;
+ // Time until which icons will be added to folder instead.
+ final long addIconToFolderTime;
- // Do not add shortcuts on the homescreen for the first time. This prevents the launcher
- // getting filled with the managed user apps, when it start with a fresh DB (or after
- // a very long time).
- if (userAppsExisted && !homescreenApps.isEmpty() && mAddIconsToHomescreen) {
- mModel.addAndBindAddedWorkspaceItems(new ArrayList<ItemInfo>(homescreenApps));
- }
- }
+ final String folderIdKey;
+ final SharedPreferences prefs;
+
+ final boolean folderAlreadyCreated;
+ final FolderInfo folderInfo;
+
+ boolean folderPendingAddition;
+
+ public UserFolderInfo(Context context, UserHandle user, BgDataModel dataModel) {
+ this.user = user;
+
+ UserManagerCompat um = UserManagerCompat.getInstance(context);
+ userSerial = um.getSerialNumberForUser(user);
+ addIconToFolderTime = um.getUserCreationTime(user) + AUTO_ADD_TO_FOLDER_DURATION;
- @Override
- protected void onLauncherPackageRemoved(String packageName, UserHandle user) {
+ folderIdKey = USER_FOLDER_ID_PREFIX + userSerial;
+ prefs = prefs(context);
+
+ folderAlreadyCreated = prefs.contains(folderIdKey);
+ if (dataModel != null) {
+ if (folderAlreadyCreated) {
+ long folderId = prefs.getLong(folderIdKey, ItemInfo.NO_ID);
+ folderInfo = dataModel.folders.get(folderId);
+ } else {
+ folderInfo = new FolderInfo();
+ folderInfo.title = context.getText(R.string.work_folder_name);
+ folderInfo.setOption(FolderInfo.FLAG_WORK_FOLDER, true, null);
+ folderPendingAddition = true;
+ }
+ } else {
+ folderInfo = null;
+ }
}
/**
- * Adds and binds shortcuts marked to be added to the work folder.
+ * Returns the ItemInfo which should be added to the workspace. In case the the provided
+ * {@link ShortcutInfo} or a wrapped {@link FolderInfo} or null.
*/
- private void finalizeWorkFolder(
- UserHandle user, final ArrayList<ShortcutInfo> workFolderApps,
- ArrayList<ShortcutInfo> homescreenApps) {
- if (workFolderApps.isEmpty()) {
- return;
+ public ItemInfo convertToWorkspaceItem(
+ ShortcutInfo shortcut, LauncherActivityInfo activityInfo) {
+ if (activityInfo.getFirstInstallTime() >= addIconToFolderTime) {
+ return shortcut;
}
- // Try to get a work folder.
- String folderIdKey = USER_FOLDER_ID_PREFIX + mUserManager.getSerialNumberForUser(user);
- if (!mAddIconsToHomescreen) {
- if (!mPrefs.contains(folderIdKey)) {
- // Just mark the folder id preference to avoid new folder creation later.
- mPrefs.edit().putLong(folderIdKey, -1).apply();
+
+ if (folderAlreadyCreated) {
+ if (folderInfo == null) {
+ // Work folder was deleted by user, add icon to home screen.
+ return shortcut;
+ } else {
+ // Add item to work folder instead. Nothing needs to be added
+ // on the homescreen.
+ pendingShortcuts.add(shortcut);
+ return null;
}
+ }
+
+ pendingShortcuts.add(shortcut);
+ folderInfo.add(shortcut, false);
+ if (folderPendingAddition) {
+ folderPendingAddition = false;
+ return folderInfo;
+ } else {
+ // WorkFolder already requested to be added. Nothing new needs to be added.
+ return null;
+ }
+ }
+
+ public void applyPendingState(ModelWriter writer) {
+ if (folderInfo == null) {
return;
}
- if (mPrefs.contains(folderIdKey)) {
- long folderId = mPrefs.getLong(folderIdKey, 0);
- final FolderInfo workFolder = mModel.findFolderById(folderId);
-
- if (workFolder == null || !workFolder.hasOption(FolderInfo.FLAG_WORK_FOLDER)) {
- // Could not get a work folder. Add all the icons to homescreen.
- homescreenApps.addAll(0, workFolderApps);
- return;
- }
- saveWorkFolderShortcuts(folderId, workFolder.contents.size(), workFolderApps);
+ int startingRank = 0;
+ if (folderAlreadyCreated) {
+ startingRank = folderInfo.contents.size();
+ }
+
+ for (ShortcutInfo info : pendingShortcuts) {
+ info.rank = startingRank++;
+ writer.addItemToDatabase(info, folderInfo.id, 0, 0, 0);
+ }
+
+ if (folderAlreadyCreated) {
// FolderInfo could already be bound. We need to add shortcuts on the UI thread.
new MainThreadExecutor().execute(new Runnable() {
@Override
public void run() {
- workFolder.prepareAutoUpdate();
- for (ShortcutInfo info : workFolderApps) {
- workFolder.add(info, false);
+ folderInfo.prepareAutoUpdate();
+ for (ShortcutInfo info : pendingShortcuts) {
+ folderInfo.add(info, false);
}
}
});
} else {
- // Create a new folder.
- final FolderInfo workFolder = new FolderInfo();
- workFolder.title = mContext.getText(R.string.work_folder_name);
- workFolder.setOption(FolderInfo.FLAG_WORK_FOLDER, true, null);
-
- // Add all shortcuts before adding it to the UI, as an empty folder might get deleted.
- for (ShortcutInfo info : workFolderApps) {
- workFolder.add(info, false);
- }
-
- // Add the item to home screen and DB. This also generates an item id synchronously.
- ArrayList<ItemInfo> itemList = new ArrayList<>(1);
- itemList.add(workFolder);
- mModel.addAndBindAddedWorkspaceItems(itemList);
- mPrefs.edit().putLong(folderIdKey, workFolder.id).apply();
-
- saveWorkFolderShortcuts(workFolder.id, 0, workFolderApps);
+ prefs.edit().putLong(folderIdKey, folderInfo.id).apply();
}
}
-
- @Override
- public void onShortcutsChanged(String packageName, List<ShortcutInfoCompat> shortcuts,
- UserHandle user) {
- // Do nothing
- }
- }
-
- /**
- * Add work folder shortcuts to the DB.
- */
- private void saveWorkFolderShortcuts(
- long workFolderId, int startingRank, ArrayList<ShortcutInfo> workFolderApps) {
- for (ItemInfo info : workFolderApps) {
- info.rank = startingRank++;
- mModel.getWriter(false).addItemToDatabase(info, workFolderId, 0, 0, 0);
- }
}
/**
@@ -225,14 +209,12 @@ public class ManagedProfileHeuristic {
*/
public static void processAllUsers(List<UserHandle> users, Context context) {
UserManagerCompat userManager = UserManagerCompat.getInstance(context);
- HashSet<String> validKeys = new HashSet<String>();
+ HashSet<String> validKeys = new HashSet<>();
for (UserHandle user : users) {
- addAllUserKeys(userManager.getSerialNumberForUser(user), validKeys);
+ validKeys.add(USER_FOLDER_ID_PREFIX + userManager.getSerialNumberForUser(user));
}
- SharedPreferences prefs = context.getSharedPreferences(
- LauncherFiles.MANAGED_USER_PREFERENCES_KEY,
- Context.MODE_PRIVATE);
+ SharedPreferences prefs = prefs(context);
SharedPreferences.Editor editor = prefs.edit();
for (String key : prefs.getAll().keySet()) {
if (!validKeys.contains(key)) {
@@ -242,11 +224,6 @@ public class ManagedProfileHeuristic {
editor.apply();
}
- private static void addAllUserKeys(long userSerial, HashSet<String> keysOut) {
- keysOut.add(INSTALLED_PACKAGES_PREFIX + userSerial);
- keysOut.add(USER_FOLDER_ID_PREFIX + userSerial);
- }
-
/**
* For each user, if a work folder has not been created, mark it such that the folder will
* never get created.
@@ -260,11 +237,8 @@ public class ManagedProfileHeuristic {
if (myUser.equals(user)) {
continue;
}
-
if (prefs == null) {
- prefs = context.getSharedPreferences(
- LauncherFiles.MANAGED_USER_PREFERENCES_KEY,
- Context.MODE_PRIVATE);
+ prefs = prefs(context);
}
String folderIdKey = USER_FOLDER_ID_PREFIX + userManager.getSerialNumberForUser(user);
if (!prefs.contains(folderIdKey)) {
@@ -272,4 +246,9 @@ public class ManagedProfileHeuristic {
}
}
}
+
+ public static SharedPreferences prefs(Context context) {
+ return context.getSharedPreferences(
+ LauncherFiles.MANAGED_USER_PREFERENCES_KEY, Context.MODE_PRIVATE);
+ }
}