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

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

Merge "Removing support for legacy shortcuts from default layouts" into udc-dev

parents 5489507e afaa8f0b
Loading
Loading
Loading
Loading
+33 −68
Original line number Diff line number Diff line
@@ -24,30 +24,29 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Patterns;
import android.util.Xml;

import androidx.annotation.Nullable;

import com.android.launcher3.LauncherProvider.SqlArguments;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.GraphicsUtils;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.qsb.QsbContainerView;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.uioverrides.ApiWrapper;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.Partner;
@@ -58,6 +57,7 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.function.Supplier;
@@ -135,6 +135,7 @@ public class AutoInstallsLayout {
    private static final String ATTR_TITLE = "title";
    private static final String ATTR_TITLE_TEXT = "titleText";
    private static final String ATTR_SCREEN = "screen";
    private static final String ATTR_SHORTCUT_ID = "shortcutId";

    // x and y can be specified as negative integers, in which case -1 represents the
    // last row / column, -2 represents the second last, and so on.
@@ -143,8 +144,6 @@ public class AutoInstallsLayout {

    private static final String ATTR_SPAN_X = "spanX";
    private static final String ATTR_SPAN_Y = "spanY";
    private static final String ATTR_ICON = "icon";
    private static final String ATTR_URL = "url";

    // Attrs for "Include"
    private static final String ATTR_WORKSPACE = "workspace";
@@ -156,10 +155,8 @@ public class AutoInstallsLayout {
    private static final String HOTSEAT_CONTAINER_NAME =
            Favorites.containerToString(Favorites.CONTAINER_HOTSEAT);

    @Thunk
    final Context mContext;
    @Thunk
    final LauncherWidgetHolder mAppWidgetHolder;
    protected final Context mContext;
    protected final LauncherWidgetHolder mAppWidgetHolder;
    protected final LayoutParserCallback mCallback;

    protected final PackageManager mPackageManager;
@@ -308,7 +305,15 @@ public class AutoInstallsLayout {
        mValues.put(Favorites.SPANY, 1);
        mValues.put(Favorites._ID, id);

        maybeReplaceShortcut(intent.getComponent().getPackageName(), type);
        if (type == ITEM_TYPE_APPLICATION) {
            ComponentName cn = intent.getComponent();
            if (cn != null && mActivityOverride.containsKey(cn.getPackageName())) {
                LauncherActivityInfo replacementInfo = mActivityOverride.get(cn.getPackageName());
                mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
                        .getSerialNumberForUser(replacementInfo.getUser()));
                mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
            }
        }

        if (mCallback.insertAndCheck(mDb, mValues) < 0) {
            return -1;
@@ -321,7 +326,7 @@ public class AutoInstallsLayout {
        ArrayMap<String, TagParser> parsers = new ArrayMap<>();
        parsers.put(TAG_APP_ICON, new AppShortcutParser());
        parsers.put(TAG_AUTO_INSTALL, new AutoInstallParser());
        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
        parsers.put(TAG_SHORTCUT, new ShortcutParser());
        return parsers;
    }

@@ -332,7 +337,7 @@ public class AutoInstallsLayout {
        parsers.put(TAG_FOLDER, new FolderParser());
        parsers.put(TAG_APPWIDGET, new PendingWidgetParser());
        parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
        parsers.put(TAG_SHORTCUT, new ShortcutParser(mSourceRes));
        parsers.put(TAG_SHORTCUT, new ShortcutParser());
        return parsers;
    }

@@ -420,60 +425,28 @@ public class AutoInstallsLayout {
    }

    /**
     * Parses a web shortcut. Required attributes url, icon, title
     * Parses a deep shortcut. Required attributes packageName and shortcutId
     */
    protected class ShortcutParser implements TagParser {

        private final Resources mIconRes;

        public ShortcutParser(Resources iconRes) {
            mIconRes = iconRes;
        }

        @Override
        public int parseAndAdd(XmlPullParser parser) {
            final int titleResId = getAttributeResourceValue(parser, ATTR_TITLE, 0);
            final int iconId = getAttributeResourceValue(parser, ATTR_ICON, 0);

            if (titleResId == 0 || iconId == 0) {
                if (LOGD) Log.d(TAG, "Ignoring shortcut");
                return -1;
            }
            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
            final String shortcutId = getAttributeValue(parser, ATTR_SHORTCUT_ID);

            final Intent intent = parseIntent(parser);
            if (intent == null) {
                return -1;
            try {
                LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
                launcherApps.pinShortcuts(packageName, Collections.singletonList(shortcutId),
                        Process.myUserHandle());
                Intent intent = ShortcutKey.makeIntent(shortcutId, packageName);
                mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_RESTORED_ICON);
                return addShortcut(null, intent, Favorites.ITEM_TYPE_DEEP_SHORTCUT);
            } catch (Exception e) {
                Log.e(TAG, "Unable to pin the shortcut for shortcut id = " + shortcutId
                        + " and package name = " + packageName, e);
            }

            Drawable icon = mIconRes.getDrawable(iconId);
            if (icon == null) {
                if (LOGD) Log.d(TAG, "Ignoring shortcut, can't load icon");
            return -1;
        }

            // Auto installs should always support the current platform version.
            LauncherIcons li = LauncherIcons.obtain(mContext);
            mValues.put(LauncherSettings.Favorites.ICON, GraphicsUtils.flattenBitmap(
                    li.createBadgedIconBitmap(icon).icon));
            li.recycle();

            mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
            mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));

            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                    Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
            return addShortcut(mSourceRes.getString(titleResId),
                    intent, Favorites.ITEM_TYPE_SHORTCUT);
        }

        protected Intent parseIntent(XmlPullParser parser) {
            final String url = getAttributeValue(parser, ATTR_URL);
            if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches()) {
                if (LOGD) Log.d(TAG, "Ignoring shortcut, invalid url: " + url);
                return null;
            }
            return new Intent(Intent.ACTION_VIEW, null).setData(Uri.parse(url));
        }
    }

    /**
@@ -728,12 +701,4 @@ public class AutoInstallsLayout {
        to.put(key, from.getAsInteger(key));
    }

    private void maybeReplaceShortcut(String packageName, int type) {
        if (mActivityOverride.containsKey(packageName) && type == ITEM_TYPE_APPLICATION) {
            LauncherActivityInfo replacementInfo = mActivityOverride.get(packageName);
            mValues.put(Favorites.PROFILE_ID, UserCache.INSTANCE.get(mContext)
                    .getSerialNumberForUser(replacementInfo.getUser()));
            mValues.put(Favorites.INTENT, AppInfo.makeLaunchIntent(replacementInfo).toUri(0));
        }
    }
}
+4 −69
Original line number Diff line number Diff line
@@ -6,19 +6,15 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Process;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;

import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.Partner;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.widget.LauncherWidgetHolder;
@@ -28,7 +24,6 @@ import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.List;

/**
@@ -49,8 +44,6 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
    private static final String ATTR_CONTAINER = "container";
    private static final String ATTR_SCREEN = "screen";
    private static final String ATTR_FOLDER_ITEMS = "folderItems";
    private static final String ATTR_SHORTCUT_ID = "shortcutId";
    private static final String ATTR_PACKAGE_NAME = "packageName";

    public static final String RES_PARTNER_FOLDER = "partner_folder";
    public static final String RES_PARTNER_DEFAULT_LAYOUT = "partner_default_layout";
@@ -66,14 +59,9 @@ public class DefaultLayoutParser extends AutoInstallsLayout {

    @Override
    protected ArrayMap<String, TagParser> getFolderElementsMap() {
        return getFolderElementsMap(mSourceRes);
    }

    @Thunk
    ArrayMap<String, TagParser> getFolderElementsMap(Resources res) {
        ArrayMap<String, TagParser> parsers = new ArrayMap<>();
        parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
        parsers.put(TAG_SHORTCUT, new UriShortcutParser(res));
        parsers.put(TAG_SHORTCUT, new ShortcutParser());
        return parsers;
    }

@@ -83,7 +71,7 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
        parsers.put(TAG_FAVORITE, new AppShortcutWithUriParser());
        parsers.put(TAG_APPWIDGET, new AppWidgetParser());
        parsers.put(TAG_SEARCH_WIDGET, new SearchWidgetParser());
        parsers.put(TAG_SHORTCUT, new UriShortcutParser(mSourceRes));
        parsers.put(TAG_SHORTCUT, new ShortcutParser());
        parsers.put(TAG_RESOLVE, new ResolveParser());
        parsers.put(TAG_FOLDER, new MyFolderParser());
        parsers.put(TAG_PARTNER_FOLDER, new PartnerFolderParser());
@@ -189,57 +177,6 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
        }
    }

    /**
     * Shortcut parser which allows any uri and not just web urls.
     */
    public class UriShortcutParser extends ShortcutParser {

        public UriShortcutParser(Resources iconRes) {
            super(iconRes);
        }

        @Override
        public int parseAndAdd(XmlPullParser parser) {
            final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
            final String shortcutId = getAttributeValue(parser, ATTR_SHORTCUT_ID);
            if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(shortcutId)) {
                return parseAndAddDeepShortcut(shortcutId, packageName);
            }
            return super.parseAndAdd(parser);
        }

        /**
         * This method parses and adds a deep shortcut.
         * @return item id if the shortcut is successfully added else -1
         */
        private int parseAndAddDeepShortcut(String shortcutId, String packageName) {
            try {
                LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class);
                launcherApps.pinShortcuts(packageName, Collections.singletonList(shortcutId),
                        Process.myUserHandle());
                Intent intent = ShortcutKey.makeIntent(shortcutId, packageName);
                mValues.put(Favorites.RESTORED, WorkspaceItemInfo.FLAG_RESTORED_ICON);
                return addShortcut(null, intent, Favorites.ITEM_TYPE_DEEP_SHORTCUT);
            } catch (Exception e) {
                Log.e(TAG, "Unable to pin the shortcut for shortcut id = " + shortcutId
                        + " and package name = " + packageName);
            }
            return -1;
        }

        @Override
        protected Intent parseIntent(XmlPullParser parser) {
            String uri = null;
            try {
                uri = getAttributeValue(parser, ATTR_URI);
                return Intent.parseUri(uri, 0);
            } catch (URISyntaxException e) {
                Log.w(TAG, "Shortcut has malformed uri: " + uri);
                return null; // Oh well
            }
        }
    }

    /**
     * Contains a list of <favorite> nodes, and accepts the first successfully parsed node.
     */
