From 95f3d6ba2ca02a9841487777cfff43fb9df65ec7 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Wed, 10 Aug 2016 16:09:29 -0700 Subject: [PATCH] Reloading workspace when the shortcuts permission changes > Check for permission on every onResume > If the permission is different than last known permission, reload and rebind workspace. Bug: 30789422 Change-Id: Idfa445815e29e2336505779545507d106b33a253 --- src/com/android/launcher3/Launcher.java | 3 ++ src/com/android/launcher3/LauncherModel.java | 41 ++++++++++++++++--- .../shortcuts/DeepShortcutManager.java | 12 ++++++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index adf07a1ca7..886c5f0a26 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1090,6 +1090,9 @@ public class Launcher extends Activity if (!isWorkspaceLoading()) { // Process any items that were added while Launcher was away. InstallShortcutReceiver.disableAndFlushInstallQueue(this); + + // Refresh shortcuts if the permission changed. + mModel.refreshShortcutsIfRequired(); } if (shouldShowDiscoveryBounce()) { diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 34660ac151..6a63110b11 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -146,6 +146,20 @@ public class LauncherModel extends BroadcastReceiver // Maps all launcher activities to the id's of their shortcuts (if they have any). private final MultiHashMap mBgDeepShortcutMap = new MultiHashMap<>(); + private boolean mHasShortcutHostPermission; + // Runnable to check if the shortcuts permission has changed. + private final Runnable mShortcutPermissionCheckRunnable = new Runnable() { + @Override + public void run() { + if (mDeepShortcutsLoaded) { + boolean hasShortcutHostPermission = mDeepShortcutManager.hasHostPermission(); + if (hasShortcutHostPermission != mHasShortcutHostPermission) { + mApp.reloadWorkspace(); + } + } + } + }; + // The lock that must be acquired before referencing any static bg data structures. Unlike // other locks, this one can generally be held long-term because we never expect any of these // static data structures to be referenced outside of the worker thread except on the first @@ -1244,6 +1258,7 @@ public class LauncherModel extends BroadcastReceiver if (resetAllAppsLoaded) mAllAppsLoaded = false; if (resetWorkspaceLoaded) mWorkspaceLoaded = false; // Always reset deep shortcuts loaded. + // TODO: why? mDeepShortcutsLoaded = false; } } @@ -1299,6 +1314,7 @@ public class LauncherModel extends BroadcastReceiver // If there is already one running, tell it to stop. stopLoaderLocked(); mLoaderTask = new LoaderTask(mApp.getContext(), synchronousBindPage); + // TODO: mDeepShortcutsLoaded does not need to be true for synchronous bind. if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE && mAllAppsLoaded && mWorkspaceLoaded && mDeepShortcutsLoaded && !mIsLoaderTaskRunning) { mLoaderTask.runBindSynchronousPage(synchronousBindPage); @@ -2793,11 +2809,14 @@ public class LauncherModel extends BroadcastReceiver } if (!mDeepShortcutsLoaded) { mBgDeepShortcutMap.clear(); - for (UserHandleCompat user : mUserManager.getUserProfiles()) { - if (mUserManager.isUserUnlocked(user)) { - List shortcuts = mDeepShortcutManager - .queryForAllShortcuts(user); - updateDeepShortcutMap(null, user, shortcuts); + mHasShortcutHostPermission = mDeepShortcutManager.hasHostPermission(); + if (mHasShortcutHostPermission) { + for (UserHandleCompat user : mUserManager.getUserProfiles()) { + if (mUserManager.isUserUnlocked(user)) { + List shortcuts = mDeepShortcutManager + .queryForAllShortcuts(user); + updateDeepShortcutMap(null, user, shortcuts); + } } } synchronized (LoaderTask.this) { @@ -2862,6 +2881,18 @@ public class LauncherModel extends BroadcastReceiver runOnMainThread(r); } + /** + * Refreshes the cached shortcuts if the shortcut permission has changed. + * Current implementation simply reloads the workspace, but it can be optimized to + * use partial updates similar to {@link UserManagerCompat} + */ + public void refreshShortcutsIfRequired() { + if (Utilities.isNycMR1OrAbove()) { + sWorker.removeCallbacks(mShortcutPermissionCheckRunnable); + sWorker.post(mShortcutPermissionCheckRunnable); + } + } + /** * Called when the icons for packages have been updated in the icon cache. */ diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java index 05ab843616..49d6fa932f 100644 --- a/src/com/android/launcher3/shortcuts/DeepShortcutManager.java +++ b/src/com/android/launcher3/shortcuts/DeepShortcutManager.java @@ -224,4 +224,16 @@ public class DeepShortcutManager { return Collections.EMPTY_LIST; } } + + @TargetApi(25) + public boolean hasHostPermission() { + if (Utilities.isNycMR1OrAbove()) { + try { + return mLauncherApps.hasShortcutHostPermission(); + } catch (SecurityException|IllegalStateException e) { + Log.e(TAG, "Failed to make shortcut manager call", e); + } + } + return false; + } }