Merge "ShortcutManager: Fix work profile" into nyc-dev
This commit is contained in:
@@ -40,28 +40,37 @@ public abstract class ShortcutServiceInternal {
|
||||
}
|
||||
|
||||
public abstract List<ShortcutInfo>
|
||||
getShortcuts(@NonNull String callingPackage, long changedSince,
|
||||
getShortcuts(int launcherUserId,
|
||||
@NonNull String callingPackage, long changedSince,
|
||||
@Nullable String packageName, @Nullable ComponentName componentName,
|
||||
@ShortcutQuery.QueryFlags int flags,
|
||||
int userId);
|
||||
|
||||
public abstract List<ShortcutInfo>
|
||||
getShortcutInfo(@NonNull String callingPackage,
|
||||
getShortcutInfo(int launcherUserId, @NonNull String callingPackage,
|
||||
@NonNull String packageName, @Nullable List<String> ids, int userId);
|
||||
|
||||
public abstract void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
|
||||
|
||||
public abstract boolean
|
||||
isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
|
||||
@NonNull String packageName, @NonNull String id, int userId);
|
||||
|
||||
public abstract void pinShortcuts(int launcherUserId,
|
||||
@NonNull String callingPackage, @NonNull String packageName,
|
||||
@NonNull List<String> shortcutIds, int userId);
|
||||
|
||||
public abstract Intent createShortcutIntent(@NonNull String callingPackage,
|
||||
public abstract Intent createShortcutIntent(int launcherUserId, @NonNull String callingPackage,
|
||||
@NonNull String packageName, @NonNull String shortcutId, int userId);
|
||||
|
||||
public abstract void addListener(@NonNull ShortcutChangeListener listener);
|
||||
|
||||
public abstract int getShortcutIconResId(@NonNull String callingPackage,
|
||||
public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
|
||||
@NonNull ShortcutInfo shortcut, int userId);
|
||||
|
||||
public abstract ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
|
||||
public abstract ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
|
||||
@NonNull String callingPackage,
|
||||
@NonNull ShortcutInfo shortcut, int userId);
|
||||
|
||||
public abstract boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId);
|
||||
public abstract boolean hasShortcutHostPermission(int launcherUserId,
|
||||
@NonNull String callingPackage);
|
||||
}
|
||||
|
||||
@@ -335,40 +335,40 @@ public class LauncherAppsService extends SystemService {
|
||||
verifyCallingPackage(callingPackage);
|
||||
ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
|
||||
|
||||
if (!mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
|
||||
user.getIdentifier())) {
|
||||
if (!mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
|
||||
callingPackage)) {
|
||||
throw new SecurityException("Caller can't access shortcut information");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
|
||||
String packageName, ComponentName componentName, int flags, UserHandle user)
|
||||
throws RemoteException {
|
||||
String packageName, ComponentName componentName, int flags, UserHandle user) {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
|
||||
return new ParceledListSlice<>(
|
||||
mShortcutServiceInternal.getShortcuts(callingPackage, changedSince, packageName,
|
||||
componentName, flags, user.getIdentifier()));
|
||||
mShortcutServiceInternal.getShortcuts(getCallingUserId(),
|
||||
callingPackage, changedSince, packageName,
|
||||
componentName, flags, user.getIdentifier()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParceledListSlice getShortcutInfo(String callingPackage, String packageName,
|
||||
List<String> ids, UserHandle user) throws RemoteException {
|
||||
List<String> ids, UserHandle user) {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
|
||||
return new ParceledListSlice<>(
|
||||
mShortcutServiceInternal.getShortcutInfo(callingPackage, packageName,
|
||||
ids, user.getIdentifier()));
|
||||
mShortcutServiceInternal.getShortcutInfo(getCallingUserId(),
|
||||
callingPackage, packageName, ids, user.getIdentifier()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pinShortcuts(String callingPackage, String packageName, List<String> ids,
|
||||
UserHandle user) throws RemoteException {
|
||||
UserHandle user) {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
|
||||
mShortcutServiceInternal.pinShortcuts(callingPackage, packageName,
|
||||
ids, user.getIdentifier());
|
||||
mShortcutServiceInternal.pinShortcuts(getCallingUserId(),
|
||||
callingPackage, packageName, ids, user.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -376,8 +376,8 @@ public class LauncherAppsService extends SystemService {
|
||||
UserHandle user) {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
|
||||
return mShortcutServiceInternal.getShortcutIconResId(callingPackage, shortcut,
|
||||
user.getIdentifier());
|
||||
return mShortcutServiceInternal.getShortcutIconResId(getCallingUserId(),
|
||||
callingPackage, shortcut, user.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -385,25 +385,31 @@ public class LauncherAppsService extends SystemService {
|
||||
UserHandle user) {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
|
||||
return mShortcutServiceInternal.getShortcutIconFd(callingPackage, shortcut,
|
||||
user.getIdentifier());
|
||||
return mShortcutServiceInternal.getShortcutIconFd(getCallingUserId(),
|
||||
callingPackage, shortcut, user.getIdentifier());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasShortcutHostPermission(String callingPackage) throws RemoteException {
|
||||
public boolean hasShortcutHostPermission(String callingPackage) {
|
||||
verifyCallingPackage(callingPackage);
|
||||
return mShortcutServiceInternal.hasShortcutHostPermission(callingPackage,
|
||||
getCallingUserId());
|
||||
return mShortcutServiceInternal.hasShortcutHostPermission(getCallingUserId(),
|
||||
callingPackage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startShortcut(String callingPackage, String packageName, String shortcutId,
|
||||
Rect sourceBounds, Bundle startActivityOptions, UserHandle user)
|
||||
throws RemoteException {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
Rect sourceBounds, Bundle startActivityOptions, UserHandle user) {
|
||||
verifyCallingPackage(callingPackage);
|
||||
ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
|
||||
|
||||
final Intent intent = mShortcutServiceInternal.createShortcutIntent(callingPackage,
|
||||
packageName, shortcutId, user.getIdentifier());
|
||||
// Even without the permission, pinned shortcuts are always launchable.
|
||||
if (!mShortcutServiceInternal.isPinnedByCaller(getCallingUserId(),
|
||||
callingPackage, packageName, shortcutId, user.getIdentifier())) {
|
||||
ensureShortcutPermission(callingPackage, user);
|
||||
}
|
||||
|
||||
final Intent intent = mShortcutServiceInternal.createShortcutIntent(getCallingUserId(),
|
||||
callingPackage, packageName, shortcutId, user.getIdentifier());
|
||||
if (intent == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -713,9 +719,11 @@ public class LauncherAppsService extends SystemService {
|
||||
BroadcastCookie cookie = (BroadcastCookie) mListeners.getBroadcastCookie(i);
|
||||
if (!isEnabledProfileOf(user, cookie.user, "onShortcutChanged")) continue;
|
||||
|
||||
final int launcherUserId = cookie.user.getIdentifier();
|
||||
|
||||
// Make sure the caller has the permission.
|
||||
if (!mShortcutServiceInternal.hasShortcutHostPermission(cookie.packageName,
|
||||
cookie.user.getIdentifier())) {
|
||||
if (!mShortcutServiceInternal.hasShortcutHostPermission(
|
||||
launcherUserId, cookie.packageName)) {
|
||||
continue;
|
||||
}
|
||||
// Each launcher has a different set of pinned shortcuts, so we need to do a
|
||||
@@ -723,8 +731,9 @@ public class LauncherAppsService extends SystemService {
|
||||
// (As of now, only one launcher has the permission at a time, so it's bit
|
||||
// moot, but we may change the permission model eventually.)
|
||||
final List<ShortcutInfo> list =
|
||||
mShortcutServiceInternal.getShortcuts(cookie.packageName,
|
||||
/* changedSince= */ 0, packageName, /* component= */ null,
|
||||
mShortcutServiceInternal.getShortcuts(launcherUserId,
|
||||
cookie.packageName,
|
||||
/* changedSince= */ 0, packageName, /* component= */ null,
|
||||
ShortcutQuery.FLAG_GET_KEY_FIELDS_ONLY
|
||||
| ShortcutQuery.FLAG_GET_PINNED
|
||||
| ShortcutQuery.FLAG_GET_DYNAMIC
|
||||
|
||||
@@ -40,6 +40,7 @@ class ShortcutLauncher implements ShortcutPackageItem {
|
||||
private static final String TAG_PACKAGE = "package";
|
||||
private static final String TAG_PIN = "pin";
|
||||
|
||||
private static final String ATTR_LAUNCHER_USER_ID = "launcher-user";
|
||||
private static final String ATTR_VALUE = "value";
|
||||
private static final String ATTR_PACKAGE_NAME = "package-name";
|
||||
|
||||
@@ -49,14 +50,19 @@ class ShortcutLauncher implements ShortcutPackageItem {
|
||||
@NonNull
|
||||
private final String mPackageName;
|
||||
|
||||
@UserIdInt
|
||||
private final int mLauncherUserId;
|
||||
|
||||
/**
|
||||
* Package name -> IDs.
|
||||
*/
|
||||
final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
|
||||
|
||||
ShortcutLauncher(@UserIdInt int userId, @NonNull String packageName) {
|
||||
ShortcutLauncher(@UserIdInt int userId, @NonNull String packageName,
|
||||
@UserIdInt int launcherUserId) {
|
||||
mUserId = userId;
|
||||
mPackageName = packageName;
|
||||
mLauncherUserId = launcherUserId;
|
||||
}
|
||||
|
||||
@UserIdInt
|
||||
@@ -64,6 +70,11 @@ class ShortcutLauncher implements ShortcutPackageItem {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
@UserIdInt
|
||||
public int getLauncherUserId() {
|
||||
return mLauncherUserId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getPackageName() {
|
||||
return mPackageName;
|
||||
@@ -120,8 +131,8 @@ class ShortcutLauncher implements ShortcutPackageItem {
|
||||
}
|
||||
|
||||
out.startTag(null, TAG_ROOT);
|
||||
ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
|
||||
mPackageName);
|
||||
ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME, mPackageName);
|
||||
ShortcutService.writeAttr(out, ATTR_LAUNCHER_USER_ID, mLauncherUserId);
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
out.startTag(null, TAG_PACKAGE);
|
||||
@@ -142,12 +153,15 @@ class ShortcutLauncher implements ShortcutPackageItem {
|
||||
/**
|
||||
* Load.
|
||||
*/
|
||||
public static ShortcutLauncher loadFromXml(XmlPullParser parser, int userId)
|
||||
public static ShortcutLauncher loadFromXml(XmlPullParser parser, int ownerUserId)
|
||||
throws IOException, XmlPullParserException {
|
||||
final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
|
||||
ATTR_PACKAGE_NAME);
|
||||
final int launcherUserId = ShortcutService.parseIntAttribute(parser,
|
||||
ATTR_LAUNCHER_USER_ID, ownerUserId);
|
||||
|
||||
final ShortcutLauncher ret = new ShortcutLauncher(userId, launcherPackageName);
|
||||
final ShortcutLauncher ret = new ShortcutLauncher(launcherUserId, launcherPackageName,
|
||||
launcherUserId);
|
||||
|
||||
ArraySet<String> ids = null;
|
||||
final int outerDepth = parser.getDepth();
|
||||
@@ -184,6 +198,8 @@ class ShortcutLauncher implements ShortcutPackageItem {
|
||||
pw.print(prefix);
|
||||
pw.print("Launcher: ");
|
||||
pw.print(mPackageName);
|
||||
pw.print(" UserId: ");
|
||||
pw.print(mLauncherUserId);
|
||||
pw.println();
|
||||
|
||||
final int size = mPinnedShortcuts.size();
|
||||
|
||||
@@ -104,6 +104,9 @@ class ShortcutPackage implements ShortcutPackageItem {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note this does *not* provide a correct view to the calling launcher.
|
||||
*/
|
||||
@Nullable
|
||||
public ShortcutInfo findShortcutById(String id) {
|
||||
return mShortcuts.get(id);
|
||||
@@ -229,8 +232,8 @@ class ShortcutPackage implements ShortcutPackageItem {
|
||||
}
|
||||
|
||||
// Then, for the pinned set for each launcher, set the pin flag one by one.
|
||||
final ArrayMap<String, ShortcutLauncher> launchers =
|
||||
s.getUserShortcutsLocked(mUserId).getLaunchers();
|
||||
final ArrayMap<ShortcutUser.PackageWithUser, ShortcutLauncher> launchers =
|
||||
s.getUserShortcutsLocked(mUserId).getAllLaunchers();
|
||||
|
||||
for (int l = launchers.size() - 1; l >= 0; l--) {
|
||||
final ShortcutLauncher launcherShortcuts = launchers.valueAt(l);
|
||||
@@ -300,13 +303,25 @@ class ShortcutPackage implements ShortcutPackageItem {
|
||||
/**
|
||||
* Find all shortcuts that match {@code query}.
|
||||
*/
|
||||
public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
|
||||
@Nullable Predicate<ShortcutInfo> query, int cloneFlag) {
|
||||
findAll(s, result, query, cloneFlag, null, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all shortcuts that match {@code query}.
|
||||
*
|
||||
* This will also provide a "view" for each launcher -- a non-dynamic shortcut that's not pinned
|
||||
* by the calling launcher will not be included in the result, and also "isPinned" will be
|
||||
* adjusted for the caller too.
|
||||
*/
|
||||
public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
|
||||
@Nullable Predicate<ShortcutInfo> query, int cloneFlag,
|
||||
@Nullable String callingLauncher) {
|
||||
@Nullable String callingLauncher, int launcherUserId) {
|
||||
|
||||
// Set of pinned shortcuts by the calling launcher.
|
||||
final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
|
||||
: s.getLauncherShortcuts(callingLauncher, mUserId)
|
||||
: s.getLauncherShortcuts(callingLauncher, mUserId, launcherUserId)
|
||||
.getPinnedShortcutIds(mPackageName);
|
||||
|
||||
for (int i = 0; i < mShortcuts.size(); i++) {
|
||||
|
||||
@@ -48,6 +48,7 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
private static final String TAG = ShortcutService.TAG;
|
||||
|
||||
static final String TAG_ROOT = "package-info";
|
||||
private static final String ATTR_USER_ID = "user";
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String ATTR_VERSION = "version";
|
||||
private static final String ATTR_SHADOW = "shadow";
|
||||
@@ -55,11 +56,8 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
private static final String TAG_SIGNATURE = "signature";
|
||||
private static final String ATTR_SIGNATURE_HASH = "hash";
|
||||
|
||||
public interface ShortcutPackageInfoHolder {
|
||||
ShortcutPackageInfo getShortcutPackageInfo();
|
||||
}
|
||||
|
||||
private final String mPackageName;
|
||||
private final int mUserId;
|
||||
|
||||
/**
|
||||
* When true, this package information was restored from the previous device, and the app hasn't
|
||||
@@ -69,12 +67,13 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
private int mVersionCode;
|
||||
private ArrayList<byte[]> mSigHashes;
|
||||
|
||||
private ShortcutPackageInfo(String packageName, int versionCode, ArrayList<byte[]> sigHashes,
|
||||
boolean isShadow) {
|
||||
private ShortcutPackageInfo(String packageName, int userId,
|
||||
int versionCode, ArrayList<byte[]> sigHashes, boolean isShadow) {
|
||||
mPackageName = Preconditions.checkNotNull(packageName);
|
||||
mUserId = userId;
|
||||
mVersionCode = versionCode;
|
||||
mIsShadow = isShadow;
|
||||
mSigHashes = sigHashes;
|
||||
mPackageName = Preconditions.checkNotNull(packageName);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -82,6 +81,10 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
public int getUserId() {
|
||||
return mUserId;
|
||||
}
|
||||
|
||||
public boolean isShadow() {
|
||||
return mIsShadow;
|
||||
}
|
||||
@@ -197,7 +200,7 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
Slog.e(TAG, "Can't get signatures: package=" + packageName);
|
||||
return null;
|
||||
}
|
||||
final ShortcutPackageInfo ret = new ShortcutPackageInfo(packageName, pi.versionCode,
|
||||
final ShortcutPackageInfo ret = new ShortcutPackageInfo(packageName, userId, pi.versionCode,
|
||||
hashSignatureArray(pi.signatures), /* shadow=*/ false);
|
||||
|
||||
return ret;
|
||||
@@ -221,6 +224,7 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
out.startTag(null, TAG_ROOT);
|
||||
|
||||
ShortcutService.writeAttr(out, ATTR_NAME, mPackageName);
|
||||
ShortcutService.writeAttr(out, ATTR_USER_ID, mUserId);
|
||||
ShortcutService.writeAttr(out, ATTR_VERSION, mVersionCode);
|
||||
ShortcutService.writeAttr(out, ATTR_SHADOW, mIsShadow);
|
||||
|
||||
@@ -232,10 +236,11 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
out.endTag(null, TAG_ROOT);
|
||||
}
|
||||
|
||||
public static ShortcutPackageInfo loadFromXml(XmlPullParser parser)
|
||||
public static ShortcutPackageInfo loadFromXml(XmlPullParser parser, int ownerUserId)
|
||||
throws IOException, XmlPullParserException {
|
||||
|
||||
final String packageName = ShortcutService.parseStringAttribute(parser, ATTR_NAME);
|
||||
final int userId = ShortcutService.parseIntAttribute(parser, ATTR_USER_ID, ownerUserId);
|
||||
final int versionCode = ShortcutService.parseIntAttribute(parser, ATTR_VERSION);
|
||||
final boolean shadow = ShortcutService.parseBooleanAttribute(parser, ATTR_SHADOW);
|
||||
|
||||
@@ -261,7 +266,7 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
}
|
||||
throw ShortcutService.throwForInvalidTag(depth, tag);
|
||||
}
|
||||
return new ShortcutPackageInfo(packageName, versionCode, hashes, shadow);
|
||||
return new ShortcutPackageInfo(packageName, userId, versionCode, hashes, shadow);
|
||||
}
|
||||
|
||||
public void dump(ShortcutService s, PrintWriter pw, String prefix) {
|
||||
@@ -272,6 +277,11 @@ class ShortcutPackageInfo implements ShortcutPackageItem {
|
||||
pw.print(mPackageName);
|
||||
pw.println();
|
||||
|
||||
pw.print(prefix);
|
||||
pw.print(" User: ");
|
||||
pw.print(mUserId);
|
||||
pw.println();
|
||||
|
||||
pw.print(prefix);
|
||||
pw.print(" IsShadow: ");
|
||||
pw.print(mIsShadow);
|
||||
|
||||
@@ -31,7 +31,6 @@ import android.content.pm.LauncherApps;
|
||||
import android.content.pm.LauncherApps.ShortcutQuery;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.ResolveInfo;
|
||||
@@ -78,6 +77,7 @@ import com.android.internal.util.FastXmlSerializer;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.pm.ShortcutUser.PackageWithUser;
|
||||
|
||||
import libcore.io.IoUtils;
|
||||
|
||||
@@ -104,14 +104,9 @@ import java.util.function.Predicate;
|
||||
*
|
||||
* - Default launcher check does take a few ms. Worth caching.
|
||||
*
|
||||
* - Allow non-default launcher to start pinned shortcuts. (but not dynamic.)
|
||||
* - Don't backup launcher from different profile.
|
||||
*
|
||||
* - Extract the user/package/launcher classes to their own files. Maybe rename so they all have
|
||||
* the same "Shortcut" prefix.
|
||||
*
|
||||
* - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
|
||||
* -> Need to scan all packages when a user starts too.
|
||||
* -> Clear data -> remove all dynamic? but not the pinned?
|
||||
* - Clear data -> remove all dynamic? but not the pinned?
|
||||
*
|
||||
* - Scan and remove orphan bitmaps (just in case).
|
||||
*
|
||||
@@ -455,16 +450,24 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
return (int) parseLongAttribute(parser, attribute);
|
||||
}
|
||||
|
||||
static int parseIntAttribute(XmlPullParser parser, String attribute, int def) {
|
||||
return (int) parseLongAttribute(parser, attribute, def);
|
||||
}
|
||||
|
||||
static long parseLongAttribute(XmlPullParser parser, String attribute) {
|
||||
return parseLongAttribute(parser, attribute, 0);
|
||||
}
|
||||
|
||||
static long parseLongAttribute(XmlPullParser parser, String attribute, long def) {
|
||||
final String value = parseStringAttribute(parser, attribute);
|
||||
if (TextUtils.isEmpty(value)) {
|
||||
return 0;
|
||||
return def;
|
||||
}
|
||||
try {
|
||||
return Long.parseLong(value);
|
||||
} catch (NumberFormatException e) {
|
||||
Slog.e(TAG, "Error parsing long " + value);
|
||||
return 0;
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,8 +828,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
@GuardedBy("mLock")
|
||||
@NonNull
|
||||
ShortcutLauncher getLauncherShortcuts(
|
||||
@NonNull String packageName, @UserIdInt int userId) {
|
||||
return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName);
|
||||
@NonNull String packageName, @UserIdInt int userId, @UserIdInt int launcherUserId) {
|
||||
return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName, launcherUserId);
|
||||
}
|
||||
|
||||
// === Caller validation ===
|
||||
@@ -1324,8 +1327,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
|
||||
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
|
||||
|
||||
getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags,
|
||||
/* callingLauncher= */ null);
|
||||
getPackageShortcutsLocked(packageName, userId).findAll(this, ret, query, cloneFlags);
|
||||
|
||||
return new ParceledListSlice<>(ret);
|
||||
}
|
||||
@@ -1463,22 +1465,26 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
// === House keeping ===
|
||||
|
||||
@VisibleForTesting
|
||||
void cleanUpPackageLocked(String packageName, int userId) {
|
||||
final boolean wasUserLoaded = isUserLoadedLocked(userId);
|
||||
void cleanUpPackageLocked(String packageName, int owningUserId, int packageUserId) {
|
||||
final boolean wasUserLoaded = isUserLoadedLocked(owningUserId);
|
||||
|
||||
final ShortcutUser mUser = getUserShortcutsLocked(userId);
|
||||
final ShortcutUser mUser = getUserShortcutsLocked(owningUserId);
|
||||
boolean doNotify = false;
|
||||
|
||||
// First, remove the package from the package list (if the package is a publisher).
|
||||
if (mUser.getPackages().remove(packageName) != null) {
|
||||
doNotify = true;
|
||||
if (packageUserId == owningUserId) {
|
||||
if (mUser.getPackages().remove(packageName) != null) {
|
||||
doNotify = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Also remove from the launcher list (if the package is a launcher).
|
||||
mUser.getLaunchers().remove(packageName);
|
||||
mUser.removeLauncher(packageUserId, packageName);
|
||||
|
||||
// Then remove pinned shortcuts from all launchers.
|
||||
for (int i = mUser.getLaunchers().size() - 1; i >= 0; i--) {
|
||||
mUser.getLaunchers().valueAt(i).cleanUpPackage(packageName);
|
||||
final ArrayMap<PackageWithUser, ShortcutLauncher> launchers = mUser.getAllLaunchers();
|
||||
for (int i = launchers.size() - 1; i >= 0; i--) {
|
||||
launchers.valueAt(i).cleanUpPackage(packageName);
|
||||
}
|
||||
// Now there may be orphan shortcuts because we removed pinned shortucts at the previous
|
||||
// step. Remove them too.
|
||||
@@ -1487,17 +1493,17 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
}
|
||||
|
||||
// Remove the package info too.
|
||||
mUser.getPackageInfos().remove(packageName);
|
||||
mUser.removePackageInfo(packageUserId, packageName);
|
||||
|
||||
scheduleSaveUser(userId);
|
||||
scheduleSaveUser(owningUserId);
|
||||
|
||||
if (doNotify) {
|
||||
notifyListeners(packageName, userId);
|
||||
notifyListeners(packageName, owningUserId);
|
||||
}
|
||||
|
||||
if (!wasUserLoaded) {
|
||||
// Note this will execute the scheduled save.
|
||||
unloadUserLocked(userId);
|
||||
unloadUserLocked(owningUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1506,7 +1512,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
*/
|
||||
private class LocalService extends ShortcutServiceInternal {
|
||||
@Override
|
||||
public List<ShortcutInfo> getShortcuts(
|
||||
public List<ShortcutInfo> getShortcuts(int launcherUserId,
|
||||
@NonNull String callingPackage, long changedSince,
|
||||
@Nullable String packageName, @Nullable ComponentName componentName,
|
||||
int queryFlags, int userId) {
|
||||
@@ -1518,14 +1524,14 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
|
||||
synchronized (mLock) {
|
||||
if (packageName != null) {
|
||||
getShortcutsInnerLocked(
|
||||
getShortcutsInnerLocked(launcherUserId,
|
||||
callingPackage, packageName, changedSince,
|
||||
componentName, queryFlags, userId, ret, cloneFlag);
|
||||
} else {
|
||||
final ArrayMap<String, ShortcutPackage> packages =
|
||||
getUserShortcutsLocked(userId).getPackages();
|
||||
for (int i = packages.size() - 1; i >= 0; i--) {
|
||||
getShortcutsInnerLocked(
|
||||
getShortcutsInnerLocked(launcherUserId,
|
||||
callingPackage, packages.keyAt(i), changedSince,
|
||||
componentName, queryFlags, userId, ret, cloneFlag);
|
||||
}
|
||||
@@ -1534,7 +1540,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void getShortcutsInnerLocked(@NonNull String callingPackage,
|
||||
private void getShortcutsInnerLocked(int launcherUserId, @NonNull String callingPackage,
|
||||
@Nullable String packageName,long changedSince,
|
||||
@Nullable ComponentName componentName, int queryFlags,
|
||||
int userId, ArrayList<ShortcutInfo> ret, int cloneFlag) {
|
||||
@@ -1554,11 +1560,11 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
((queryFlags & ShortcutQuery.FLAG_GET_PINNED) != 0)
|
||||
&& si.isPinned();
|
||||
return matchDynamic || matchPinned;
|
||||
}, cloneFlag, callingPackage);
|
||||
}, cloneFlag, callingPackage, launcherUserId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ShortcutInfo> getShortcutInfo(
|
||||
public List<ShortcutInfo> getShortcutInfo(int launcherUserId,
|
||||
@NonNull String callingPackage,
|
||||
@NonNull String packageName, @Nullable List<String> ids, int userId) {
|
||||
// Calling permission must be checked by LauncherAppsImpl.
|
||||
@@ -1570,13 +1576,41 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
getPackageShortcutsLocked(packageName, userId).findAll(
|
||||
ShortcutService.this, ret,
|
||||
(ShortcutInfo si) -> idSet.contains(si.getId()),
|
||||
ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage);
|
||||
ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER, callingPackage, launcherUserId);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pinShortcuts(@NonNull String callingPackage, @NonNull String packageName,
|
||||
public boolean isPinnedByCaller(int launcherUserId, @NonNull String callingPackage,
|
||||
@NonNull String packageName, @NonNull String shortcutId, int userId) {
|
||||
Preconditions.checkStringNotEmpty(packageName, "packageName");
|
||||
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
|
||||
|
||||
synchronized (mLock) {
|
||||
final ShortcutInfo si = getShortcutInfoLocked(
|
||||
launcherUserId, callingPackage, packageName, shortcutId, userId);
|
||||
return si != null && si.isPinned();
|
||||
}
|
||||
}
|
||||
|
||||
public ShortcutInfo getShortcutInfoLocked(
|
||||
int launcherUserId, @NonNull String callingPackage,
|
||||
@NonNull String packageName, @NonNull String shortcutId, int userId) {
|
||||
Preconditions.checkStringNotEmpty(packageName, "packageName");
|
||||
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId");
|
||||
|
||||
final ArrayList<ShortcutInfo> list = new ArrayList<>(1);
|
||||
getPackageShortcutsLocked(packageName, userId).findAll(
|
||||
ShortcutService.this, list,
|
||||
(ShortcutInfo si) -> shortcutId.equals(si.getId()),
|
||||
/* clone flags=*/ 0, callingPackage, launcherUserId);
|
||||
return list.size() == 0 ? null : list.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pinShortcuts(int launcherUserId,
|
||||
@NonNull String callingPackage, @NonNull String packageName,
|
||||
@NonNull List<String> shortcutIds, int userId) {
|
||||
// Calling permission must be checked by LauncherAppsImpl.
|
||||
Preconditions.checkStringNotEmpty(packageName, "packageName");
|
||||
@@ -1584,26 +1618,31 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
|
||||
synchronized (mLock) {
|
||||
getUserShortcutsLocked(userId).ensurePackageInfo(
|
||||
ShortcutService.this, callingPackage, userId);
|
||||
ShortcutService.this, callingPackage, launcherUserId);
|
||||
|
||||
getLauncherShortcuts(callingPackage, userId).pinShortcuts(
|
||||
getLauncherShortcuts(callingPackage, userId, launcherUserId).pinShortcuts(
|
||||
ShortcutService.this, packageName, shortcutIds);
|
||||
}
|
||||
userPackageChanged(packageName, userId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent createShortcutIntent(@NonNull String callingPackage,
|
||||
public Intent createShortcutIntent(int launcherUserId,
|
||||
@NonNull String callingPackage,
|
||||
@NonNull String packageName, @NonNull String shortcutId, int userId) {
|
||||
// Calling permission must be checked by LauncherAppsImpl.
|
||||
Preconditions.checkStringNotEmpty(packageName, "packageName can't be empty");
|
||||
Preconditions.checkStringNotEmpty(shortcutId, "shortcutId can't be empty");
|
||||
|
||||
synchronized (mLock) {
|
||||
final ShortcutInfo fullShortcut =
|
||||
getPackageShortcutsLocked(packageName, userId)
|
||||
.findShortcutById(shortcutId);
|
||||
return fullShortcut == null ? null : fullShortcut.getIntent();
|
||||
// Make sure the shortcut is actually visible to the launcher.
|
||||
final ShortcutInfo si = getShortcutInfoLocked(
|
||||
launcherUserId, callingPackage, packageName, shortcutId, userId);
|
||||
// "si == null" should suffice here, but check the flags too just to make sure.
|
||||
if (si == null || !(si.isDynamic() || si.isPinned())) {
|
||||
return null;
|
||||
}
|
||||
return si.getIntent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1615,7 +1654,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShortcutIconResId(@NonNull String callingPackage,
|
||||
public int getShortcutIconResId(int launcherUserId,
|
||||
@NonNull String callingPackage,
|
||||
@NonNull ShortcutInfo shortcut, int userId) {
|
||||
Preconditions.checkNotNull(shortcut, "shortcut");
|
||||
|
||||
@@ -1628,7 +1668,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ParcelFileDescriptor getShortcutIconFd(@NonNull String callingPackage,
|
||||
public ParcelFileDescriptor getShortcutIconFd(int launcherUserId,
|
||||
@NonNull String callingPackage,
|
||||
@NonNull ShortcutInfo shortcutIn, int userId) {
|
||||
Preconditions.checkNotNull(shortcutIn, "shortcut");
|
||||
|
||||
@@ -1654,8 +1695,9 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasShortcutHostPermission(@NonNull String callingPackage, int userId) {
|
||||
return ShortcutService.this.hasShortcutHostPermission(callingPackage, userId);
|
||||
public boolean hasShortcutHostPermission(int launcherUserId,
|
||||
@NonNull String callingPackage) {
|
||||
return ShortcutService.this.hasShortcutHostPermission(callingPackage, launcherUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1684,28 +1726,31 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
* Called when a user is unlocked. Check all known packages still exist, and otherwise
|
||||
* perform cleanup.
|
||||
*/
|
||||
private void cleanupGonePackages(@UserIdInt int userId) {
|
||||
@VisibleForTesting
|
||||
void cleanupGonePackages(@UserIdInt int userId) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "cleanupGonePackages() userId=" + userId);
|
||||
}
|
||||
ArrayList<String> gonePackages = null;
|
||||
ArrayList<PackageWithUser> gonePackages = null;
|
||||
|
||||
final ShortcutUser user = getUserShortcutsLocked(userId);
|
||||
final ArrayMap<String, ShortcutPackageInfo> infos = user.getPackageInfos();
|
||||
for (int i = infos.size() -1; i >= 0; i--) {
|
||||
final ShortcutPackageInfo info = infos.valueAt(i);
|
||||
if (info.isShadow()) {
|
||||
continue;
|
||||
synchronized (mLock) {
|
||||
final ShortcutUser user = getUserShortcutsLocked(userId);
|
||||
final ArrayMap<PackageWithUser, ShortcutPackageInfo> infos = user.getAllPackageInfos();
|
||||
for (int i = infos.size() -1; i >= 0; i--) {
|
||||
final ShortcutPackageInfo info = infos.valueAt(i);
|
||||
if (info.isShadow()) {
|
||||
continue;
|
||||
}
|
||||
if (isPackageInstalled(info.getPackageName(), info.getUserId())) {
|
||||
continue;
|
||||
}
|
||||
gonePackages = ArrayUtils.add(gonePackages,
|
||||
PackageWithUser.of(info.getUserId(), info.getPackageName()));
|
||||
}
|
||||
if (isPackageInstalled(info.getPackageName(), userId)) {
|
||||
continue;
|
||||
}
|
||||
gonePackages = ArrayUtils.add(gonePackages, info.getPackageName());
|
||||
}
|
||||
if (gonePackages != null) {
|
||||
synchronized (mLock) {
|
||||
if (gonePackages != null) {
|
||||
for (int i = gonePackages.size() - 1; i >= 0; i--) {
|
||||
cleanUpPackageLocked(gonePackages.get(i), userId);
|
||||
final PackageWithUser pu = gonePackages.get(i);
|
||||
cleanUpPackageLocked(pu.packageName, userId, pu.userId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1716,9 +1761,8 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
Slog.d(TAG, String.format("handlePackageAdded: %s user=%d", packageName, userId));
|
||||
}
|
||||
synchronized (mLock) {
|
||||
final ArrayMap<String, ShortcutPackageInfo> infos =
|
||||
getUserShortcutsLocked(userId).getPackageInfos();
|
||||
final ShortcutPackageInfo existing = infos.get(packageName);
|
||||
final ShortcutPackageInfo existing = getUserShortcutsLocked(userId)
|
||||
.getPackageInfo(userId, packageName);
|
||||
|
||||
if (existing != null && existing.isShadow()) {
|
||||
Slog.w(TAG, "handlePackageAdded: TODO Restore not implemented");
|
||||
@@ -1732,7 +1776,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
}
|
||||
synchronized (mLock) {
|
||||
final ShortcutPackageInfo spi =
|
||||
getUserShortcutsLocked(userId).getPackageInfos().get(packageName);
|
||||
getUserShortcutsLocked(userId).getPackageInfo(userId, packageName);
|
||||
if (spi != null) {
|
||||
spi.refreshAndSave(this, userId);
|
||||
}
|
||||
@@ -1744,7 +1788,7 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
Slog.d(TAG, String.format("handlePackageRemoved: %s user=%d", packageName, userId));
|
||||
}
|
||||
synchronized (mLock) {
|
||||
cleanUpPackageLocked(packageName, userId);
|
||||
cleanUpPackageLocked(packageName, userId, userId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2161,11 +2205,16 @@ public class ShortcutService extends IShortcutService.Stub {
|
||||
|
||||
@VisibleForTesting
|
||||
ShortcutPackageInfo getPackageInfoForTest(String packageName, int userId) {
|
||||
return getPackageInfoForTest(packageName, userId, userId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
ShortcutPackageInfo getPackageInfoForTest(String packageName, int userId, int packageUserId) {
|
||||
synchronized (mLock) {
|
||||
final ShortcutUser user = mUsers.get(userId);
|
||||
if (user == null) return null;
|
||||
|
||||
return user.getPackageInfos().get(packageName);
|
||||
return user.getPackageInfo(packageUserId, packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ import android.content.ComponentName;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
import libcore.util.Objects;
|
||||
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
@@ -41,14 +43,48 @@ class ShortcutUser {
|
||||
|
||||
private static final String ATTR_VALUE = "value";
|
||||
|
||||
static final class PackageWithUser {
|
||||
final int userId;
|
||||
final String packageName;
|
||||
|
||||
private PackageWithUser(int userId, String packageName) {
|
||||
this.userId = userId;
|
||||
this.packageName = Preconditions.checkNotNull(packageName);
|
||||
}
|
||||
|
||||
public static PackageWithUser of(int launcherUserId, String packageName) {
|
||||
return new PackageWithUser(launcherUserId, packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return packageName.hashCode() ^ userId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof PackageWithUser)) {
|
||||
return false;
|
||||
}
|
||||
final PackageWithUser that = (PackageWithUser) obj;
|
||||
|
||||
return userId == that.userId && packageName.equals(that.packageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{Launcher: %d, %s}", userId, packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@UserIdInt
|
||||
final int mUserId;
|
||||
|
||||
private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>();
|
||||
|
||||
private final ArrayMap<String, ShortcutLauncher> mLaunchers = new ArrayMap<>();
|
||||
private final ArrayMap<PackageWithUser, ShortcutLauncher> mLaunchers = new ArrayMap<>();
|
||||
|
||||
private final ArrayMap<String, ShortcutPackageInfo> mPackageInfos = new ArrayMap<>();
|
||||
private final ArrayMap<PackageWithUser, ShortcutPackageInfo> mPackageInfos = new ArrayMap<>();
|
||||
|
||||
private ComponentName mLauncherComponent;
|
||||
|
||||
@@ -60,14 +96,41 @@ class ShortcutUser {
|
||||
return mPackages;
|
||||
}
|
||||
|
||||
public ArrayMap<String, ShortcutLauncher> getLaunchers() {
|
||||
public ArrayMap<PackageWithUser, ShortcutLauncher> getAllLaunchers() {
|
||||
return mLaunchers;
|
||||
}
|
||||
|
||||
public ArrayMap<String, ShortcutPackageInfo> getPackageInfos() {
|
||||
public ShortcutLauncher getLauncher(@UserIdInt int userId, @NonNull String packageName) {
|
||||
return mLaunchers.get(PackageWithUser.of(userId, packageName));
|
||||
}
|
||||
|
||||
public void addLauncher(ShortcutLauncher launcher) {
|
||||
mLaunchers.put(PackageWithUser.of(launcher.getUserId(), launcher.getPackageName()),
|
||||
launcher);
|
||||
}
|
||||
|
||||
public ShortcutLauncher removeLauncher(
|
||||
@UserIdInt int userId, @NonNull String packageName) {
|
||||
return mLaunchers.remove(PackageWithUser.of(userId, packageName));
|
||||
}
|
||||
|
||||
public ArrayMap<PackageWithUser, ShortcutPackageInfo> getAllPackageInfos() {
|
||||
return mPackageInfos;
|
||||
}
|
||||
|
||||
public ShortcutPackageInfo getPackageInfo(@UserIdInt int userId, @NonNull String packageName) {
|
||||
return mPackageInfos.get(PackageWithUser.of(userId, packageName));
|
||||
}
|
||||
|
||||
public void addPackageInfo(ShortcutPackageInfo spi) {
|
||||
mPackageInfos.put(PackageWithUser.of(spi.getUserId(), spi.getPackageName()), spi);
|
||||
}
|
||||
|
||||
public ShortcutPackageInfo removePackageInfo(
|
||||
@UserIdInt int userId, @NonNull String packageName) {
|
||||
return mPackageInfos.remove(PackageWithUser.of(userId, packageName));
|
||||
}
|
||||
|
||||
public ShortcutPackage getPackageShortcuts(@NonNull String packageName) {
|
||||
ShortcutPackage ret = mPackages.get(packageName);
|
||||
if (ret == null) {
|
||||
@@ -77,17 +140,20 @@ class ShortcutUser {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName) {
|
||||
ShortcutLauncher ret = mLaunchers.get(packageName);
|
||||
public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName,
|
||||
@UserIdInt int launcherUserId) {
|
||||
final PackageWithUser key = PackageWithUser.of(launcherUserId, packageName);
|
||||
ShortcutLauncher ret = mLaunchers.get(key);
|
||||
if (ret == null) {
|
||||
ret = new ShortcutLauncher(mUserId, packageName);
|
||||
mLaunchers.put(packageName, ret);
|
||||
ret = new ShortcutLauncher(mUserId, packageName, launcherUserId);
|
||||
mLaunchers.put(key, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void ensurePackageInfo(ShortcutService s, String packageName, @UserIdInt int userId) {
|
||||
final ShortcutPackageInfo existing = mPackageInfos.get(packageName);
|
||||
final PackageWithUser key = PackageWithUser.of(userId, packageName);
|
||||
final ShortcutPackageInfo existing = mPackageInfos.get(key);
|
||||
|
||||
if (existing != null) {
|
||||
return;
|
||||
@@ -97,7 +163,7 @@ class ShortcutUser {
|
||||
}
|
||||
final ShortcutPackageInfo newSpi = ShortcutPackageInfo.generateForInstalledPackage(
|
||||
s, packageName, userId);
|
||||
mPackageInfos.put(packageName, newSpi);
|
||||
mPackageInfos.put(key, newSpi);
|
||||
s.scheduleSaveUser(mUserId);
|
||||
}
|
||||
|
||||
@@ -166,18 +232,12 @@ class ShortcutUser {
|
||||
}
|
||||
|
||||
case ShortcutLauncher.TAG_ROOT: {
|
||||
final ShortcutLauncher shortcuts =
|
||||
ShortcutLauncher.loadFromXml(parser, userId);
|
||||
|
||||
ret.getLaunchers().put(shortcuts.getPackageName(), shortcuts);
|
||||
ret.addLauncher(ShortcutLauncher.loadFromXml(parser, userId));
|
||||
continue;
|
||||
}
|
||||
|
||||
case ShortcutPackageInfo.TAG_ROOT: {
|
||||
final ShortcutPackageInfo pi =
|
||||
ShortcutPackageInfo.loadFromXml(parser);
|
||||
|
||||
ret.getPackageInfos().put(pi.getPackageName(), pi);
|
||||
ret.addPackageInfo(ShortcutPackageInfo.loadFromXml(parser, userId));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user