import android.annotation.NonNull;
import android.annotation.UserIdInt;
+import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.util.ArrayMap;
import android.util.ArraySet;
return mPinnedShortcuts.remove(PackageWithUser.of(packageUserId, packageName)) != null;
}
+ public void ensureVersionInfo() {
+ final PackageInfo pi = mShortcutUser.mService.getPackageInfoWithSignatures(
+ getPackageName(), getPackageUserId());
+ if (pi == null) {
+ Slog.w(TAG, "Package not found: " + getPackageName());
+ return;
+ }
+ getPackageInfo().updateVersionInfo(pi);
+ }
+
/**
* Persist.
*/
fromBackup ? ownerUserId
: ShortcutService.parseIntAttribute(parser, ATTR_LAUNCHER_USER_ID, ownerUserId);
- final ShortcutLauncher ret = new ShortcutLauncher(shortcutUser, launcherUserId,
+ final ShortcutLauncher ret = new ShortcutLauncher(shortcutUser, ownerUserId,
launcherPackageName, launcherUserId);
ArraySet<String> ids = null;
import android.content.pm.PackageInfo;
import android.content.pm.ShortcutInfo;
import android.content.res.Resources;
-import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.format.Formatter;
import android.util.ArrayMap;
return mPackageUid;
}
- /**
- * Called when a shortcut is about to be published. At this point we know the publisher
- * package
- * exists (as opposed to Launcher trying to fetch shortcuts from a non-existent package), so
- * we do some initialization for the package.
- */
- private void ensurePackageVersionInfo() {
- // Make sure we have the version code for the app. We need the version code in
- // handlePackageUpdated().
- if (getPackageInfo().getVersionCode() < 0) {
- final ShortcutService s = mShortcutUser.mService;
-
- final PackageInfo pi = s.getPackageInfo(getPackageName(), getOwnerUserId());
- if (pi != null) {
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("Package %s version = %d", getPackageName(),
- pi.versionCode));
- }
- getPackageInfo().updateVersionInfo(pi);
- s.scheduleSaveUser(getOwnerUserId());
- }
- }
- }
-
@Nullable
public Resources getPackageResources() {
return mShortcutUser.mService.injectGetResourcesForApplicationAsUser(
Preconditions.checkArgument(newShortcut.isEnabled(),
"add/setDynamicShortcuts() cannot publish disabled shortcuts");
- ensurePackageVersionInfo();
-
newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
import android.content.pm.PackageInfo;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.backup.BackupUtils;
import libcore.io.Base64;
return mLastUpdateTime;
}
+ /** Set {@link #mVersionCode} and {@link #mLastUpdateTime} from a {@link PackageInfo}. */
public void updateVersionInfo(@NonNull PackageInfo pi) {
if (pi != null) {
mVersionCode = pi.versionCode;
return true;
}
- public static ShortcutPackageInfo generateForInstalledPackage(
+ @VisibleForTesting
+ public static ShortcutPackageInfo generateForInstalledPackageForTest(
ShortcutService s, String packageName, @UserIdInt int packageUserId) {
final PackageInfo pi = s.getPackageInfoWithSignatures(packageName, packageUserId);
if (pi.signatures == null || pi.signatures.length == 0) {
return ret;
}
- public void refresh(ShortcutService s, ShortcutPackageItem pkg) {
+ public void refreshSignature(ShortcutService s, ShortcutPackageItem pkg) {
if (mIsShadow) {
s.wtf("Attempted to refresh package info for shadow package " + pkg.getPackageName()
+ ", user=" + pkg.getOwnerUserId());
Slog.w(TAG, "Package not found: " + pkg.getPackageName());
return;
}
- mVersionCode = pi.versionCode;
- mLastUpdateTime = pi.lastUpdateTime;
mSigHashes = BackupUtils.hashSignatureArray(pi.signatures);
}
/**
* ID of the user who actually has this package running on. For {@link ShortcutPackage},
* this is the same thing as {@link #getOwnerUserId}, but if it's a {@link ShortcutLauncher} and
- * {@link #getOwnerUserId} is of a work profile, then this ID could be the user who owns the
- * profile.
+ * {@link #getOwnerUserId} is of work profile, then this ID is of the primary user.
*/
public int getPackageUserId() {
return mPackageUserId;
return mPackageInfo;
}
- public void refreshPackageInfoAndSave() {
+ public void refreshPackageSignatureAndSave() {
if (mPackageInfo.isShadow()) {
return; // Don't refresh for shadow user.
}
final ShortcutService s = mShortcutUser.mService;
- mPackageInfo.refresh(s, this);
+ mPackageInfo.refreshSignature(s, this);
s.scheduleSaveUser(getOwnerUserId());
}
}
}
- /** Return the per-user per-package state. */
+ /**
+ * Return the per-user per-package state. If the caller is a publisher, use
+ * {@link #getPackageShortcutsForPublisherLocked} instead.
+ */
@GuardedBy("mLock")
@NonNull
ShortcutPackage getPackageShortcutsLocked(
return getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
}
+ /** Return the per-user per-package state. Use this when the caller is a publisher. */
+ @GuardedBy("mLock")
+ @NonNull
+ ShortcutPackage getPackageShortcutsForPublisherLocked(
+ @NonNull String packageName, @UserIdInt int userId) {
+ final ShortcutPackage ret = getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
+ ret.getUser().onCalledByPublisher(packageName);
+ return ret;
+ }
+
@GuardedBy("mLock")
@NonNull
ShortcutLauncher getLauncherShortcutsLocked(
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncluded(newShortcuts);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.ensureImmutableShortcutsNotIncludedWithIds((List<String>) shortcutIds);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.deleteAllDynamicShortcuts();
}
packageShortcutsChanged(packageName, userId);
final ArrayList<ShortcutInfo> ret = new ArrayList<>();
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
ps.findAll(ret, query, cloneFlags);
return new ParceledListSlice<>(ret);
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
return mMaxUpdatesPerInterval - ps.getApiCallCount();
}
}
synchronized (mLock) {
throwIfUserLockedL(userId);
- final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
- ps.getUser().onCalledByPublisher(packageName);
+ final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
if (ps.findShortcutById(shortcutId) == null) {
Log.w(TAG, String.format("reportShortcutUsed: package %s doesn't have shortcut %s",
return null;
}
- user.forAllPackageItems(spi -> spi.refreshPackageInfoAndSave());
+ // Update the signatures for all packages.
+ user.forAllPackageItems(spi -> spi.refreshPackageSignatureAndSave());
+
+ // Set the version code for the launchers.
+ // We shouldn't do this for publisher packages, because we don't want to update the
+ // version code without rescanning the manifest.
+ user.forAllLaunchers(launcher -> launcher.ensureVersionInfo());
+
+ // Save to the filesystem.
+ scheduleSaveUser(userId);
+ saveDirtyInfo();
- // Then save.
+ // Then create the backup payload.
final ByteArrayOutputStream os = new ByteArrayOutputStream(32 * 1024);
try {
saveUserInternalLocked(userId, os, /* forBackup */ true);
addPackage(CALLING_PACKAGE_1, CALLING_UID_1, 10, "sig1");
addPackage(CALLING_PACKAGE_2, CALLING_UID_1, 10, "sig1", "sig2");
- final ShortcutPackageInfo spi1 = ShortcutPackageInfo.generateForInstalledPackage(
+ final ShortcutPackageInfo spi1 = ShortcutPackageInfo.generateForInstalledPackageForTest(
mService, CALLING_PACKAGE_1, USER_0);
- final ShortcutPackageInfo spi2 = ShortcutPackageInfo.generateForInstalledPackage(
+ final ShortcutPackageInfo spi2 = ShortcutPackageInfo.generateForInstalledPackageForTest(
mService, CALLING_PACKAGE_2, USER_0);
checkCanRestoreTo(true, spi1, 10, "sig1");
buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_P0);
});
});
+ // Check the user-IDs.
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getOwnerUserId());
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getPackageUserId());
+ assertEquals(USER_P0,
+ mService.getUserShortcutsLocked(USER_P0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getOwnerUserId());
+ assertEquals(USER_P0,
+ mService.getUserShortcutsLocked(USER_P0).getPackageShortcuts(CALLING_PACKAGE_1)
+ .getPackageUserId());
+
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getOwnerUserId());
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getPackageUserId());
+ assertEquals(USER_P0,
+ mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getOwnerUserId());
+ assertEquals(USER_0,
+ mService.getUserShortcutsLocked(USER_P0).getLauncherShortcuts(LAUNCHER_1, USER_0)
+ .getPackageUserId());
}
public void testOnApplicationActive_permission() {