Merge "Removing support for legacy shortcuts from default layouts" into udc-dev am: 8382546a11
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/22351739 Change-Id: I2e0bfb7fa547a999db77086388b9457dc0730e02 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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,59 +425,27 @@ 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);
|
||||
final String packageName = getAttributeValue(parser, ATTR_PACKAGE_NAME);
|
||||
final String shortcutId = getAttributeValue(parser, ATTR_SHORTCUT_ID);
|
||||
|
||||
if (titleResId == 0 || iconId == 0) {
|
||||
if (LOGD) Log.d(TAG, "Ignoring shortcut");
|
||||
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);
|
||||
}
|
||||
|
||||
final Intent intent = parseIntent(parser);
|
||||
if (intent == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
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));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user