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

Commit e7fba958 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Update RemoteViews in background" into udc-qpr-dev am: 5ccb0ccd

parents 64189ac1 5ccb0ccd
Loading
Loading
Loading
Loading
+108 −19
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.annotation.UiThread;
import android.annotation.UserIdInt;
import android.app.IServiceConnection;
import android.app.PendingIntent;
@@ -39,6 +40,10 @@ import android.content.pm.ShortcutInfo;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.DisplayMetrics;
@@ -53,6 +58,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

/**
 * Updates AppWidget state; gets information about installed AppWidget providers and other
@@ -475,6 +481,8 @@ public class AppWidgetManager {

    private static final String TAG = "AppWidgetManager";

    private static Executor sUpdateExecutor;

    /**
     * An intent extra that contains multiple appWidgetIds.  These are id values as
     * they were provided to the application during a recent restore from backup.  It is
@@ -510,6 +518,8 @@ public class AppWidgetManager {
    private final IAppWidgetService mService;
    private final DisplayMetrics mDisplayMetrics;

    private boolean mHasPostedLegacyLists = false;

    /**
     * Get the AppWidgetManager instance to use for the supplied {@link android.content.Context
     * Context} object.
@@ -552,6 +562,13 @@ public class AppWidgetManager {
        });
    }

    private boolean isPostingTaskToBackground(@Nullable RemoteViews views) {
        return Looper.myLooper() == Looper.getMainLooper()
                && RemoteViews.isAdapterConversionEnabled()
                && (mHasPostedLegacyLists = mHasPostedLegacyLists
                        || (views != null && views.hasLegacyLists()));
    }

    /**
     * Set the RemoteViews to use for the specified appWidgetIds.
     * <p>
@@ -575,6 +592,19 @@ public class AppWidgetManager {
        if (mService == null) {
            return;
        }

        if (isPostingTaskToBackground(views)) {
            createUpdateExecutorIfNull().execute(() -> {
                try {
                    mService.updateAppWidgetIds(mPackageName, appWidgetIds, views);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error updating app widget views in background", e);
                }
            });

            return;
        }

        try {
            mService.updateAppWidgetIds(mPackageName, appWidgetIds, views);
        } catch (RemoteException e) {
@@ -683,6 +713,19 @@ public class AppWidgetManager {
        if (mService == null) {
            return;
        }

        if (isPostingTaskToBackground(views)) {
            createUpdateExecutorIfNull().execute(() -> {
                try {
                    mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error partially updating app widget views in background", e);
                }
            });

            return;
        }

        try {
            mService.partiallyUpdateAppWidgetIds(mPackageName, appWidgetIds, views);
        } catch (RemoteException e) {
@@ -738,6 +781,19 @@ public class AppWidgetManager {
        if (mService == null) {
            return;
        }

        if (isPostingTaskToBackground(views)) {
            createUpdateExecutorIfNull().execute(() -> {
                try {
                    mService.updateAppWidgetProvider(provider, views);
                } catch (RemoteException e) {
                    Log.e(TAG, "Error updating app widget view using provider in background", e);
                }
            });

            return;
        }

        try {
            mService.updateAppWidgetProvider(provider, views);
        } catch (RemoteException e) {
@@ -786,8 +842,28 @@ public class AppWidgetManager {
        if (mService == null) {
            return;
        }

        if (!RemoteViews.isAdapterConversionEnabled()) {
            try {
                mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
            } catch (RemoteException re) {
                throw re.rethrowFromSystemServer();
            }

            return;
        }

        if (Looper.myLooper() == Looper.getMainLooper()) {
            mHasPostedLegacyLists = true;
            createUpdateExecutorIfNull().execute(() -> notifyCollectionWidgetChange(appWidgetIds,
                    viewId));
        } else {
            notifyCollectionWidgetChange(appWidgetIds, viewId);
        }
    }

    private void notifyCollectionWidgetChange(int[] appWidgetIds, int viewId) {
        try {
            if (RemoteViews.isAdapterConversionEnabled()) {
            List<CompletableFuture<Void>> updateFutures = new ArrayList<>();
            for (int i = 0; i < appWidgetIds.length; i++) {
                final int widgetId = appWidgetIds[i];
@@ -803,11 +879,8 @@ public class AppWidgetManager {
                }));
            }
            CompletableFuture.allOf(updateFutures.toArray(CompletableFuture[]::new)).join();
            } else {
                mService.notifyAppWidgetViewDataChanged(mPackageName, appWidgetIds, viewId);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        } catch (Exception e) {
            Log.e(TAG, "Error notifying changes for all widgets", e);
        }
    }

@@ -1338,4 +1411,20 @@ public class AppWidgetManager {
            throw e.rethrowFromSystemServer();
        }
    }

    @UiThread
    private static @NonNull Executor createUpdateExecutorIfNull() {
        if (sUpdateExecutor == null) {
            sUpdateExecutor = new HandlerExecutor(createAndStartNewHandler(
                    "widget_manager_update_helper_thread", Process.THREAD_PRIORITY_FOREGROUND));
        }

        return sUpdateExecutor;
    }

    private static @NonNull Handler createAndStartNewHandler(@NonNull String name, int priority) {
        HandlerThread thread = new HandlerThread(name, priority);
        thread.start();
        return thread.getThreadHandler();
    }
}
+41 −0
Original line number Diff line number Diff line
@@ -801,6 +801,11 @@ public class RemoteViews implements Parcelable, Filter {
                    mActions.set(i, new SetRemoteCollectionItemListAdapterAction(itemsAction.viewId,
                            itemsAction.mServiceIntent));
                    isActionReplaced = true;
                } else if (action instanceof SetRemoteViewsAdapterIntent intentAction
                        && intentAction.viewId == viewId) {
                    mActions.set(i, new SetRemoteCollectionItemListAdapterAction(
                            intentAction.viewId, intentAction.intent));
                    isActionReplaced = true;
                } else if (action instanceof ViewGroupActionAdd groupAction
                        && groupAction.mNestedViews != null) {
                    isActionReplaced |= groupAction.mNestedViews.replaceRemoteCollections(viewId);
@@ -822,6 +827,42 @@ public class RemoteViews implements Parcelable, Filter {
        return isActionReplaced;
    }

    /**
     * @return True if has set remote adapter using service intent
     * @hide
     */
    public boolean hasLegacyLists() {
        if (mActions != null) {
            for (int i = 0; i < mActions.size(); i++) {
                Action action = mActions.get(i);
                if ((action instanceof SetRemoteCollectionItemListAdapterAction itemsAction
                        && itemsAction.mServiceIntent != null)
                        || (action instanceof SetRemoteViewsAdapterIntent intentAction
                                && intentAction.intent != null)
                        || (action instanceof ViewGroupActionAdd groupAction
                                && groupAction.mNestedViews != null
                                && groupAction.mNestedViews.hasLegacyLists())) {
                    return true;
                }
            }
        }
        if (mSizedRemoteViews != null) {
            for (int i = 0; i < mSizedRemoteViews.size(); i++) {
                if (mSizedRemoteViews.get(i).hasLegacyLists()) {
                    return true;
                }
            }
        }
        if (mLandscape != null && mLandscape.hasLegacyLists()) {
            return true;
        }
        if (mPortrait != null && mPortrait.hasLegacyLists()) {
            return true;
        }

        return false;
    }

    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)) {