diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2016-05-27 00:44:56 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2016-05-27 00:44:57 +0000 |
commit | 3c4b03dd01b89a4d4beba6a866ae3bb9093e101e (patch) | |
tree | 34ea43c08ac6d67fa7a2c508a64588cda7466d57 | |
parent | 5c93eac3ae163a5a3d866db24d9b853caa9b9f88 (diff) | |
parent | d478c83fd6abebe6ce3f066d392a28f8ba9be100 (diff) | |
download | android_packages_apps_Trebuchet-3c4b03dd01b89a4d4beba6a866ae3bb9093e101e.tar.gz android_packages_apps_Trebuchet-3c4b03dd01b89a4d4beba6a866ae3bb9093e101e.tar.bz2 android_packages_apps_Trebuchet-3c4b03dd01b89a4d4beba6a866ae3bb9093e101e.zip |
Merge "Showing a permission dialog when a restored widget is not yet bound, and launcher does not has the permission to bind the widget" into ub-launcher3-calgary
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 131 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherAppWidgetInfo.java | 11 | ||||
-rw-r--r-- | src/com/android/launcher3/PendingAppWidgetHostView.java | 14 |
3 files changed, 103 insertions, 53 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index ec09cf149..13e451a27 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -158,6 +158,7 @@ public class Launcher extends Activity private static final int REQUEST_PICK_WALLPAPER = 10; private static final int REQUEST_BIND_APPWIDGET = 11; + private static final int REQUEST_BIND_PENDING_APPWIDGET = 14; private static final int REQUEST_RECONFIGURE_APPWIDGET = 12; private static final int REQUEST_PERMISSION_CALL_PHONE = 13; @@ -688,8 +689,22 @@ public class Launcher extends Activity completeAddAppWidget(args.appWidgetId, args.container, screenId, null, null); break; case REQUEST_RECONFIGURE_APPWIDGET: - completeRestoreAppWidget(args.appWidgetId); + completeRestoreAppWidget(args.appWidgetId, LauncherAppWidgetInfo.RESTORE_COMPLETED); break; + case REQUEST_BIND_PENDING_APPWIDGET: { + int widgetId = args.appWidgetId; + LauncherAppWidgetInfo info = + completeRestoreAppWidget(widgetId, LauncherAppWidgetInfo.FLAG_UI_NOT_READY); + if (info != null) { + // Since the view was just bound, also launch the configure activity if needed + LauncherAppWidgetProviderInfo provider = mAppWidgetManager + .getLauncherAppWidgetInfo(widgetId); + if (provider != null && provider.configure != null) { + startRestoredWidgetReconfigActivity(provider, info); + } + } + break; + } } // Before adding this resetAddInfo(), after a shortcut was added to a workspace screen, // if you turned the screen off and then back while in All Apps, Launcher would not @@ -804,7 +819,8 @@ public class Launcher extends Activity return; } - if (requestCode == REQUEST_RECONFIGURE_APPWIDGET) { + if (requestCode == REQUEST_RECONFIGURE_APPWIDGET + || requestCode == REQUEST_BIND_PENDING_APPWIDGET) { if (resultCode == RESULT_OK) { // Update the widget view. PendingAddArguments args = preparePendingAddArgs(requestCode, data, @@ -2380,7 +2396,7 @@ public class Launcher extends Activity */ private void deleteWidgetInfo(final LauncherAppWidgetInfo widgetInfo) { final LauncherAppWidgetHost appWidgetHost = getAppWidgetHost(); - if (appWidgetHost != null && !widgetInfo.isCustomWidget() && widgetInfo.isWidgetIdValid()) { + if (appWidgetHost != null && !widgetInfo.isCustomWidget() && widgetInfo.isWidgetIdAllocated()) { // Deleting an app widget ID is a void call but writes to disk before returning // to the caller... new AsyncTask<Void, Void, Void>() { @@ -2526,16 +2542,31 @@ public class Launcher extends Activity final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag(); if (v.isReadyForClickSetup()) { - int widgetId = info.appWidgetId; - LauncherAppWidgetProviderInfo appWidgetInfo = - mAppWidgetManager.getLauncherAppWidgetInfo(widgetId); - if (appWidgetInfo != null) { - mPendingAddWidgetInfo = appWidgetInfo; - mPendingAddInfo.copyFrom(info); - mPendingAddWidgetId = widgetId; - - AppWidgetManagerCompat.getInstance(this).startConfigActivity(appWidgetInfo, - info.appWidgetId, this, mAppWidgetHost, REQUEST_RECONFIGURE_APPWIDGET); + if (info.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) { + if (!info.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) { + // This should not happen, as we make sure that an Id is allocated during bind. + return; + } + LauncherAppWidgetProviderInfo appWidgetInfo = + mAppWidgetManager.findProvider(info.providerName, info.user); + if (appWidgetInfo != null) { + mPendingAddWidgetId = info.appWidgetId; + mPendingAddInfo.copyFrom(info); + mPendingAddWidgetInfo = appWidgetInfo; + + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mPendingAddWidgetId); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, appWidgetInfo.provider); + mAppWidgetManager.getUser(mPendingAddWidgetInfo) + .addToIntent(intent, AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE); + startActivityForResult(intent, REQUEST_BIND_PENDING_APPWIDGET); + } + } else { + LauncherAppWidgetProviderInfo appWidgetInfo = + mAppWidgetManager.getLauncherAppWidgetInfo(info.appWidgetId); + if (appWidgetInfo != null) { + startRestoredWidgetReconfigActivity(appWidgetInfo, info); + } } } else if (info.installProgress < 0) { // The install has not been queued @@ -2553,6 +2584,15 @@ public class Launcher extends Activity } } + private void startRestoredWidgetReconfigActivity( + LauncherAppWidgetProviderInfo provider, LauncherAppWidgetInfo info) { + mPendingAddWidgetInfo = provider; + mPendingAddInfo.copyFrom(info); + mPendingAddWidgetId = info.appWidgetId; + mAppWidgetManager.startConfigActivity(provider, + info.appWidgetId, this, mAppWidgetHost, REQUEST_RECONFIGURE_APPWIDGET); + } + /** * Event handler for the "grid" button that appears on the home screen, which * enters all apps mode. @@ -3919,41 +3959,33 @@ public class Launcher extends Activity // If we do not have a valid id, try to bind an id. if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) { - // Note: This assumes that the id remap broadcast is received before this step. - // If that is not the case, the id remap will be ignored and user may see the - // click to setup view. - PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(this, appWidgetInfo); - pendingInfo.spanX = item.spanX; - pendingInfo.spanY = item.spanY; - pendingInfo.minSpanX = item.minSpanX; - pendingInfo.minSpanY = item.minSpanY; - Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo); - - int newWidgetId = mAppWidgetHost.allocateAppWidgetId(); - boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( - newWidgetId, appWidgetInfo, options); - - // TODO consider showing a permission dialog when the widget is clicked. - if (!success) { - mAppWidgetHost.deleteAppWidgetId(newWidgetId); - if (DEBUG_WIDGETS) { - Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId - + " belongs to component " + item.providerName - + ", as the launcher is unable to bing a new widget id"); + if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) { + // Id has not been allocated yet. Allocate a new id. + item.appWidgetId = mAppWidgetHost.allocateAppWidgetId(); + item.restoreStatus |= LauncherAppWidgetInfo.FLAG_ID_ALLOCATED; + + // Also try to bind the widget. If the bind fails, the user will be shown + // a click to setup UI, which will ask for the bind permission. + PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(this, appWidgetInfo); + pendingInfo.spanX = item.spanX; + pendingInfo.spanY = item.spanY; + pendingInfo.minSpanX = item.minSpanX; + pendingInfo.minSpanY = item.minSpanY; + Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo); + boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( + item.appWidgetId, appWidgetInfo, options); + + // Bind succeeded + if (success) { + // If the widget has a configure activity, it is still needs to set it up, + // otherwise the widget is ready to go. + item.restoreStatus = (appWidgetInfo.configure == null) + ? LauncherAppWidgetInfo.RESTORE_COMPLETED + : LauncherAppWidgetInfo.FLAG_UI_NOT_READY; } - LauncherModel.deleteItemFromDatabase(this, item); - return; - } - - item.appWidgetId = newWidgetId; - - // If the widget has a configure activity, it is still needs to set it up, otherwise - // the widget is ready to go. - item.restoreStatus = (appWidgetInfo.configure == null) - ? LauncherAppWidgetInfo.RESTORE_COMPLETED - : LauncherAppWidgetInfo.FLAG_UI_NOT_READY; - LauncherModel.updateItemInDatabase(this, item); + LauncherModel.updateItemInDatabase(this, item); + } } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) && (appWidgetInfo.configure == null)) { // The widget was marked as UI not ready, but there is no configure activity to @@ -4001,18 +4033,19 @@ public class Launcher extends Activity * * @param appWidgetId The app widget id */ - private void completeRestoreAppWidget(final int appWidgetId) { + private LauncherAppWidgetInfo completeRestoreAppWidget(int appWidgetId, int finalRestoreFlag) { LauncherAppWidgetHostView view = mWorkspace.getWidgetForAppWidgetId(appWidgetId); if ((view == null) || !(view instanceof PendingAppWidgetHostView)) { Log.e(TAG, "Widget update called, when the widget no longer exists."); - return; + return null; } LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag(); - info.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED; + info.restoreStatus = finalRestoreFlag; mWorkspace.reinflateWidgetsIfNecessary(); LauncherModel.updateItemInDatabase(this, info); + return info; } public void onPageBoundSynchronously(int page) { diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java index 42d646820..4c8fedf5e 100644 --- a/src/com/android/launcher3/LauncherAppWidgetInfo.java +++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java @@ -51,6 +51,12 @@ public class LauncherAppWidgetInfo extends ItemInfo { public static final int FLAG_RESTORE_STARTED = 8; /** + * Indicates that the widget has been allocated an Id. The id is still not valid, as it has + * not been bound yet. + */ + public static final int FLAG_ID_ALLOCATED = 16; + + /** * Indicates that the widget hasn't been instantiated yet. */ static final int NO_ID = -1; @@ -127,8 +133,9 @@ public class LauncherAppWidgetInfo extends ItemInfo { return "AppWidget(id=" + Integer.toString(appWidgetId) + ")"; } - public final boolean isWidgetIdValid() { - return (restoreStatus & FLAG_ID_NOT_VALID) == 0; + public final boolean isWidgetIdAllocated() { + return (restoreStatus & FLAG_ID_NOT_VALID) == 0 || + (restoreStatus & FLAG_ID_ALLOCATED) == FLAG_ID_ALLOCATED; } public final boolean hasRestoreFlag(int flag) { diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java index 1c0290417..a455026fa 100644 --- a/src/com/android/launcher3/PendingAppWidgetHostView.java +++ b/src/com/android/launcher3/PendingAppWidgetHostView.java @@ -189,9 +189,19 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implemen } } + /** + * A pending widget is ready for setup after the provider is installed and + * 1) Widget id is not valid: the widget id is not yet bound to the provider, probably + * because the launcher doesn't have appropriate permissions. + * Note that we would still have an allocated id as that does not + * require any permissions and can be done during view inflation. + * 2) UI is not ready: the id is valid and the bound. But the widget has a configure activity + * which needs to be called once. + */ public boolean isReadyForClickSetup() { - return (mInfo.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0 - && (mInfo.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0; + return !mInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) + && (mInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) + || mInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)); } private void updateDrawableBounds() { |