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

Commit e2b2fb79 authored by Sunny Goyal's avatar Sunny Goyal Committed by Android (Google) Code Review
Browse files

Merge "Adding support for pending widgets in AutoInstall layout" into ub-launcher3-calgary-polish

parents c816967f 86df138d
Loading
Loading
Loading
Loading
+25 −47
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ public class AutoInstallsLayout {
        parsers.put(TAG_APP_ICON, new AppShortcutParser());
        parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
        parsers.put(TAG_FOLDER, new FolderParser());
        parsers.put(TAG_APPWIDGET, new AppWidgetParser());
        parsers.put(TAG_APPWIDGET, new PendingWidgetParser());
        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
        return parsers;
    }
@@ -459,8 +459,12 @@ public class AutoInstallsLayout {
    /**
     * AppWidget parser: Required attributes packageName, className, spanX and spanY.
     * Options child nodes: <extra key=... value=... />
     * It adds a pending widget which allows the widget to come later. If there are extras, those
     * are passed to widget options during bind.
     * The config activity for the widget (if present) is not shown, so any optional configurations
     * should be passed as extras and the widget should support reading these widget options.
     */
    protected class AppWidgetParser implements TagParser {
    protected class PendingWidgetParser implements TagParser {

        @Override
        public long parseAndAdd(XmlResourceParser parser)
@@ -468,27 +472,13 @@ public class AutoInstallsLayout {
            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
            final String className = getAttributeValue(parser, ATTR_CLASS_NAME);
            if (TextUtils.isEmpty(packageName) || TextUtils.isEmpty(className)) {
                if (LOGD) Log.d(TAG, "Skipping invalid <favorite> with no component");
                if (LOGD) Log.d(TAG, "Skipping invalid <appwidget> with no component");
                return -1;
            }

            ComponentName cn = new ComponentName(packageName, className);
            try {
                mPackageManager.getReceiverInfo(cn, 0);
            } catch (Exception e) {
                String[] packages = mPackageManager.currentToCanonicalPackageNames(
                        new String[] { packageName });
                cn = new ComponentName(packages[0], className);
                try {
                    mPackageManager.getReceiverInfo(cn, 0);
                } catch (Exception e1) {
                    if (LOGD) Log.d(TAG, "Can't find widget provider: " + className);
                    return -1;
                }
            }

            mValues.put(Favorites.SPANX, getAttributeValue(parser, ATTR_SPAN_X));
            mValues.put(Favorites.SPANY, getAttributeValue(parser, ATTR_SPAN_Y));
            mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);

            // Read the extras
            Bundle extras = new Bundle();
@@ -513,40 +503,28 @@ public class AutoInstallsLayout {
                }
            }

            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
            long insertedId = -1;
            try {
                int appWidgetId = mAppWidgetHost.allocateAppWidgetId();

                if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn)) {
                    if (LOGD) Log.e(TAG, "Unable to bind app widget id " + cn);
                    return -1;
            return verifyAndInsert(new ComponentName(packageName, className), extras);
        }

                mValues.put(Favorites.ITEM_TYPE, Favorites.ITEM_TYPE_APPWIDGET);
                mValues.put(Favorites.APPWIDGET_ID, appWidgetId);
        protected long verifyAndInsert(ComponentName cn, Bundle extras) {
            mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
            mValues.put(Favorites.RESTORED,
                    LauncherAppWidgetInfo.FLAG_ID_NOT_VALID |
                            LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY |
                            LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
            mValues.put(Favorites._ID, mCallback.generateNewItemId());
                insertedId = mCallback.insertAndCheck(mDb, mValues);
                if (insertedId < 0) {
                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
                    return insertedId;
                }

                // Send a broadcast to configure the widget
            if (!extras.isEmpty()) {
                    Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE);
                    intent.setComponent(cn);
                    intent.putExtras(extras);
                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                    mContext.sendBroadcast(intent);
                }
            } catch (RuntimeException ex) {
                if (LOGD) Log.e(TAG, "Problem allocating appWidgetId", ex);
                mValues.put(Favorites.INTENT, new Intent().putExtras(extras).toUri(0));
            }

            long insertedId = mCallback.insertAndCheck(mDb, mValues);
            if (insertedId < 0) {
                return -1;
            } else {
                return insertedId;
            }
        }
    }

    protected class FolderParser implements TagParser {
        private final HashMap<String, TagParser> mFolderElements;
+64 −0
Original line number Diff line number Diff line
package com.android.launcher3;

import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
@@ -9,6 +11,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;

@@ -42,6 +45,10 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
    private static final String ATTR_SCREEN = "screen";
    private static final String ATTR_FOLDER_ITEMS = "folderItems";

    // TODO: Remove support for this broadcast, instead use widget options to send bind time options
    private static final String ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE =
            "com.android.launcher.action.APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE";

    public DefaultLayoutParser(Context context, AppWidgetHost appWidgetHost,
            LayoutParserCallback callback, Resources sourceRes, int layoutId) {
        super(context, appWidgetHost, callback, sourceRes, layoutId, TAG_FAVORITES);
@@ -270,4 +277,61 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
            return super.parseAndAdd(parser);
        }
    }


    /**
     * AppWidget parser which enforces that the app is already installed when the layout is parsed.
     */
    protected class AppWidgetParser extends PendingWidgetParser {

        @Override
        protected long verifyAndInsert(ComponentName cn, Bundle extras) {
            try {
                mPackageManager.getReceiverInfo(cn, 0);
            } catch (Exception e) {
                String[] packages = mPackageManager.currentToCanonicalPackageNames(
                        new String[] { cn.getPackageName() });
                cn = new ComponentName(packages[0], cn.getClassName());
                try {
                    mPackageManager.getReceiverInfo(cn, 0);
                } catch (Exception e1) {
                    Log.d(TAG, "Can't find widget provider: " + cn.getClassName());
                    return -1;
                }
            }

            final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(mContext);
            long insertedId = -1;
            try {
                int appWidgetId = mAppWidgetHost.allocateAppWidgetId();

                if (!appWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, cn)) {
                    Log.e(TAG, "Unable to bind app widget id " + cn);
                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
                    return -1;
                }

                mValues.put(Favorites.APPWIDGET_ID, appWidgetId);
                mValues.put(Favorites.APPWIDGET_PROVIDER, cn.flattenToString());
                mValues.put(Favorites._ID, mCallback.generateNewItemId());
                insertedId = mCallback.insertAndCheck(mDb, mValues);
                if (insertedId < 0) {
                    mAppWidgetHost.deleteAppWidgetId(appWidgetId);
                    return insertedId;
                }

                // Send a broadcast to configure the widget
                if (!extras.isEmpty()) {
                    Intent intent = new Intent(ACTION_APPWIDGET_DEFAULT_WORKSPACE_CONFIGURE);
                    intent.setComponent(cn);
                    intent.putExtras(extras);
                    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
                    mContext.sendBroadcast(intent);
                }
            } catch (RuntimeException ex) {
                Log.e(TAG, "Problem allocating appWidgetId", ex);
            }
            return insertedId;
        }
    }
}
+17 −1
Original line number Diff line number Diff line
@@ -3952,14 +3952,30 @@ public class Launcher extends Activity
                    pendingInfo.minSpanX = item.minSpanX;
                    pendingInfo.minSpanY = item.minSpanY;
                    Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, pendingInfo);

                    boolean isDirectConfig =
                            item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
                    if (isDirectConfig && item.bindOptions != null) {
                        Bundle newOptions = item.bindOptions.getExtras();
                        if (options != null) {
                            newOptions.putAll(options);
                        }
                        options = newOptions;
                    }
                    boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
                            item.appWidgetId, appWidgetInfo, options);

                    // We tried to bind once. If we were not able to bind, we would need to
                    // go through the permission dialog, which means we cannot skip the config
                    // activity.
                    item.bindOptions = null;
                    item.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG;

                    // Bind succeeded
                    if (success) {
                        // If the widget has a configure activity, it is still needs to set it up,
                        // otherwise the widget is ready to go.
                        item.restoreStatus = (appWidgetInfo.configure == null)
                        item.restoreStatus = (appWidgetInfo.configure == null) || isDirectConfig
                                ? LauncherAppWidgetInfo.RESTORE_COMPLETED
                                : LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
                    }
