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

Commit 9151c011 authored by Samuel Fufa's avatar Samuel Fufa
Browse files

Allow Launcher to automatically restore widgets

This replaces PendingAppWidgetHostView with configured widget view when
OPTION_APPWIDGET_RESTORE_COMPLETED is set to True by a widget provider.

Bug: 63667276
Test: Manual
Change-Id: Ide21f5e9a7dac7e3d6a745660a38ad0b951b47d3
parent d71c3b18
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -2305,6 +2305,13 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
                    item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
                    getModelWriter().updateItemInDatabase(item);
                }
                else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
                        && appWidgetInfo.configure != null) {
                    if (mAppWidgetManager.isAppWidgetRestored(item.appWidgetId)) {
                        item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
                        getModelWriter().updateItemInDatabase(item);
                    }
                }
            }

            if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
@@ -2318,6 +2325,11 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
                item.minSpanX = appWidgetInfo.minSpanX;
                item.minSpanY = appWidgetInfo.minSpanY;
                view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
            } else if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)
                    && appWidgetInfo != null) {
                mAppWidgetHost.addPendingView(item.appWidgetId,
                        new PendingAppWidgetHostView(this, item, mIconCache, false));
                view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
            } else {
                view = new PendingAppWidgetHostView(this, item, mIconCache, false);
            }
+16 −3
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.widget.Toast;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.widget.DeferredAppWidgetHostView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.PendingAppWidgetHostView;
import com.android.launcher3.widget.custom.CustomWidgetManager;

import java.util.ArrayList;
@@ -53,12 +54,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 Context mContext;
    private int mFlags = FLAG_RESUMED;

    private IntConsumer mAppWidgetRemovedCallback = null;


    public LauncherAppWidgetHost(Context context) {
        this(context, null);
    }
@@ -73,7 +76,13 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
    @Override
    protected LauncherAppWidgetHostView onCreateView(Context context, int appWidgetId,
            AppWidgetProviderInfo appWidget) {
        LauncherAppWidgetHostView view = new LauncherAppWidgetHostView(context);
        final LauncherAppWidgetHostView view;
        if (mPendingViews.get(appWidgetId) != null) {
            view = mPendingViews.get(appWidgetId);
            mPendingViews.remove(appWidgetId);
        } else {
            view = new LauncherAppWidgetHostView(context);
        }
        mViews.put(appWidgetId, view);
        return view;
    }
@@ -189,6 +198,10 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
        }
    }

    void addPendingView(int appWidgetId, PendingAppWidgetHostView view) {
        mPendingViews.put(appWidgetId, view);
    }

    public AppWidgetHostView createView(Context context, int appWidgetId,
            LauncherAppWidgetProviderInfo appWidget) {
        if (appWidget.isCustomWidget()) {
@@ -238,8 +251,8 @@ public class LauncherAppWidgetHost extends AppWidgetHost {

    /**
     * Called on an appWidget is removed for a widgetId
     * @param appWidgetId
     * TODO: make this override when SDK is updated
     *
     * @param appWidgetId TODO: make this override when SDK is updated
     */
    public void onAppWidgetRemoved(int appWidgetId) {
        if (mAppWidgetRemovedCallback == null) {
+10 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RemoteViews;

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.FastBitmapDrawable;
@@ -93,6 +94,15 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
        }
    }

    @Override
    public void updateAppWidget(RemoteViews remoteViews) {
        super.updateAppWidget(remoteViews);
        WidgetManagerHelper widgetManagerHelper = new WidgetManagerHelper(getContext());
        if (widgetManagerHelper.isAppWidgetRestored(mInfo.appWidgetId)) {
            reInflate();
        }
    }

    @Override
    public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth,
            int maxHeight) {
+11 −0
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ import java.util.stream.Stream;
 */
public class WidgetManagerHelper {

    //TODO: replace this with OPTION_APPWIDGET_RESTORE_COMPLETED b/63667276
    public static final String WIDGET_OPTION_RESTORE_COMPLETED = "appWidgetRestoreCompleted";

    final AppWidgetManager mAppWidgetManager;
    final Context mContext;

@@ -127,6 +130,14 @@ public class WidgetManagerHelper {
        return null;
    }

    /**
     * Returns if a AppWidgetProvider has marked a widget restored
     */
    public boolean isAppWidgetRestored(int appWidgetId) {
        return !WidgetsModel.GO_DISABLE_WIDGETS && mAppWidgetManager.getAppWidgetOptions(
                appWidgetId).getBoolean(WIDGET_OPTION_RESTORE_COMPLETED);
    }

    public static Map<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap(Context context) {
        if (WidgetsModel.GO_DISABLE_WIDGETS) {
            return Collections.emptyMap();
+28 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.launcher3.widget.WidgetHostViewLoader.getDefaultOption

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import android.appwidget.AppWidgetHost;
@@ -33,6 +34,7 @@ import android.content.pm.PackageInstaller.SessionParams;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.widget.RemoteViews;

import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -41,6 +43,7 @@ import com.android.launcher3.LauncherAppWidgetHost;
import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.R;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.tapl.Workspace;
import com.android.launcher3.ui.AbstractLauncherUiTest;
@@ -86,7 +89,8 @@ public class BindWidgetTest extends AbstractLauncherUiTest {

        // Clear all existing data
        LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CREATE_EMPTY_DB);
        LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
        LauncherSettings.Settings.call(mResolver,
                LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG);
    }

    @After
@@ -172,6 +176,26 @@ public class BindWidgetTest extends AbstractLauncherUiTest {
        assertNotNull(AppWidgetManager.getInstance(mTargetContext)
                .getAppWidgetInfo(mCursor.getInt(mCursor.getColumnIndex(
                        LauncherSettings.Favorites.APPWIDGET_ID))));

        // send OPTION_APPWIDGET_RESTORE_COMPLETED
        int appWidgetId = mCursor.getInt(
                mCursor.getColumnIndex(LauncherSettings.Favorites.APPWIDGET_ID));
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mTargetContext);

        Bundle b = new Bundle();
        b.putBoolean(WidgetManagerHelper.WIDGET_OPTION_RESTORE_COMPLETED, true);
        RemoteViews remoteViews = new RemoteViews(mTargetPackage, R.layout.appwidget_not_ready);
        appWidgetManager.updateAppWidgetOptions(appWidgetId, b);
        appWidgetManager.updateAppWidget(appWidgetId, remoteViews);


        // verify changes are reflected
        waitForLauncherCondition("App widget options did not update",
                l -> appWidgetManager.getAppWidgetOptions(appWidgetId).getBoolean(
                        WidgetManagerHelper.WIDGET_OPTION_RESTORE_COMPLETED));
        executeOnLauncher(l -> l.getAppWidgetHost().startListening());
        verifyWidgetPresent(info);
        assertNull(mLauncher.getWorkspace().tryGetPendingWidget(DEFAULT_UI_TIMEOUT));
    }

    @Test
@@ -254,6 +278,7 @@ public class BindWidgetTest extends AbstractLauncherUiTest {

    /**
     * Creates a LauncherAppWidgetInfo corresponding to {@param info}
     *
     * @param bindWidget if true the info is bound and a valid widgetId is assigned to
     *                   the LauncherAppWidgetInfo
     */