diff options
| -rw-r--r-- | core/java/android/appwidget/AppWidgetManager.java | 22 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViews.java | 55 |
2 files changed, 73 insertions, 4 deletions
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index eb672dcc42fd..b159321af837 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -48,9 +48,11 @@ import android.widget.RemoteViews; import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.os.BackgroundThread; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; /** * Updates AppWidget state; gets information about installed AppWidget providers and other @@ -785,7 +787,25 @@ public class AppWidgetManager { return; } try { - mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); + if (RemoteViews.isAdapterConversionEnabled()) { + List<CompletableFuture<Void>> updateFutures = new ArrayList<>(); + for (int i = 0; i < appWidgetIds.length; i++) { + final int widgetId = appWidgetIds[i]; + updateFutures.add(CompletableFuture.runAsync(() -> { + try { + RemoteViews views = mService.getAppWidgetViews(mPackageName, widgetId); + if (views.replaceRemoteCollections(viewId)) { + updateAppWidget(widgetId, views); + } + } catch (Exception e) { + Log.e(TAG, "Error notifying changes in RemoteViews", e); + } + })); + } + CompletableFuture.allOf(updateFutures.toArray(CompletableFuture[]::new)).join(); + } else { + mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index d9e76fefad7f..a2f95fa9df45 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -786,6 +786,42 @@ public class RemoteViews implements Parcelable, Filter { } } + /** + * @hide + * @return True if there is a change + */ + public boolean replaceRemoteCollections(int viewId) { + boolean isActionReplaced = false; + if (mActions != null) { + for (int i = 0; i < mActions.size(); i++) { + Action action = mActions.get(i); + if (action instanceof SetRemoteCollectionItemListAdapterAction itemsAction + && itemsAction.viewId == viewId + && itemsAction.mServiceIntent != null) { + mActions.set(i, new SetRemoteCollectionItemListAdapterAction(itemsAction.viewId, + itemsAction.mServiceIntent)); + isActionReplaced = true; + } else if (action instanceof ViewGroupActionAdd groupAction + && groupAction.mNestedViews != null) { + isActionReplaced |= groupAction.mNestedViews.replaceRemoteCollections(viewId); + } + } + } + if (mSizedRemoteViews != null) { + for (int i = 0; i < mSizedRemoteViews.size(); i++) { + isActionReplaced |= mSizedRemoteViews.get(i).replaceRemoteCollections(viewId); + } + } + if (mLandscape != null) { + isActionReplaced |= mLandscape.replaceRemoteCollections(viewId); + } + if (mPortrait != null) { + isActionReplaced |= mPortrait.replaceRemoteCollections(viewId); + } + + return isActionReplaced; + } + private static void visitIconUri(Icon icon, @NonNull Consumer<Uri> visitor) { if (icon != null && (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) { @@ -1059,18 +1095,21 @@ public class RemoteViews implements Parcelable, Filter { private class SetRemoteCollectionItemListAdapterAction extends Action { private @NonNull CompletableFuture<RemoteCollectionItems> mItemsFuture; + final Intent mServiceIntent; SetRemoteCollectionItemListAdapterAction(@IdRes int id, @NonNull RemoteCollectionItems items) { viewId = id; items.setHierarchyRootData(getHierarchyRootData()); mItemsFuture = CompletableFuture.completedFuture(items); + mServiceIntent = null; } SetRemoteCollectionItemListAdapterAction(@IdRes int id, Intent intent) { viewId = id; mItemsFuture = getItemsFutureFromIntentWithTimeout(intent); setHierarchyRootData(getHierarchyRootData()); + mServiceIntent = intent; } private static CompletableFuture<RemoteCollectionItems> getItemsFutureFromIntentWithTimeout( @@ -1119,6 +1158,7 @@ public class RemoteViews implements Parcelable, Filter { viewId = parcel.readInt(); mItemsFuture = CompletableFuture.completedFuture( new RemoteCollectionItems(parcel, getHierarchyRootData())); + mServiceIntent = parcel.readTypedObject(Intent.CREATOR); } @Override @@ -1148,6 +1188,7 @@ public class RemoteViews implements Parcelable, Filter { dest.writeInt(viewId); RemoteCollectionItems items = getCollectionItemsFromFuture(mItemsFuture); items.writeToParcel(dest, flags, /* attached= */ true); + dest.writeTypedObject(mServiceIntent, flags); } @Override @@ -4765,9 +4806,7 @@ public class RemoteViews implements Parcelable, Filter { * providing data to the RemoteViewsAdapter */ public void setRemoteAdapter(@IdRes int viewId, Intent intent) { - if (AppGlobals.getIntCoreSetting( - SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION, - SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT ? 1 : 0) == 1) { + if (isAdapterConversionEnabled()) { addAction(new SetRemoteCollectionItemListAdapterAction(viewId, intent)); return; } @@ -4775,6 +4814,16 @@ public class RemoteViews implements Parcelable, Filter { } /** + * @hide + * @return True if the remote adapter conversion is enabled + */ + public static boolean isAdapterConversionEnabled() { + return AppGlobals.getIntCoreSetting( + SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION, + SystemUiDeviceConfigFlags.REMOTEVIEWS_ADAPTER_CONVERSION_DEFAULT ? 1 : 0) == 1; + } + + /** * Creates a simple Adapter for the viewId specified. The viewId must point to an AdapterView, * ie. {@link ListView}, {@link GridView}, {@link StackView} or {@link AdapterViewAnimator}. * This is a simpler but less flexible approach to populating collection widgets. Its use is |