@@ -284,11 +221,9 @@ public class DefaultLayoutParser extends AutoInstallsLayout {
            if (partner != null) {
                final int resId = partner.getXmlResId(RES_PARTNER_FOLDER);
                if (resId != 0) {
                    final Resources partnerRes = partner.getResources();
                    final XmlPullParser partnerParser = partnerRes.getXml(resId);
                    final XmlPullParser partnerParser = partner.getResources().getXml(resId);
                    beginDocument(partnerParser, TAG_FOLDER);

                    FolderParser folderParser = new FolderParser(getFolderElementsMap(partnerRes));
                    FolderParser folderParser = new FolderParser(getFolderElementsMap());
                    return folderParser.parseAndAdd(partnerParser);
                }
            }
+34 −0
Original line number Diff line number Diff line
@@ -20,8 +20,10 @@ import static com.android.launcher3.util.LauncherModelHelper.TEST_ACTIVITY;
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;

import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

import android.content.Context;
import android.content.pm.LauncherApps;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageInstaller.SessionParams;

@@ -127,6 +129,38 @@ public class DefaultLayoutProviderTest {
        assertEquals(2, info.spanY);
    }

    @Test
    public void testCustomProfileLoaded_with_shortcut_on_hotseat() throws Exception {
        assumeTrue(mTargetContext.getSystemService(LauncherApps.class).hasShortcutHostPermission());
        writeLayoutAndLoad(new LauncherLayoutBuilder().atHotseat(0)
                .putShortcut(TEST_PACKAGE, "shortcut2"));

        // Verify one item in hotseat
        assertEquals(1, mModelHelper.getBgDataModel().workspaceItems.size());
        ItemInfo info = mModelHelper.getBgDataModel().workspaceItems.get(0);
        assertEquals(LauncherSettings.Favorites.CONTAINER_HOTSEAT, info.container);
        assertEquals(LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT, info.itemType);
    }

    @Test
    public void testCustomProfileLoaded_with_shortcut_in_folder() throws Exception {
        assumeTrue(mTargetContext.getSystemService(LauncherApps.class).hasShortcutHostPermission());
        writeLayoutAndLoad(new LauncherLayoutBuilder().atHotseat(0).putFolder(android.R.string.copy)
                .addApp(TEST_PACKAGE, TEST_ACTIVITY)
                .addApp(TEST_PACKAGE, TEST_ACTIVITY)
                .addShortcut(TEST_PACKAGE, "shortcut2")
                .build());

        // Verify folder
        assertEquals(1, mModelHelper.getBgDataModel().workspaceItems.size());
        FolderInfo info = (FolderInfo) mModelHelper.getBgDataModel().workspaceItems.get(0);
        assertEquals(3, info.contents.size());

        // Verify last icon
        assertEquals(LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT,
                info.contents.get(info.contents.size() - 1).itemType);
    }

    private void writeLayoutAndLoad(LauncherLayoutBuilder builder) throws Exception {
        mModelHelper.setupDefaultLayoutProvider(builder).loadModelSync();
    }
+17 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ public class LauncherLayoutBuilder {
    private static final String TAG_AUTO_INSTALL = "autoinstall";
    private static final String TAG_FOLDER = "folder";
    private static final String TAG_APPWIDGET = "appwidget";
    private static final String TAG_SHORTCUT = "shortcut";
    private static final String TAG_EXTRA = "extra";

    private static final String ATTR_CONTAINER = "container";
@@ -49,6 +50,7 @@ public class LauncherLayoutBuilder {
    private static final String ATTR_TITLE = "title";
    private static final String ATTR_TITLE_TEXT = "titleText";
    private static final String ATTR_SCREEN = "screen";
    private static final String ATTR_SHORTCUT_ID = "shortcutId";

    // x and y can be specified as negative integers, in which case -1 represents the
    // last row / column, -2 represents the second last, and so on.
@@ -135,6 +137,13 @@ public class LauncherLayoutBuilder {
            return LauncherLayoutBuilder.this;
        }

        public LauncherLayoutBuilder putShortcut(String packageName, String shortcutId) {
            items.put(ATTR_PACKAGE_NAME, packageName);
            items.put(ATTR_SHORTCUT_ID, shortcutId);
            mNodes.add(Pair.create(TAG_SHORTCUT, items));
            return LauncherLayoutBuilder.this;
        }

        public LauncherLayoutBuilder putWidget(String packageName, String className,
                int spanX, int spanY) {
            items.put(ATTR_PACKAGE_NAME, packageName);
@@ -175,6 +184,14 @@ public class LauncherLayoutBuilder {
            return this;
        }

        public FolderBuilder addShortcut(String packageName, String shortcutId) {
            HashMap<String, Object> items = new HashMap<>();
            items.put(ATTR_PACKAGE_NAME, packageName);
            items.put(ATTR_SHORTCUT_ID, shortcutId);
            mChildren.add(Pair.create(TAG_SHORTCUT, items));
            return this;
        }

        public LauncherLayoutBuilder build() {
            return LauncherLayoutBuilder.this;
        }