diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2016-04-21 19:37:08 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2016-04-22 11:50:01 -0700 |
commit | 752848a3b1f4d127f8665517b3e5999cea2fac56 (patch) | |
tree | c4e5d2c54611842f25a6482ce02f6a17a8d8c4a5 /src | |
parent | cc8f9e0af7f9acc6f03a1a0173d3e118b4e96ae5 (diff) | |
download | android_packages_apps_Trebuchet-752848a3b1f4d127f8665517b3e5999cea2fac56.tar.gz android_packages_apps_Trebuchet-752848a3b1f4d127f8665517b3e5999cea2fac56.tar.bz2 android_packages_apps_Trebuchet-752848a3b1f4d127f8665517b3e5999cea2fac56.zip |
Refactoring package tracking in managed profile heuristic into a
separate class
Change-Id: I4f346422e5c7f94f8559942e21aa01b5c96cd8be
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher3/util/CachedPackageTracker.java | 188 | ||||
-rw-r--r-- | src/com/android/launcher3/util/ManagedProfileHeuristic.java | 285 |
2 files changed, 278 insertions, 195 deletions
diff --git a/src/com/android/launcher3/util/CachedPackageTracker.java b/src/com/android/launcher3/util/CachedPackageTracker.java new file mode 100644 index 000000000..d55d57335 --- /dev/null +++ b/src/com/android/launcher3/util/CachedPackageTracker.java @@ -0,0 +1,188 @@ +/* + * 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 com.android.launcher3.Utilities; +import com.android.launcher3.compat.LauncherActivityInfoCompat; +import com.android.launcher3.compat.LauncherAppsCompat; +import com.android.launcher3.compat.LauncherAppsCompat.OnAppsChangedCallbackCompat; +import com.android.launcher3.compat.UserHandleCompat; +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<LauncherActivityInfoCompat> apps, UserHandleCompat 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 (LauncherActivityInfoCompat 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, UserHandleCompat 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, UserHandleCompat 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<LauncherActivityInfoCompat> activities = + mLauncherApps.getActivityList(packageName, user); + if (!activities.isEmpty()) { + LauncherActivityInfoCompat 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, UserHandleCompat user) { } + + @Override + public void onPackagesAvailable( + String[] packageNames, UserHandleCompat user, boolean replacing) { } + + @Override + public void onPackagesUnavailable( + String[] packageNames, UserHandleCompat user, boolean replacing) { } + + @Override + public void onPackagesSuspended(String[] packageNames, UserHandleCompat user) { } + + @Override + public void onPackagesUnsuspended(String[] packageNames, UserHandleCompat 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, + UserHandleCompat user, boolean userAppsExisted); + + /** + * Called when apps are removed from the system. + */ + protected abstract void onLauncherPackageRemoved(String packageName, UserHandleCompat user); + + protected static class LauncherActivityInstallInfo + implements Comparable<LauncherActivityInstallInfo> { + public final LauncherActivityInfoCompat info; + public final long installTime; + + public LauncherActivityInstallInfo(LauncherActivityInfoCompat 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 3925c4034..df23abe08 100644 --- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java +++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java @@ -16,14 +16,8 @@ package com.android.launcher3.util; -import android.annotation.TargetApi; import android.content.Context; import android.content.SharedPreferences; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.os.Build; -import android.util.Log; import com.android.launcher3.FolderInfo; import com.android.launcher3.ItemInfo; @@ -35,27 +29,19 @@ import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; import com.android.launcher3.Utilities; import com.android.launcher3.compat.LauncherActivityInfoCompat; -import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.compat.UserManagerCompat; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Set; /** * Handles addition of app shortcuts for managed profiles. * Methods of class should only be called on {@link LauncherModel#sWorkerThread}. */ -@TargetApi(Build.VERSION_CODES.LOLLIPOP) public class ManagedProfileHeuristic { - private static final String TAG = "ManagedProfileHeuristic"; - /** * Maintain a set of packages installed per user. */ @@ -76,229 +62,138 @@ public class ManagedProfileHeuristic { } private final Context mContext; - private final UserHandleCompat mUser; private final LauncherModel mModel; - - private final SharedPreferences mPrefs; - private final long mUserSerial; - private final long mUserCreationTime; - private final String mPackageSetKey; - - private ArrayList<ShortcutInfo> mHomescreenApps; - private ArrayList<ShortcutInfo> mWorkFolderApps; - private HashMap<ShortcutInfo, Long> mShortcutToInstallTimeMap; + private final UserHandleCompat mUser; private ManagedProfileHeuristic(Context context, UserHandleCompat user) { mContext = context; mUser = user; mModel = LauncherAppState.getInstance().getModel(); - - UserManagerCompat userManager = UserManagerCompat.getInstance(context); - mUserSerial = userManager.getSerialNumberForUser(user); - mUserCreationTime = userManager.getUserCreationTime(user); - mPackageSetKey = INSTALLED_PACKAGES_PREFIX + mUserSerial; - - mPrefs = mContext.getSharedPreferences(LauncherFiles.MANAGED_USER_PREFERENCES_KEY, - Context.MODE_PRIVATE); } - private void initVars() { - mHomescreenApps = new ArrayList<>(); - mWorkFolderApps = new ArrayList<>(); - mShortcutToInstallTimeMap = new HashMap<>(); - } - - /** - * Checks the list of user apps and adds icons for newly installed apps on the homescreen or - * workfolder. - */ - public void processUserApps(List<LauncherActivityInfoCompat> apps) { - initVars(); - - HashSet<String> packageSet = new HashSet<>(); - final boolean userAppsExisted = getUserApps(packageSet); - - boolean newPackageAdded = false; - for (LauncherActivityInfoCompat info : apps) { - String packageName = info.getComponentName().getPackageName(); - if (!packageSet.contains(packageName)) { - packageSet.add(packageName); - newPackageAdded = true; - markForAddition(info, info.getFirstInstallTime()); - } + public void processPackageRemoved(String[] packages) { + Preconditions.assertWorkerThread(); + ManagedProfilePackageHandler handler = new ManagedProfilePackageHandler(); + for (String pkg : packages) { + handler.onPackageRemoved(pkg, mUser); } + } - if (newPackageAdded) { - mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply(); - // 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). - finalizeAdditions(userAppsExisted); + public void processPackageAdd(String[] packages) { + Preconditions.assertWorkerThread(); + ManagedProfilePackageHandler handler = new ManagedProfilePackageHandler(); + for (String pkg : packages) { + handler.onPackageAdded(pkg, mUser); } } - private void markForAddition(LauncherActivityInfoCompat info, long installTime) { - ArrayList<ShortcutInfo> targetList = - (installTime <= mUserCreationTime + AUTO_ADD_TO_FOLDER_DURATION) ? - mWorkFolderApps : mHomescreenApps; - ShortcutInfo si = ShortcutInfo.fromActivityInfo(info, mContext); - mShortcutToInstallTimeMap.put(si, installTime); - targetList.add(si); + public void processUserApps(List<LauncherActivityInfoCompat> apps) { + Preconditions.assertWorkerThread(); + new ManagedProfilePackageHandler().processUserApps(apps, mUser); } - private void sortList(ArrayList<ShortcutInfo> infos) { - Collections.sort(infos, new Comparator<ShortcutInfo>() { + private class ManagedProfilePackageHandler extends CachedPackageTracker { - @Override - public int compare(ShortcutInfo lhs, ShortcutInfo rhs) { - Long lhsTime = mShortcutToInstallTimeMap.get(lhs); - Long rhsTime = mShortcutToInstallTimeMap.get(rhs); - return Utilities.longCompare(lhsTime == null ? 0 : lhsTime, - rhsTime == null ? 0 : rhsTime); - } - }); - } - - /** - * Adds and binds shortcuts marked to be added to the work folder. - */ - private void finalizeWorkFolder() { - if (mWorkFolderApps.isEmpty()) { - return; + private ManagedProfilePackageHandler() { + super(mContext, LauncherFiles.MANAGED_USER_PREFERENCES_KEY); } - sortList(mWorkFolderApps); - // Try to get a work folder. - String folderIdKey = USER_FOLDER_ID_PREFIX + mUserSerial; - if (mPrefs.contains(folderIdKey)) { - long folderId = mPrefs.getLong(folderIdKey, 0); - final FolderInfo workFolder = mModel.findFolderById(folderId); + protected void onLauncherAppsAdded( + List<LauncherActivityInstallInfo> apps, UserHandleCompat user, boolean userAppsExisted) { + ArrayList<ShortcutInfo> workFolderApps = new ArrayList<>(); + ArrayList<ShortcutInfo> homescreenApps = new ArrayList<>(); - if (workFolder == null || !workFolder.hasOption(FolderInfo.FLAG_WORK_FOLDER)) { - // Could not get a work folder. Add all the icons to homescreen. - mHomescreenApps.addAll(mWorkFolderApps); - return; - } - saveWorkFolderShortcuts(folderId, workFolder.contents.size()); + int count = apps.size(); + long folderCreationTime = + mUserManager.getUserCreationTime(user) + AUTO_ADD_TO_FOLDER_DURATION; - final ArrayList<ShortcutInfo> shortcuts = mWorkFolderApps; - // FolderInfo could already be bound. We need to add shortcuts on the UI thread. - new MainThreadExecutor().execute(new Runnable() { + for (int i = 0; i < count; i++) { + LauncherActivityInstallInfo info = apps.get(i); - @Override - public void run() { - for (ShortcutInfo info : shortcuts) { - workFolder.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 : mWorkFolderApps) { - workFolder.add(info, false); + ShortcutInfo si = ShortcutInfo.fromActivityInfo(info.info, mContext); + ((info.installTime <= folderCreationTime) ? workFolderApps : homescreenApps).add(si); } - // Add the item to home screen and DB. This also generates an item id synchronously. - ArrayList<ItemInfo> itemList = new ArrayList<ItemInfo>(1); - itemList.add(workFolder); - mModel.addAndBindAddedWorkspaceItems(mContext, itemList); - mPrefs.edit().putLong(USER_FOLDER_ID_PREFIX + mUserSerial, workFolder.id).apply(); + finalizeWorkFolder(user, workFolderApps, homescreenApps); - saveWorkFolderShortcuts(workFolder.id, 0); + // 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()) { + mModel.addAndBindAddedWorkspaceItems(mContext, homescreenApps); + } } - } - /** - * Add work folder shortcuts to the DB. - */ - private void saveWorkFolderShortcuts(long workFolderId, int startingRank) { - for (ItemInfo info : mWorkFolderApps) { - info.rank = startingRank++; - LauncherModel.addItemToDatabase(mContext, info, workFolderId, 0, 0, 0); + @Override + protected void onLauncherPackageRemoved(String packageName, UserHandleCompat user) { } - } - /** - * Adds and binds all shortcuts marked for addition. - */ - private void finalizeAdditions(boolean addHomeScreenShortcuts) { - finalizeWorkFolder(); + /** + * Adds and binds shortcuts marked to be added to the work folder. + */ + private void finalizeWorkFolder( + UserHandleCompat user, final ArrayList<ShortcutInfo> workFolderApps, + ArrayList<ShortcutInfo> homescreenApps) { + if (workFolderApps.isEmpty()) { + return; + } + // Try to get a work folder. + String folderIdKey = USER_FOLDER_ID_PREFIX + mUserManager.getSerialNumberForUser(user); + 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); - if (addHomeScreenShortcuts && !mHomescreenApps.isEmpty()) { - sortList(mHomescreenApps); - mModel.addAndBindAddedWorkspaceItems(mContext, mHomescreenApps); - } - } + // FolderInfo could already be bound. We need to add shortcuts on the UI thread. + new MainThreadExecutor().execute(new Runnable() { - /** - * Updates the list of installed apps and adds any new icons on homescreen or work folder. - */ - public void processPackageAdd(String[] packages) { - initVars(); - HashSet<String> packageSet = new HashSet<>(); - final boolean userAppsExisted = getUserApps(packageSet); - - boolean newPackageAdded = false; - long installTime = System.currentTimeMillis(); - LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext); - - for (String packageName : packages) { - if (!packageSet.contains(packageName)) { - packageSet.add(packageName); - newPackageAdded = true; - - List<LauncherActivityInfoCompat> activities = - launcherApps.getActivityList(packageName, mUser); - if (!activities.isEmpty()) { - markForAddition(activities.get(0), installTime); + @Override + public void run() { + for (ShortcutInfo info : workFolderApps) { + workFolder.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); } - } - } - if (newPackageAdded) { - mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply(); - finalizeAdditions(userAppsExisted); - } - } + // Add the item to home screen and DB. This also generates an item id synchronously. + ArrayList<ItemInfo> itemList = new ArrayList<ItemInfo>(1); + itemList.add(workFolder); + mModel.addAndBindAddedWorkspaceItems(mContext, itemList); + mPrefs.edit().putLong(folderIdKey, workFolder.id).apply(); - /** - * Updates the list of installed packages for the user. - */ - public void processPackageRemoved(String[] packages) { - HashSet<String> packageSet = new HashSet<String>(); - getUserApps(packageSet); - boolean packageRemoved = false; - - for (String packageName : packages) { - if (packageSet.remove(packageName)) { - packageRemoved = true; + saveWorkFolderShortcuts(workFolder.id, 0, workFolderApps); } } - - if (packageRemoved) { - mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply(); - } } /** - * Reads the list of user apps which have already been processed. - * @return false if the list didn't exist, true otherwise + * Add work folder shortcuts to the DB. */ - private boolean getUserApps(HashSet<String> outExistingApps) { - Set<String> userApps = mPrefs.getStringSet(mPackageSetKey, null); - if (userApps == null) { - return false; - } else { - outExistingApps.addAll(userApps); - return true; + private void saveWorkFolderShortcuts( + long workFolderId, int startingRank, ArrayList<ShortcutInfo> workFolderApps) { + for (ItemInfo info : workFolderApps) { + info.rank = startingRank++; + LauncherModel.addItemToDatabase(mContext, info, workFolderId, 0, 0, 0); } } + /** * Verifies that entries corresponding to {@param users} exist and removes all invalid entries. */ |