Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09361277 authored by Sihua Ma's avatar Sihua Ma
Browse files

Notify the change in collection items by passing the old RemoteViews

Also tuning the meta parameter a bit to mitigate the parcel exception

Bug: 245950570
Test: Manual
Change-Id: I1c34e8cf1b30f8a24dddafeed0eec50415457d0b
parent 990069ff
Loading
Loading
Loading
Loading
+21 −1
Original line number Diff line number Diff line
@@ -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 {
            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();
        }
+52 −3
Original line number Diff line number Diff line
@@ -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,15 +4806,23 @@ 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;
        }
        addAction(new SetRemoteViewsAdapterIntent(viewId, intent));
    }

    /**
     * @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}.