Automatically adding managed profile shortcuts to homescreen.
When the managed profile is created, a "Work" folder is created and added to the homescreen. All work profile apps are added to this folder and icons for subsequent installs (withing a fixed time frame) are automatically added to this folder. If this folder get deleted or the time-frame expires, icon for any new install is placed on the homescreen. Bug: 17410319 Change-Id: I49f4e437707d5eabe4eec85320765bf6ba7fde97
This commit is contained in:
@@ -38,6 +38,8 @@
|
|||||||
<string name="uid_name">Android Core Apps</string>
|
<string name="uid_name">Android Core Apps</string>
|
||||||
<!-- Default folder name -->
|
<!-- Default folder name -->
|
||||||
<string name="folder_name"></string>
|
<string name="folder_name"></string>
|
||||||
|
<!-- Work folder name -->
|
||||||
|
<string name="work_folder_name">Work</string>
|
||||||
<!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
|
<!-- Displayed when user selects a shortcut for an app that was uninstalled [CHAR_LIMIT=none]-->
|
||||||
<string name="activity_not_found">App isn\'t installed.</string>
|
<string name="activity_not_found">App isn\'t installed.</string>
|
||||||
<!-- Displayed when user selects a shortcut for an app that is current not available [CHAR_LIMIT=none]-->
|
<!-- Displayed when user selects a shortcut for an app that is current not available [CHAR_LIMIT=none]-->
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ public class FolderInfo extends ItemInfo {
|
|||||||
*/
|
*/
|
||||||
public static final int FLAG_ITEMS_SORTED = 0x00000001;
|
public static final int FLAG_ITEMS_SORTED = 0x00000001;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is a work folder
|
||||||
|
*/
|
||||||
|
public static final int FLAG_WORK_FOLDER = 0x00000002;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this folder has been opened
|
* Whether this folder has been opened
|
||||||
*/
|
*/
|
||||||
@@ -46,11 +51,11 @@ public class FolderInfo extends ItemInfo {
|
|||||||
/**
|
/**
|
||||||
* The apps and shortcuts
|
* The apps and shortcuts
|
||||||
*/
|
*/
|
||||||
ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
|
public ArrayList<ShortcutInfo> contents = new ArrayList<ShortcutInfo>();
|
||||||
|
|
||||||
ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
|
ArrayList<FolderListener> listeners = new ArrayList<FolderListener>();
|
||||||
|
|
||||||
FolderInfo() {
|
public FolderInfo() {
|
||||||
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
|
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
|
||||||
user = UserHandleCompat.myUserHandle();
|
user = UserHandleCompat.myUserHandle();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
|||||||
// Add the new apps to the model and bind them
|
// Add the new apps to the model and bind them
|
||||||
if (!addShortcuts.isEmpty()) {
|
if (!addShortcuts.isEmpty()) {
|
||||||
LauncherAppState app = LauncherAppState.getInstance();
|
LauncherAppState app = LauncherAppState.getInstance();
|
||||||
app.getModel().addAndBindAddedWorkspaceApps(context, addShortcuts);
|
app.getModel().addAndBindAddedWorkspaceItems(context, addShortcuts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -352,16 +352,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
|||||||
|
|
||||||
public ShortcutInfo getShortcutInfo() {
|
public ShortcutInfo getShortcutInfo() {
|
||||||
if (activityInfo != null) {
|
if (activityInfo != null) {
|
||||||
final ShortcutInfo info = new ShortcutInfo();
|
return ShortcutInfo.fromActivityInfo(activityInfo, mContext);
|
||||||
info.user = user;
|
|
||||||
info.title = label;
|
|
||||||
info.contentDescription = label;
|
|
||||||
info.customIcon = false;
|
|
||||||
info.intent = launchIntent;
|
|
||||||
info.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
|
||||||
info.flags = AppInfo.initFlags(activityInfo);
|
|
||||||
info.firstInstallTime = activityInfo.getFirstInstallTime();
|
|
||||||
return info;
|
|
||||||
} else {
|
} else {
|
||||||
return LauncherAppState.getInstance().getModel().infoFromShortcutIntent(mContext, data);
|
return LauncherAppState.getInstance().getModel().infoFromShortcutIntent(mContext, data);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate {
|
|||||||
mLauncher.showWorkspace(true, new Runnable() {
|
mLauncher.showWorkspace(true, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mLauncher.getModel().addAndBindAddedWorkspaceApps(
|
mLauncher.getModel().addAndBindAddedWorkspaceItems(
|
||||||
mLauncher, addShortcuts, screenProvider, 0, true);
|
mLauncher, addShortcuts, screenProvider, 0, true);
|
||||||
announceConfirmation(R.string.item_added_to_workspace);
|
announceConfirmation(R.string.item_added_to_workspace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
|
|||||||
return mIconCache;
|
return mIconCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
LauncherModel getModel() {
|
public LauncherModel getModel() {
|
||||||
return mModel;
|
return mModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class LauncherFiles {
|
|||||||
public static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
|
public static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
|
||||||
public static final String WALLPAPER_CROP_PREFERENCES_KEY =
|
public static final String WALLPAPER_CROP_PREFERENCES_KEY =
|
||||||
"com.android.launcher3.WallpaperCropActivity";
|
"com.android.launcher3.WallpaperCropActivity";
|
||||||
|
public static final String MANAGED_USER_PREFERENCES_KEY = "com.android.launcher3.managedusers.prefs";
|
||||||
|
|
||||||
public static final String WALLPAPER_IMAGES_DB = "saved_wallpaper_images.db";
|
public static final String WALLPAPER_IMAGES_DB = "saved_wallpaper_images.db";
|
||||||
public static final String WIDGET_PREVIEWS_DB = "widgetpreviews.db";
|
public static final String WIDGET_PREVIEWS_DB = "widgetpreviews.db";
|
||||||
@@ -35,6 +36,7 @@ public class LauncherFiles {
|
|||||||
WALLPAPER_CROP_PREFERENCES_KEY + XML,
|
WALLPAPER_CROP_PREFERENCES_KEY + XML,
|
||||||
WALLPAPER_IMAGES_DB,
|
WALLPAPER_IMAGES_DB,
|
||||||
WIDGET_PREVIEWS_DB,
|
WIDGET_PREVIEWS_DB,
|
||||||
|
MANAGED_USER_PREFERENCES_KEY,
|
||||||
APP_ICONS_DB));
|
APP_ICONS_DB));
|
||||||
|
|
||||||
// TODO: Delete these files on upgrade
|
// TODO: Delete these files on upgrade
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
|
|||||||
import com.android.launcher3.compat.UserHandleCompat;
|
import com.android.launcher3.compat.UserHandleCompat;
|
||||||
import com.android.launcher3.compat.UserManagerCompat;
|
import com.android.launcher3.compat.UserManagerCompat;
|
||||||
import com.android.launcher3.util.ComponentKey;
|
import com.android.launcher3.util.ComponentKey;
|
||||||
|
import com.android.launcher3.util.ManagedProfileHeuristic;
|
||||||
import com.android.launcher3.util.Thunk;
|
import com.android.launcher3.util.Thunk;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
@@ -87,7 +88,6 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
static final boolean DEBUG_LOADERS = false;
|
static final boolean DEBUG_LOADERS = false;
|
||||||
private static final boolean DEBUG_RECEIVER = false;
|
private static final boolean DEBUG_RECEIVER = false;
|
||||||
private static final boolean REMOVE_UNRESTORED_ICONS = true;
|
private static final boolean REMOVE_UNRESTORED_ICONS = true;
|
||||||
private static final boolean ADD_MANAGED_PROFILE_SHORTCUTS = false;
|
|
||||||
|
|
||||||
static final String TAG = "Launcher.Model";
|
static final String TAG = "Launcher.Model";
|
||||||
|
|
||||||
@@ -107,11 +107,6 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
@Thunk LoaderTask mLoaderTask;
|
@Thunk LoaderTask mLoaderTask;
|
||||||
@Thunk boolean mIsLoaderTaskRunning;
|
@Thunk boolean mIsLoaderTaskRunning;
|
||||||
|
|
||||||
/**
|
|
||||||
* Maintain a set of packages per user, for which we added a shortcut on the workspace.
|
|
||||||
*/
|
|
||||||
private static final String INSTALLED_SHORTCUTS_SET_PREFIX = "installed_shortcuts_set_for_user_";
|
|
||||||
|
|
||||||
// Specific runnable types that are run on the main thread deferred handler, this allows us to
|
// Specific runnable types that are run on the main thread deferred handler, this allows us to
|
||||||
// clear all queued binding runnables when the Launcher activity is destroyed.
|
// clear all queued binding runnables when the Launcher activity is destroyed.
|
||||||
private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;
|
private static final int MAIN_THREAD_NORMAL_RUNNABLE = 0;
|
||||||
@@ -338,9 +333,9 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
runOnWorkerThread(r);
|
runOnWorkerThread(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAndBindAddedWorkspaceApps(final Context context,
|
public void addAndBindAddedWorkspaceItems(final Context context,
|
||||||
final ArrayList<ItemInfo> workspaceApps) {
|
final ArrayList<ItemInfo> workspaceApps) {
|
||||||
addAndBindAddedWorkspaceApps(context, workspaceApps,
|
addAndBindAddedWorkspaceItems(context, workspaceApps,
|
||||||
new ScreenPosProvider() {
|
new ScreenPosProvider() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -518,7 +513,7 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
* @param fallbackStartScreen the screen to start search for empty space if
|
* @param fallbackStartScreen the screen to start search for empty space if
|
||||||
* preferredScreen is not available.
|
* preferredScreen is not available.
|
||||||
*/
|
*/
|
||||||
public void addAndBindAddedWorkspaceApps(final Context context,
|
public void addAndBindAddedWorkspaceItems(final Context context,
|
||||||
final ArrayList<ItemInfo> workspaceApps,
|
final ArrayList<ItemInfo> workspaceApps,
|
||||||
final ScreenPosProvider preferredScreen,
|
final ScreenPosProvider preferredScreen,
|
||||||
final int fallbackStartScreen,
|
final int fallbackStartScreen,
|
||||||
@@ -539,7 +534,7 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
|
ArrayList<Long> workspaceScreens = loadWorkspaceScreensDb(context);
|
||||||
synchronized(sBgLock) {
|
synchronized(sBgLock) {
|
||||||
for (ItemInfo item : workspaceApps) {
|
for (ItemInfo item : workspaceApps) {
|
||||||
if (!allowDuplicate) {
|
if (!allowDuplicate && item instanceof ShortcutInfo) {
|
||||||
// Short-circuit this logic if the icon exists somewhere on the workspace
|
// Short-circuit this logic if the icon exists somewhere on the workspace
|
||||||
if (shortcutExists(context, item.title.toString(),
|
if (shortcutExists(context, item.title.toString(),
|
||||||
item.getIntent(), item.user)) {
|
item.getIntent(), item.user)) {
|
||||||
@@ -554,21 +549,21 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
long screenId = coords.first;
|
long screenId = coords.first;
|
||||||
int[] cordinates = coords.second;
|
int[] cordinates = coords.second;
|
||||||
|
|
||||||
ShortcutInfo shortcutInfo;
|
ItemInfo itemInfo;
|
||||||
if (item instanceof ShortcutInfo) {
|
if (item instanceof ShortcutInfo || item instanceof FolderInfo) {
|
||||||
shortcutInfo = (ShortcutInfo) item;
|
itemInfo = item;
|
||||||
} else if (item instanceof AppInfo) {
|
} else if (item instanceof AppInfo) {
|
||||||
shortcutInfo = ((AppInfo) item).makeShortcut();
|
itemInfo = ((AppInfo) item).makeShortcut();
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unexpected info type");
|
throw new RuntimeException("Unexpected info type");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the shortcut to the db
|
// Add the shortcut to the db
|
||||||
addItemToDatabase(context, shortcutInfo,
|
addItemToDatabase(context, itemInfo,
|
||||||
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
LauncherSettings.Favorites.CONTAINER_DESKTOP,
|
||||||
screenId, cordinates[0], cordinates[1]);
|
screenId, cordinates[0], cordinates[1]);
|
||||||
// Save the ShortcutInfo for binding in the workspace
|
// Save the ShortcutInfo for binding in the workspace
|
||||||
addedShortcutsFinal.add(shortcutInfo);
|
addedShortcutsFinal.add(itemInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -993,7 +988,7 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
* Add an item to the database in a specified container. Sets the container, screen, cellX and
|
* Add an item to the database in a specified container. Sets the container, screen, cellX and
|
||||||
* cellY fields of the item. Also assigns an ID to the item.
|
* cellY fields of the item. Also assigns an ID to the item.
|
||||||
*/
|
*/
|
||||||
static void addItemToDatabase(Context context, final ItemInfo item, final long container,
|
public static void addItemToDatabase(Context context, final ItemInfo item, final long container,
|
||||||
final long screenId, final int cellX, final int cellY) {
|
final long screenId, final int cellX, final int cellY) {
|
||||||
item.container = container;
|
item.container = container;
|
||||||
item.cellX = cellX;
|
item.cellX = cellX;
|
||||||
@@ -1097,7 +1092,6 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
*/
|
*/
|
||||||
static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
|
static void deleteItemsFromDatabase(Context context, final ArrayList<? extends ItemInfo> items) {
|
||||||
final ContentResolver cr = context.getContentResolver();
|
final ContentResolver cr = context.getContentResolver();
|
||||||
|
|
||||||
Runnable r = new Runnable() {
|
Runnable r = new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
for (ItemInfo item : items) {
|
for (ItemInfo item : items) {
|
||||||
@@ -2845,23 +2839,11 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
|
mBgAllAppsList.add(new AppInfo(mContext, app, user, mIconCache));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ADD_MANAGED_PROFILE_SHORTCUTS && !user.equals(UserHandleCompat.myUserHandle())) {
|
if (!user.equals(UserHandleCompat.myUserHandle())) {
|
||||||
// Add shortcuts for packages which were installed while launcher was dead.
|
ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(mContext, user);
|
||||||
String shortcutsSetKey = INSTALLED_SHORTCUTS_SET_PREFIX
|
if (heuristic != null) {
|
||||||
+ mUserManager.getSerialNumberForUser(user);
|
heuristic.processUserApps(apps);
|
||||||
Set<String> packagesAdded = prefs.getStringSet(shortcutsSetKey, Collections.EMPTY_SET);
|
|
||||||
HashSet<String> newPackageSet = new HashSet<String>();
|
|
||||||
|
|
||||||
for (LauncherActivityInfoCompat info : apps) {
|
|
||||||
String packageName = info.getComponentName().getPackageName();
|
|
||||||
if (!packagesAdded.contains(packageName)
|
|
||||||
&& !newPackageSet.contains(packageName)) {
|
|
||||||
InstallShortcutReceiver.queueInstallShortcut(info, mContext);
|
|
||||||
}
|
|
||||||
newPackageSet.add(packageName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prefs.edit().putStringSet(shortcutsSetKey, newPackageSet).commit();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Huh? Shouldn't this be inside the Runnable below?
|
// Huh? Shouldn't this be inside the Runnable below?
|
||||||
@@ -2884,6 +2866,8 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
// Cleanup any data stored for a deleted user.
|
||||||
|
ManagedProfileHeuristic.processAllUsers(profiles, mContext);
|
||||||
|
|
||||||
if (DEBUG_LOADERS) {
|
if (DEBUG_LOADERS) {
|
||||||
Log.d(TAG, "Icons processed in "
|
Log.d(TAG, "Icons processed in "
|
||||||
@@ -2971,38 +2955,19 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
final String[] packages = mPackages;
|
final String[] packages = mPackages;
|
||||||
final int N = packages.length;
|
final int N = packages.length;
|
||||||
switch (mOp) {
|
switch (mOp) {
|
||||||
case OP_ADD:
|
case OP_ADD: {
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
|
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.addPackage " + packages[i]);
|
||||||
mIconCache.updateIconsForPkg(packages[i], mUser);
|
mIconCache.updateIconsForPkg(packages[i], mUser);
|
||||||
mBgAllAppsList.addPackage(context, packages[i], mUser);
|
mBgAllAppsList.addPackage(context, packages[i], mUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto add shortcuts for added packages.
|
ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
|
||||||
if (ADD_MANAGED_PROFILE_SHORTCUTS
|
if (heuristic != null) {
|
||||||
&& !UserHandleCompat.myUserHandle().equals(mUser)) {
|
heuristic.processPackageAdd(mPackages);
|
||||||
SharedPreferences prefs = context.getSharedPreferences(
|
|
||||||
LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
|
|
||||||
String shortcutsSetKey = INSTALLED_SHORTCUTS_SET_PREFIX
|
|
||||||
+ mUserManager.getSerialNumberForUser(mUser);
|
|
||||||
Set<String> shortcutSet = new HashSet<String>(
|
|
||||||
prefs.getStringSet(shortcutsSetKey,Collections.EMPTY_SET));
|
|
||||||
|
|
||||||
for (int i=0; i<N; i++) {
|
|
||||||
if (!shortcutSet.contains(packages[i])) {
|
|
||||||
shortcutSet.add(packages[i]);
|
|
||||||
List<LauncherActivityInfoCompat> activities =
|
|
||||||
mLauncherApps.getActivityList(packages[i], mUser);
|
|
||||||
if (activities != null && !activities.isEmpty()) {
|
|
||||||
InstallShortcutReceiver.queueInstallShortcut(
|
|
||||||
activities.get(0), context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prefs.edit().putStringSet(shortcutsSetKey, shortcutSet).commit();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case OP_UPDATE:
|
case OP_UPDATE:
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
|
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.updatePackage " + packages[i]);
|
||||||
@@ -3011,25 +2976,17 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
mApp.getWidgetCache().removePackage(packages[i], mUser);
|
mApp.getWidgetCache().removePackage(packages[i], mUser);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OP_REMOVE:
|
case OP_REMOVE: {
|
||||||
// Remove the packageName for the set of auto-installed shortcuts. This
|
ManagedProfileHeuristic heuristic = ManagedProfileHeuristic.get(context, mUser);
|
||||||
// will ensure that the shortcut when the app is installed again.
|
if (heuristic != null) {
|
||||||
if (ADD_MANAGED_PROFILE_SHORTCUTS
|
heuristic.processPackageRemoved(mPackages);
|
||||||
&& !UserHandleCompat.myUserHandle().equals(mUser)) {
|
|
||||||
SharedPreferences prefs = context.getSharedPreferences(
|
|
||||||
LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
|
|
||||||
String shortcutsSetKey = INSTALLED_SHORTCUTS_SET_PREFIX
|
|
||||||
+ mUserManager.getSerialNumberForUser(mUser);
|
|
||||||
HashSet<String> shortcutSet = new HashSet<String>(
|
|
||||||
prefs.getStringSet(shortcutsSetKey, Collections.EMPTY_SET));
|
|
||||||
shortcutSet.removeAll(Arrays.asList(mPackages));
|
|
||||||
prefs.edit().putStringSet(shortcutsSetKey, shortcutSet).commit();
|
|
||||||
}
|
}
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
|
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
|
||||||
mIconCache.removeIconsForPkg(packages[i], mUser);
|
mIconCache.removeIconsForPkg(packages[i], mUser);
|
||||||
}
|
}
|
||||||
// Fall through
|
// Fall through
|
||||||
|
}
|
||||||
case OP_UNAVAILABLE:
|
case OP_UNAVAILABLE:
|
||||||
for (int i=0; i<N; i++) {
|
for (int i=0; i<N; i++) {
|
||||||
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
|
if (DEBUG_LOADERS) Log.d(TAG, "mAllAppsList.removePackage " + packages[i]);
|
||||||
@@ -3677,4 +3634,13 @@ public class LauncherModel extends BroadcastReceiver
|
|||||||
public Callbacks getCallback() {
|
public Callbacks getCallback() {
|
||||||
return mCallbacks != null ? mCallbacks.get() : null;
|
return mCallbacks != null ? mCallbacks.get() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@link FolderInfo} if its already loaded.
|
||||||
|
*/
|
||||||
|
public FolderInfo findFolderById(Long folderId) {
|
||||||
|
synchronized (sBgLock) {
|
||||||
|
return sBgFolders.get(folderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,9 @@ import android.graphics.Bitmap;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.launcher3.LauncherSettings.Favorites;
|
import com.android.launcher3.LauncherSettings.Favorites;
|
||||||
|
import com.android.launcher3.compat.LauncherActivityInfoCompat;
|
||||||
import com.android.launcher3.compat.UserHandleCompat;
|
import com.android.launcher3.compat.UserHandleCompat;
|
||||||
|
import com.android.launcher3.compat.UserManagerCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -274,5 +276,19 @@ public class ShortcutInfo extends ItemInfo {
|
|||||||
public boolean shouldUseLowResIcon() {
|
public boolean shouldUseLowResIcon() {
|
||||||
return usingLowResIcon && container >= 0 && rank >= FolderIcon.NUM_ITEMS_IN_PREVIEW;
|
return usingLowResIcon && container >= 0 && rank >= FolderIcon.NUM_ITEMS_IN_PREVIEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ShortcutInfo fromActivityInfo(LauncherActivityInfoCompat info, Context context) {
|
||||||
|
final ShortcutInfo shortcut = new ShortcutInfo();
|
||||||
|
shortcut.user = info.getUser();
|
||||||
|
shortcut.title = info.getLabel().toString();
|
||||||
|
shortcut.contentDescription = UserManagerCompat.getInstance(context)
|
||||||
|
.getBadgedLabelForUser(info.getLabel(), info.getUser());
|
||||||
|
shortcut.customIcon = false;
|
||||||
|
shortcut.intent = AppInfo.makeLaunchIntent(context, info, info.getUser());
|
||||||
|
shortcut.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||||
|
shortcut.flags = AppInfo.initFlags(info);
|
||||||
|
shortcut.firstInstallTime = info.getFirstInstallTime();
|
||||||
|
return shortcut;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,4 +43,5 @@ public abstract class UserManagerCompat {
|
|||||||
public abstract UserHandleCompat getUserForSerialNumber(long serialNumber);
|
public abstract UserHandleCompat getUserForSerialNumber(long serialNumber);
|
||||||
public abstract Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user);
|
public abstract Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user);
|
||||||
public abstract CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user);
|
public abstract CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user);
|
||||||
|
public abstract long getUserCreationTime(UserHandleCompat user);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,4 +48,9 @@ public class UserManagerCompatV16 extends UserManagerCompat {
|
|||||||
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user) {
|
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandleCompat user) {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getUserCreationTime(UserHandleCompat user) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,21 +18,27 @@
|
|||||||
package com.android.launcher3.compat;
|
package com.android.launcher3.compat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.UserManager;
|
|
||||||
|
import com.android.launcher3.LauncherAppState;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class UserManagerCompatVL extends UserManagerCompatV17 {
|
public class UserManagerCompatVL extends UserManagerCompatV17 {
|
||||||
|
private static final String USER_CREATION_TIME_KEY = "user_creation_time_";
|
||||||
|
|
||||||
private final PackageManager mPm;
|
private final PackageManager mPm;
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
UserManagerCompatVL(Context context) {
|
UserManagerCompatVL(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
mPm = context.getPackageManager();
|
mPm = context.getPackageManager();
|
||||||
|
mContext = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -61,5 +67,17 @@ public class UserManagerCompatVL extends UserManagerCompatV17 {
|
|||||||
}
|
}
|
||||||
return mPm.getUserBadgedLabel(label, user.getUser());
|
return mPm.getUserBadgedLabel(label, user.getUser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getUserCreationTime(UserHandleCompat user) {
|
||||||
|
// TODO: Use system API once available.
|
||||||
|
SharedPreferences prefs = mContext.getSharedPreferences(
|
||||||
|
LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
|
||||||
|
String key = USER_CREATION_TIME_KEY + getSerialNumberForUser(user);
|
||||||
|
if (!prefs.contains(key)) {
|
||||||
|
prefs.edit().putLong(key, System.currentTimeMillis()).apply();
|
||||||
|
}
|
||||||
|
return prefs.getLong(key, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,277 @@
|
|||||||
|
package com.android.launcher3.util;
|
||||||
|
|
||||||
|
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.util.Log;
|
||||||
|
|
||||||
|
import com.android.launcher3.FolderInfo;
|
||||||
|
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.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.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles addition of app shortcuts for managed profiles.
|
||||||
|
* Methods of class should only be called on {@link LauncherModel#sWorkerThread}.
|
||||||
|
*/
|
||||||
|
public class ManagedProfileHeuristic {
|
||||||
|
|
||||||
|
private static final String TAG = "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_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Duration (in milliseconds) for which app shortcuts will be added to work folder.
|
||||||
|
*/
|
||||||
|
private static final long AUTO_ADD_TO_FOLDER_DURATION = 8 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
public static ManagedProfileHeuristic get(Context context, UserHandleCompat user) {
|
||||||
|
if (Utilities.isLmpOrAbove() && !UserHandleCompat.myUserHandle().equals(user)) {
|
||||||
|
return new ManagedProfileHeuristic(context, user);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
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<ItemInfo> mHomescreenApps;
|
||||||
|
private ArrayList<ItemInfo> mWorkFolderApps;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the list of user apps and adds icons for newly installed apps on the homescreen or
|
||||||
|
* workfolder.
|
||||||
|
*/
|
||||||
|
public void processUserApps(List<LauncherActivityInfoCompat> apps) {
|
||||||
|
mHomescreenApps = new ArrayList<ItemInfo>();
|
||||||
|
mWorkFolderApps = new ArrayList<ItemInfo>();
|
||||||
|
HashSet<String> packageSet = getPackageSet();
|
||||||
|
boolean newPackageAdded = false;
|
||||||
|
|
||||||
|
for (LauncherActivityInfoCompat info : apps) {
|
||||||
|
String packageName = info.getComponentName().getPackageName();
|
||||||
|
if (!packageSet.contains(packageName)) {
|
||||||
|
packageSet.add(packageName);
|
||||||
|
newPackageAdded = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
PackageInfo pkgInfo = mContext.getPackageManager()
|
||||||
|
.getPackageInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
|
||||||
|
markForAddition(info, pkgInfo.firstInstallTime);
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
Log.e(TAG, "Unknown package " + packageName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPackageAdded) {
|
||||||
|
mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply();
|
||||||
|
finalizeAdditions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markForAddition(LauncherActivityInfoCompat info, long installTime) {
|
||||||
|
ArrayList<ItemInfo> targetList =
|
||||||
|
(installTime <= mUserCreationTime + AUTO_ADD_TO_FOLDER_DURATION) ?
|
||||||
|
mWorkFolderApps : mHomescreenApps;
|
||||||
|
targetList.add(ShortcutInfo.fromActivityInfo(info, mContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds and binds shortcuts marked to be added to the work folder.
|
||||||
|
*/
|
||||||
|
private void finalizeWorkFolder() {
|
||||||
|
if (mWorkFolderApps.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
final ArrayList<ItemInfo> shortcuts = mWorkFolderApps;
|
||||||
|
// FolderInfo could already be bound. We need to add shortcuts on the UI thread.
|
||||||
|
new MainThreadExecutor().execute(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (ItemInfo info : shortcuts) {
|
||||||
|
workFolder.add((ShortcutInfo) info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} 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 (ItemInfo info : mWorkFolderApps) {
|
||||||
|
workFolder.add((ShortcutInfo) info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
saveWorkFolderShortcuts(workFolder.id, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds and binds all shortcuts marked for addition.
|
||||||
|
*/
|
||||||
|
private void finalizeAdditions() {
|
||||||
|
finalizeWorkFolder();
|
||||||
|
|
||||||
|
if (!mHomescreenApps.isEmpty()) {
|
||||||
|
mModel.addAndBindAddedWorkspaceItems(mContext, mHomescreenApps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the list of installed apps and adds any new icons on homescreen or work folder.
|
||||||
|
*/
|
||||||
|
public void processPackageAdd(String[] packages) {
|
||||||
|
mHomescreenApps = new ArrayList<ItemInfo>();
|
||||||
|
mWorkFolderApps = new ArrayList<ItemInfo>();
|
||||||
|
HashSet<String> packageSet = getPackageSet();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPackageAdded) {
|
||||||
|
mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply();
|
||||||
|
finalizeAdditions();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the list of installed packages for the user.
|
||||||
|
*/
|
||||||
|
public void processPackageRemoved(String[] packages) {
|
||||||
|
HashSet<String> packageSet = getPackageSet();
|
||||||
|
boolean packageRemoved = false;
|
||||||
|
|
||||||
|
for (String packageName : packages) {
|
||||||
|
if (packageSet.remove(packageName)) {
|
||||||
|
packageRemoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packageRemoved) {
|
||||||
|
mPrefs.edit().putStringSet(mPackageSetKey, packageSet).apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private HashSet<String> getPackageSet() {
|
||||||
|
return new HashSet<String>(mPrefs.getStringSet(mPackageSetKey, Collections.EMPTY_SET));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that entries corresponding to {@param users} exist and removes all invalid entries.
|
||||||
|
*/
|
||||||
|
public static void processAllUsers(List<UserHandleCompat> users, Context context) {
|
||||||
|
if (!Utilities.isLmpOrAbove()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UserManagerCompat userManager = UserManagerCompat.getInstance(context);
|
||||||
|
HashSet<String> validKeys = new HashSet<String>();
|
||||||
|
for (UserHandleCompat user : users) {
|
||||||
|
addAllUserKeys(userManager.getSerialNumberForUser(user), validKeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedPreferences prefs = context.getSharedPreferences(
|
||||||
|
LauncherFiles.MANAGED_USER_PREFERENCES_KEY,
|
||||||
|
Context.MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = prefs.edit();
|
||||||
|
for (String key : prefs.getAll().keySet()) {
|
||||||
|
if (!validKeys.contains(key)) {
|
||||||
|
editor.remove(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addAllUserKeys(long userSerial, HashSet<String> keysOut) {
|
||||||
|
keysOut.add(INSTALLED_PACKAGES_PREFIX + userSerial);
|
||||||
|
keysOut.add(USER_FOLDER_ID_PREFIX + userSerial);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user