+14 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.appwidget.AppWidgetHostView;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;

import com.android.launcher3.compat.UserHandleCompat;

@@ -56,6 +57,12 @@ public class LauncherAppWidgetInfo extends ItemInfo {
     */
    public static final int FLAG_ID_ALLOCATED = 16;

    /**
     * Indicates that the widget does not need to show config activity, even if it has a
     * configuration screen. It can also optionally have some extras which are sent during bind.
     */
    public static final int FLAG_DIRECT_CONFIG = 32;

    /**
     * Indicates that the widget hasn't been instantiated yet.
     */
@@ -84,6 +91,11 @@ public class LauncherAppWidgetInfo extends ItemInfo {
     */
    int installProgress = -1;

    /**
     * Optional extras sent during widget bind. See {@link #FLAG_DIRECT_CONFIG}.
     */
    public Intent bindOptions;

    private boolean mHasNotifiedInitialWidgetSizeChanged;

    LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
@@ -115,6 +127,8 @@ public class LauncherAppWidgetInfo extends ItemInfo {
        values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId);
        values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString());
        values.put(LauncherSettings.Favorites.RESTORED, restoreStatus);
        values.put(LauncherSettings.Favorites.INTENT,
                bindOptions == null ? null : bindOptions.toUri(0));
    }

    /**
+9 −1
Original line number Diff line number Diff line
@@ -2144,7 +2144,7 @@ public class LauncherModel extends BroadcastReceiver

                                            // Id would be valid only if the widget restore broadcast was received.
                                            if (isIdValid) {
                                                status = LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
                                                status |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
                                            } else {
                                                status &= ~LauncherAppWidgetInfo
                                                        .FLAG_PROVIDER_NOT_READY;
@@ -2175,6 +2175,14 @@ public class LauncherModel extends BroadcastReceiver
                                        appWidgetInfo.installProgress =
                                                installProgress == null ? 0 : installProgress;
                                    }
                                    if (appWidgetInfo.hasRestoreFlag(
                                            LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)) {
                                        intentDescription = c.getString(intentIndex);
                                        if (!TextUtils.isEmpty(intentDescription)) {
                                            appWidgetInfo.bindOptions =
                                                    Intent.parseUri(intentDescription, 0);
                                        }
                                    }

                                    appWidgetInfo.id = id;
                                    appWidgetInfo.screenId = c.getInt(screenIndex);