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

Commit 6c7361fb authored by Pinyao Ting's avatar Pinyao Ting Committed by Android (Google) Code Review
Browse files

Merge "Cache and reuses LauncherAppWidgetHostView when launcher resumes" into tm-qpr-dev

parents c4405218 e5dbb75a
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -277,6 +277,10 @@ public final class FeatureFlags {
            "ENABLE_DISMISS_PREDICTION_UNDO", false,
            "Show an 'Undo' snackbar when users dismiss a predicted hotseat item");

    public static final BooleanFlag ENABLE_CACHED_WIDGET = getDebugFlag(
            "ENABLE_CACHED_WIDGET", true,
            "Show previously cached widgets as opposed to deferred widget where available");

    public static void initialize(Context context) {
        synchronized (sDebugFlags) {
            for (DebugFlag flag : sDebugFlags) {
+55 −6
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.util.SparseArray;
import android.widget.RemoteViews;
import android.widget.Toast;

import androidx.annotation.Nullable;
@@ -37,6 +38,7 @@ import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.testing.TestLogging;
@@ -70,13 +72,14 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
    private final ArrayList<ProviderChangedListener> mProviderChangeListeners = new ArrayList<>();
    private final SparseArray<LauncherAppWidgetHostView> mViews = new SparseArray<>();
    private final SparseArray<PendingAppWidgetHostView> mPendingViews = new SparseArray<>();
    private final SparseArray<LauncherAppWidgetHostView> mDeferredViews = new SparseArray<>();
    private final SparseArray<RemoteViews> mCachedRemoteViews = new SparseArray<>();

    private final Context mContext;
    private int mFlags = FLAG_STATE_IS_NORMAL;

    private IntConsumer mAppWidgetRemovedCallback = null;


    public LauncherAppWidgetHost(Context context) {
        this(context, null);
    }
@@ -95,6 +98,11 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
        if (mPendingViews.get(appWidgetId) != null) {
            view = mPendingViews.get(appWidgetId);
            mPendingViews.remove(appWidgetId);
        } else if (mDeferredViews.get(appWidgetId) != null) {
            // In case the widget view is deferred, we will simply return the deferred view as
            // opposed to instantiate a new instance of LauncherAppWidgetHostView since launcher
            // already added the former to the workspace.
            view = mDeferredViews.get(appWidgetId);
        } else {
            view = new LauncherAppWidgetHostView(context);
        }
@@ -120,12 +128,25 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
            // widgets upon bind anyway. See issue 14255011 for more context.
        }

        // We go in reverse order and inflate any deferred widget
        // We go in reverse order and inflate any deferred or cached widget
        for (int i = mViews.size() - 1; i >= 0; i--) {
            LauncherAppWidgetHostView view = mViews.valueAt(i);
            if (view instanceof DeferredAppWidgetHostView) {
                view.reInflate();
            }
            if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
                final int appWidgetId = mViews.keyAt(i);
                if (view == mDeferredViews.get(appWidgetId)) {
                    // If the widget view was deferred, we'll need to call super.createView here
                    // to make the binder call to system process to fetch cumulative updates to this
                    // widget, as well as setting up this view for future updates.
                    super.createView(view.mLauncher, appWidgetId, view.getAppWidgetInfo());
                    // At this point #onCreateView should have been called, which in turn returned
                    // the deferred view. There's no reason to keep the reference anymore, so we
                    // removed it here.
                    mDeferredViews.remove(appWidgetId);
                }
            }
        }
    }

@@ -221,10 +242,28 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
            CustomWidgetManager.INSTANCE.get(context).onViewCreated(lahv);
            return lahv;
        } else if ((mFlags & FLAG_LISTENING) == 0) {
            // Since the launcher hasn't started listening to widget updates, we can't simply call
            // super.createView here because the later will make a binder call to retrieve
            // RemoteViews from system process.
            // TODO: have launcher always listens to widget updates in background so that this
            //  check can be removed altogether.
            if (FeatureFlags.ENABLE_CACHED_WIDGET.get()
                    && mCachedRemoteViews.get(appWidgetId) != null) {
                // We've found RemoteViews from cache for this widget, so we will instantiate a
                // widget host view and populate it with the cached RemoteViews.
                final LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
                view.setAppWidget(appWidgetId, appWidget);
                view.updateAppWidget(mCachedRemoteViews.get(appWidgetId));
                mDeferredViews.put(appWidgetId, view);
                mViews.put(appWidgetId, view);
                return view;
            } else {
                // When cache misses, a placeholder for the widget will be returned instead.
                DeferredAppWidgetHostView view = new DeferredAppWidgetHostView(context);
                view.setAppWidget(appWidgetId, appWidget);
                mViews.put(appWidgetId, view);
                return view;
            }
        } else {
            try {
                return super.createView(context, appWidgetId, appWidget);
@@ -281,6 +320,16 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
    @Override
    public void clearViews() {
        super.clearViews();
        if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
            // First, we clear any previously cached content from existing widgets
            mCachedRemoteViews.clear();
            // Then we proceed to cache the content from the widgets
            for (int i = 0; i < mViews.size(); i++) {
                final int appWidgetId = mViews.keyAt(i);
                final LauncherAppWidgetHostView view = mViews.get(appWidgetId);
                mCachedRemoteViews.put(appWidgetId, view.mLastRemoteViews);
            }
        }
        mViews.clear();
    }

+14 −7
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.launcher3.CheckLongPressHelper;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
@@ -85,7 +86,7 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
    private Runnable mAutoAdvanceRunnable;

    private long mDeferUpdatesUntilMillis = 0;
    private RemoteViews mDeferredRemoteViews;
    RemoteViews mLastRemoteViews;
    private boolean mHasDeferredColorChange = false;
    private @Nullable SparseIntArray mDeferredColorChange = null;

@@ -150,11 +151,18 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
                    TRACE_METHOD_NAME + getAppWidgetInfo().provider, getAppWidgetId());
            mTrackingWidgetUpdate = false;
        }
        if (FeatureFlags.ENABLE_CACHED_WIDGET.get()) {
            mLastRemoteViews = remoteViews;
            if (isDeferringUpdates()) {
            mDeferredRemoteViews = remoteViews;
                return;
            }
        mDeferredRemoteViews = null;
        } else {
            if (isDeferringUpdates()) {
                mLastRemoteViews = remoteViews;
                return;
            }
            mLastRemoteViews = null;
        }

        super.updateAppWidget(remoteViews);

@@ -218,8 +226,7 @@ public class LauncherAppWidgetHostView extends BaseLauncherAppWidgetHostView
        SparseIntArray deferredColors;
        boolean hasDeferredColors;
        mDeferUpdatesUntilMillis = 0;
        remoteViews = mDeferredRemoteViews;
        mDeferredRemoteViews = null;
        remoteViews = mLastRemoteViews;
        deferredColors = mDeferredColorChange;
        hasDeferredColors = mHasDeferredColorChange;
        mDeferredColorChange = null;