Merge changes I4ee2affc,I81577500

* changes:
  Fix uninstall/disable with multi-user compressed stubs
  Refactor PackageSetting codePath and remove resourcePath
This commit is contained in:
Winson Chiu
2020-08-05 21:52:58 +00:00
committed by Android (Google) Code Review
28 changed files with 944 additions and 285 deletions

View File

@@ -2091,7 +2091,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (ps == null) {
return 0;
}
final File apkDirOrPath = ps.codePath;
final File apkDirOrPath = ps.getCodePath();
if (apkDirOrPath == null) {
return 0;
}

View File

@@ -3010,7 +3010,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int packageSettingCount = mSettings.mPackages.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
PackageSetting ps = mSettings.mPackages.valueAt(i);
if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
if (!isExternal(ps) && (ps.getCodePath() == null || !ps.getCodePath().exists())
&& mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
mSettings.mPackages.removeAt(i);
mSettings.enableSystemPackageLPw(ps.name);
@@ -3175,11 +3175,11 @@ public class PackageManagerService extends IPackageManager.Stub
logCriticalInfo(Log.WARN,
"Expecting better updated system app for " + ps.name
+ "; removing system app. Last known"
+ " codePath=" + ps.codePathString
+ " codePath=" + ps.getCodePathString()
+ ", versionCode=" + ps.versionCode
+ "; scanned versionCode=" + scannedPkg.getLongVersionCode());
removePackageLI(scannedPkg, true);
mExpectingBetter.put(ps.name, ps.codePath);
mExpectingBetter.put(ps.name, ps.getCodePath());
}
continue;
@@ -3202,14 +3202,14 @@ public class PackageManagerService extends IPackageManager.Stub
// code path, but, changes the package name.
final PackageSetting disabledPs =
mSettings.getDisabledSystemPkgLPr(ps.name);
if (disabledPs.codePath == null || !disabledPs.codePath.exists()
if (disabledPs.getCodePath() == null || !disabledPs.getCodePath().exists()
|| disabledPs.pkg == null) {
possiblyDeletedUpdatedSystemApps.add(ps.name);
} else {
// We're expecting that the system app should remain disabled, but add
// it to expecting better to recover in case the data version cannot
// be scanned.
mExpectingBetter.put(disabledPs.name, disabledPs.codePath);
mExpectingBetter.put(disabledPs.name, disabledPs.getCodePath());
}
}
}
@@ -9150,7 +9150,7 @@ public class PackageManagerService extends IPackageManager.Stub
: getLastModifiedTime(parsedPackage);
final VersionInfo settingsVersionForPackage = getSettingsVersionForPackage(parsedPackage);
if (ps != null && !forceCollect
&& ps.codePathString.equals(parsedPackage.getCodePath())
&& ps.getCodePathString().equals(parsedPackage.getCodePath())
&& ps.timeStamp == lastModifiedTime
&& !isCompatSignatureUpdateNeeded(settingsVersionForPackage)
&& !isRecoverSignatureUpdateNeeded(settingsVersionForPackage)) {
@@ -9383,8 +9383,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
final boolean newPkgChangedPaths =
pkgAlreadyExists && !pkgSetting.codePathString.equals(parsedPackage.getCodePath());
final boolean newPkgChangedPaths = pkgAlreadyExists
&& !pkgSetting.getCodePathString().equals(parsedPackage.getCodePath());
final boolean newPkgVersionGreater =
pkgAlreadyExists && parsedPackage.getLongVersionCode() > pkgSetting.versionCode;
final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
@@ -9403,11 +9403,11 @@ public class PackageManagerService extends IPackageManager.Stub
"System package updated;"
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> " + parsedPackage.getLongVersionCode()
+ "; " + pkgSetting.codePathString + " --> " + parsedPackage.getCodePath());
+ "; " + pkgSetting.getCodePathString()
+ " --> " + parsedPackage.getCodePath());
final InstallArgs args = createInstallArgsForExisting(
pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(
pkgSetting.getCodePathString(), getAppDexInstructionSets(
pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString));
args.cleanUpResourcesLI();
synchronized (mLock) {
@@ -9482,11 +9482,10 @@ public class PackageManagerService extends IPackageManager.Stub
+ " name: " + pkgSetting.name
+ "; " + pkgSetting.versionCode + " --> "
+ parsedPackage.getLongVersionCode()
+ "; " + pkgSetting.codePathString + " --> "
+ "; " + pkgSetting.getCodePathString() + " --> "
+ parsedPackage.getCodePath());
InstallArgs args = createInstallArgsForExisting(
pkgSetting.codePathString,
pkgSetting.resourcePathString, getAppDexInstructionSets(
pkgSetting.getCodePathString(), getAppDexInstructionSets(
pkgSetting.primaryCpuAbiString, pkgSetting.secondaryCpuAbiString));
synchronized (mInstallLock) {
args.cleanUpResourcesLI();
@@ -9499,7 +9498,7 @@ public class PackageManagerService extends IPackageManager.Stub
logCriticalInfo(Log.INFO,
"System package disabled;"
+ " name: " + pkgSetting.name
+ "; old: " + pkgSetting.codePathString + " @ "
+ "; old: " + pkgSetting.getCodePathString() + " @ "
+ pkgSetting.versionCode
+ "; new: " + parsedPackage.getCodePath() + " @ "
+ parsedPackage.getCodePath());
@@ -11325,7 +11324,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (changedAbiCodePath == null) {
changedAbiCodePath = new ArrayList<>();
}
changedAbiCodePath.add(ps.codePathString);
changedAbiCodePath.add(ps.getCodePathString());
}
}
}
@@ -11421,7 +11420,6 @@ public class PackageManagerService extends IPackageManager.Stub
// Initialize package source and resource directories
final File destCodeFile = new File(parsedPackage.getCodePath());
final File destResourceFile = new File(parsedPackage.getCodePath());
// We keep references to the derived CPU Abis from settings in oder to reuse
// them in the case where we're not upgrading or booting for the first time.
@@ -11479,7 +11477,7 @@ public class PackageManagerService extends IPackageManager.Stub
// REMOVE SharedUserSetting from method; update in a separate call
pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(),
originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting,
destCodeFile, destResourceFile, parsedPackage.getNativeLibraryRootDir(),
destCodeFile, parsedPackage.getNativeLibraryRootDir(),
AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
parsedPackage.getVersionCode(), pkgFlags, pkgPrivateFlags, user,
@@ -11497,7 +11495,7 @@ public class PackageManagerService extends IPackageManager.Stub
// secondaryCpuAbi are not known at this point so we always update them
// to null here, only to reset them at a later point.
Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting,
destCodeFile, destResourceFile, parsedPackage.getNativeLibraryDir(),
destCodeFile, parsedPackage.getNativeLibraryDir(),
AndroidPackageUtils.getPrimaryCpuAbi(parsedPackage, pkgSetting),
AndroidPackageUtils.getSecondaryCpuAbi(parsedPackage, pkgSetting),
PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
@@ -12066,15 +12064,13 @@ public class PackageManagerService extends IPackageManager.Stub
if (known != null) {
if (DEBUG_PACKAGE_SCANNING) {
Log.d(TAG, "Examining " + pkg.getCodePath()
+ " and requiring known paths " + known.codePathString
+ " & " + known.resourcePathString);
+ " and requiring known path " + known.getCodePathString());
}
if (!pkg.getCodePath().equals(known.codePathString)
|| !pkg.getCodePath().equals(known.resourcePathString)) {
if (!pkg.getCodePath().equals(known.getCodePathString())) {
throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
"Application package " + pkg.getPackageName()
+ " found at " + pkg.getCodePath()
+ " but expected at " + known.codePathString
+ " but expected at " + known.getCodePathString()
+ "; ignoring.");
}
} else {
@@ -15586,9 +15582,8 @@ public class PackageManagerService extends IPackageManager.Stub
* Create args that describe an existing installed package. Typically used
* when cleaning up old installs, or used as a move source.
*/
private InstallArgs createInstallArgsForExisting(String codePath,
String resourcePath, String[] instructionSets) {
return new FileInstallArgs(codePath, resourcePath, instructionSets);
private InstallArgs createInstallArgsForExisting(String codePath, String[] instructionSets) {
return new FileInstallArgs(codePath, instructionSets);
}
static abstract class InstallArgs {
@@ -15669,10 +15664,8 @@ public class PackageManagerService extends IPackageManager.Stub
abstract boolean doRename(int status, ParsedPackage parsedPackage);
abstract int doPostInstall(int status, int uid);
/** @see PackageSettingBase#codePathString */
/** @see PackageSettingBase#getCodePath() */
abstract String getCodePath();
/** @see PackageSettingBase#resourcePathString */
abstract String getResourcePath();
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
@@ -15743,14 +15736,13 @@ public class PackageManagerService extends IPackageManager.Stub
}
/** Existing install */
FileInstallArgs(String codePath, String resourcePath, String[] instructionSets) {
FileInstallArgs(String codePath, String[] instructionSets) {
super(OriginInfo.fromNothing(), null, null, 0, InstallSource.EMPTY,
null, null, instructionSets, null, null, null, MODE_DEFAULT, null, 0,
PackageParser.SigningDetails.UNKNOWN,
PackageManager.INSTALL_REASON_UNKNOWN, false,
DataLoaderType.NONE);
this.codeFile = (codePath != null) ? new File(codePath) : null;
this.resourceFile = (resourcePath != null) ? new File(resourcePath) : null;
}
int copyApk() {
@@ -15766,7 +15758,6 @@ public class PackageManagerService extends IPackageManager.Stub
if (origin.staged) {
if (DEBUG_INSTALL) Slog.d(TAG, origin.file + " already staged; skipping copy");
codeFile = origin.file;
resourceFile = origin.file;
return PackageManager.INSTALL_SUCCEEDED;
}
@@ -15775,7 +15766,6 @@ public class PackageManagerService extends IPackageManager.Stub
final File tempDir =
mInstallerService.allocateStageDirLegacy(volumeUuid, isEphemeral);
codeFile = tempDir;
resourceFile = tempDir;
} catch (IOException e) {
Slog.w(TAG, "Failed to create copy file: " + e);
return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -15846,7 +15836,6 @@ public class PackageManagerService extends IPackageManager.Stub
// Reflect the rename internally
codeFile = afterCodeFile;
resourceFile = afterCodeFile;
// Reflect the rename in scanned details
try {
@@ -15875,11 +15864,6 @@ public class PackageManagerService extends IPackageManager.Stub
return (codeFile != null) ? codeFile.getAbsolutePath() : null;
}
@Override
String getResourcePath() {
return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
}
private boolean cleanUp() {
if (codeFile == null || !codeFile.exists()) {
return false;
@@ -15892,10 +15876,6 @@ public class PackageManagerService extends IPackageManager.Stub
removeCodePathLI(codeFile);
if (resourceFile != null && !FileUtils.contains(codeFile, resourceFile)) {
resourceFile.delete();
}
return true;
}
@@ -15927,7 +15907,6 @@ public class PackageManagerService extends IPackageManager.Stub
*/
class MoveInstallArgs extends InstallArgs {
private File codeFile;
private File resourceFile;
/** New install */
MoveInstallArgs(InstallParams params) {
@@ -15950,7 +15929,6 @@ public class PackageManagerService extends IPackageManager.Stub
final String toPathName = new File(move.fromCodePath).getName();
codeFile = new File(Environment.getDataAppDirectory(move.toUuid), toPathName);
resourceFile = codeFile;
if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + codeFile);
return PackageManager.INSTALL_SUCCEEDED;
@@ -15987,11 +15965,6 @@ public class PackageManagerService extends IPackageManager.Stub
return (codeFile != null) ? codeFile.getAbsolutePath() : null;
}
@Override
String getResourcePath() {
return (resourceFile != null) ? resourceFile.getAbsolutePath() : null;
}
private boolean cleanUp(String volumeUuid) {
final String toPathName = new File(move.fromCodePath).getName();
final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid),
@@ -16776,7 +16749,6 @@ public class PackageManagerService extends IPackageManager.Stub
// which means we are replacing another update that is already
// installed. We need to make sure to delete the older one's .apk.
res.removedInfo.args = createInstallArgsForExisting(
oldPackage.getCodePath(),
oldPackage.getCodePath(),
getAppDexInstructionSets(
AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
@@ -18558,7 +18530,6 @@ public class PackageManagerService extends IPackageManager.Stub
// user handle installed state
int[] allUsers;
/** enabled state of the uninstalled application */
final int origEnabledState;
synchronized (mLock) {
uninstalledPs = mSettings.mPackages.get(packageName);
if (uninstalledPs == null) {
@@ -18574,10 +18545,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
disabledSystemPs = mSettings.getDisabledSystemPkgLPr(packageName);
// Save the enabled state before we delete the package. When deleting a stub
// application we always set the enabled state to 'disabled'.
origEnabledState = uninstalledPs == null
? COMPONENT_ENABLED_STATE_DEFAULT : uninstalledPs.getEnabled(userId);
// Static shared libs can be declared by any package, so let us not
// allow removing a package if it provides a lib others depend on.
pkg = mPackages.get(packageName);
@@ -18656,20 +18623,32 @@ public class PackageManagerService extends IPackageManager.Stub
if (stubPkg != null && stubPkg.isStub()) {
final PackageSetting stubPs;
synchronized (mLock) {
// restore the enabled state of the stub; the state is overwritten when
// the stub is uninstalled
stubPs = mSettings.getPackageLPr(stubPkg.getPackageName());
if (stubPs != null) {
stubPs.setEnabled(origEnabledState, userId, "android");
}
}
if (origEnabledState == COMPONENT_ENABLED_STATE_DEFAULT
|| origEnabledState == COMPONENT_ENABLED_STATE_ENABLED) {
if (DEBUG_COMPRESSION) {
Slog.i(TAG, "Enabling system stub after removal; pkg: "
+ stubPkg.getPackageName());
if (stubPs != null) {
boolean enable = false;
for (int aUserId : allUsers) {
if (stubPs.getInstalled(aUserId)) {
int enabled = stubPs.getEnabled(aUserId);
if (enabled == COMPONENT_ENABLED_STATE_DEFAULT
|| enabled == COMPONENT_ENABLED_STATE_ENABLED) {
enable = true;
break;
}
}
}
if (enable) {
if (DEBUG_COMPRESSION) {
Slog.i(TAG, "Enabling system stub after removal; pkg: "
+ stubPkg.getPackageName());
}
enableCompressedPackage(stubPkg, stubPs);
} else if (DEBUG_COMPRESSION) {
Slog.i(TAG, "System stub disabled for all users, leaving uncompressed "
+ "after removal; pkg: " + stubPkg.getPackageName());
}
enableCompressedPackage(stubPkg, stubPs);
}
}
}
@@ -18998,7 +18977,7 @@ public class PackageManagerService extends IPackageManager.Stub
// Install the system package
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
try {
installPackageFromSystemLIF(disabledPs.codePathString, allUserHandles,
installPackageFromSystemLIF(disabledPs.getCodePathString(), allUserHandles,
outInfo == null ? null : outInfo.origUsers, deletedPs.getPermissionsState(),
writeSettings);
} catch (PackageManagerException e) {
@@ -19013,8 +18992,15 @@ public class PackageManagerService extends IPackageManager.Stub
// and re-enable it afterward.
final PackageSetting stubPs = mSettings.mPackages.get(deletedPkg.getPackageName());
if (stubPs != null) {
stubPs.setEnabled(
COMPONENT_ENABLED_STATE_DISABLED, UserHandle.USER_SYSTEM, "android");
int userId = action.user == null
? UserHandle.USER_ALL : action.user.getIdentifier();
if (userId == UserHandle.USER_ALL) {
for (int aUserId : allUserHandles) {
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, aUserId, "android");
}
} else if (userId >= UserHandle.USER_SYSTEM) {
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, userId, "android");
}
}
}
}
@@ -19123,7 +19109,7 @@ public class PackageManagerService extends IPackageManager.Stub
// Delete application code and resources only for parent packages
if (deleteCodeAndResources && (outInfo != null)) {
outInfo.args = createInstallArgsForExisting(
ps.codePathString, ps.resourcePathString, getAppDexInstructionSets(
ps.getCodePathString(), getAppDexInstructionSets(
ps.primaryCpuAbiString, ps.secondaryCpuAbiString));
if (DEBUG_SD_INSTALL) Slog.i(TAG, "args=" + outInfo.args);
}
@@ -19660,7 +19646,7 @@ public class PackageManagerService extends IPackageManager.Stub
final String[] packageNames = { packageName };
final long[] ceDataInodes = { ps.getCeDataInode(userId) };
final String[] codePaths = { ps.codePathString };
final String[] codePaths = { ps.getCodePathString() };
try {
mInstaller.getAppSize(ps.volumeUuid, packageNames, userId, 0,
@@ -22582,11 +22568,11 @@ public class PackageManagerService extends IPackageManager.Stub
synchronized (mInstallLock) {
final AndroidPackage pkg;
try {
pkg = scanPackageTracedLI(ps.codePath, parseFlags, SCAN_INITIAL, 0, null);
pkg = scanPackageTracedLI(ps.getCodePath(), parseFlags, SCAN_INITIAL, 0, null);
loaded.add(pkg);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to scan " + ps.codePath + ": " + e.getMessage());
Slog.w(TAG, "Failed to scan " + ps.getCodePath() + ": " + e.getMessage());
}
if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
@@ -22657,33 +22643,33 @@ public class PackageManagerService extends IPackageManager.Stub
final ArrayList<AndroidPackage> unloaded = new ArrayList<>();
synchronized (mInstallLock) {
synchronized (mLock) {
final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(volumeUuid);
for (PackageSetting ps : packages) {
if (ps.pkg == null) continue;
synchronized (mLock) {
final List<PackageSetting> packages = mSettings.getVolumePackagesLPr(volumeUuid);
for (PackageSetting ps : packages) {
if (ps.pkg == null) continue;
final AndroidPackage pkg = ps.pkg;
final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
final PackageRemovedInfo outInfo = new PackageRemovedInfo(this);
final AndroidPackage pkg = ps.pkg;
final int deleteFlags = PackageManager.DELETE_KEEP_DATA;
final PackageRemovedInfo outInfo = new PackageRemovedInfo(this);
try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags,
"unloadPrivatePackagesInner")) {
if (deletePackageLIF(ps.name, null, false, null, deleteFlags, outInfo,
false, null)) {
unloaded.add(pkg);
} else {
Slog.w(TAG, "Failed to unload " + ps.codePath);
try (PackageFreezer freezer = freezePackageForDelete(ps.name, deleteFlags,
"unloadPrivatePackagesInner")) {
if (deletePackageLIF(ps.name, null, false, null, deleteFlags, outInfo,
false, null)) {
unloaded.add(pkg);
} else {
Slog.w(TAG, "Failed to unload " + ps.getCodePath());
}
}
// Try very hard to release any references to this package
// so we don't risk the system server being killed due to
// open FDs
AttributeCache.instance().removePackage(ps.name);
}
// Try very hard to release any references to this package
// so we don't risk the system server being killed due to
// open FDs
AttributeCache.instance().removePackage(ps.name);
mSettings.writeLPr();
}
mSettings.writeLPr();
}
}
if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
@@ -22726,7 +22712,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int packageCount = mSettings.mPackages.size();
for (int i = 0; i < packageCount; i++) {
final PackageSetting ps = mSettings.mPackages.valueAt(i);
codePaths.add(ps.codePath.getAbsolutePath());
codePaths.add(ps.getCodePath().getAbsolutePath());
}
return codePaths;
}

View File

@@ -423,13 +423,15 @@ class PackageManagerShellCommand extends ShellCommand {
final List<ApplicationInfo> list;
if (packageName == null) {
final ParceledListSlice<ApplicationInfo> packages =
mInterface.getInstalledApplications(
PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM);
mInterface.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY
| PackageManager.MATCH_UNINSTALLED_PACKAGES,
UserHandle.USER_SYSTEM);
list = packages.getList();
} else {
list = new ArrayList<>(1);
list.add(mInterface.getApplicationInfo(packageName,
PackageManager.MATCH_SYSTEM_ONLY, UserHandle.USER_SYSTEM));
list.add(mInterface.getApplicationInfo(packageName, PackageManager.MATCH_SYSTEM_ONLY
| PackageManager.MATCH_UNINSTALLED_PACKAGES,
UserHandle.USER_SYSTEM));
}
for (ApplicationInfo info : list) {
if (info.isUpdatedSystemApp()) {

View File

@@ -71,13 +71,13 @@ public class PackageSetting extends PackageSettingBase {
private PackageStateUnserialized pkgState = new PackageStateUnserialized();
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public PackageSetting(String name, String realName, File codePath, File resourcePath,
public PackageSetting(String name, String realName, @NonNull File codePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString,
long pVersionCode, int pkgFlags, int privateFlags,
int sharedUserId, String[] usesStaticLibraries,
long[] usesStaticLibrariesVersions, Map<String, ArraySet<String>> mimeGroups) {
super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
super(name, realName, codePath, legacyNativeLibraryPathString,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
pVersionCode, pkgFlags, privateFlags,
usesStaticLibraries, usesStaticLibrariesVersions);

View File

@@ -64,10 +64,8 @@ public abstract class PackageSettingBase extends SettingBase {
* this is path to single base APK file; for cluster packages this is
* path to the cluster directory.
*/
File codePath;
String codePathString;
File resourcePath;
String resourcePathString;
private File mCodePath;
private String mCodePathString;
String[] usesStaticLibraries;
long[] usesStaticLibrariesVersions;
@@ -138,7 +136,7 @@ public abstract class PackageSettingBase extends SettingBase {
boolean forceQueryableOverride;
PackageSettingBase(String name, String realName, File codePath, File resourcePath,
PackageSettingBase(String name, String realName, @NonNull File codePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString,
long pVersionCode, int pkgFlags, int pkgPrivateFlags,
@@ -148,10 +146,7 @@ public abstract class PackageSettingBase extends SettingBase {
this.realName = realName;
this.usesStaticLibraries = usesStaticLibraries;
this.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
this.codePath = codePath;
this.codePathString = codePath.toString();
this.resourcePath = resourcePath;
this.resourcePathString = resourcePath.toString();
setCodePath(codePath);
this.legacyNativeLibraryPathString = legacyNativeLibraryPathString;
this.primaryCpuAbiString = primaryCpuAbiString;
this.secondaryCpuAbiString = secondaryCpuAbiString;
@@ -235,8 +230,7 @@ public abstract class PackageSettingBase extends SettingBase {
}
private void doCopy(PackageSettingBase orig) {
codePath = orig.codePath;
codePathString = orig.codePathString;
setCodePath(orig.getCodePath());
cpuAbiOverrideString = orig.cpuAbiOverrideString;
firstInstallTime = orig.firstInstallTime;
installPermissionsFixed = orig.installPermissionsFixed;
@@ -246,8 +240,6 @@ public abstract class PackageSettingBase extends SettingBase {
legacyNativeLibraryPathString = orig.legacyNativeLibraryPathString;
// Intentionally skip mOldCodePaths; it's not relevant for copies
primaryCpuAbiString = orig.primaryCpuAbiString;
resourcePath = orig.resourcePath;
resourcePathString = orig.resourcePathString;
secondaryCpuAbiString = orig.secondaryCpuAbiString;
signatures = orig.signatures;
timeStamp = orig.timeStamp;
@@ -705,6 +697,20 @@ public abstract class PackageSettingBase extends SettingBase {
return userState.harmfulAppWarning;
}
PackageSettingBase setCodePath(@NonNull File codePath) {
this.mCodePath = codePath;
this.mCodePathString = codePath.toString();
return this;
}
File getCodePath() {
return mCodePath;
}
String getCodePathString() {
return mCodePathString;
}
/**
* @see PackageUserState#overrideLabelAndIcon(ComponentName, String, Integer)
*
@@ -727,10 +733,7 @@ public abstract class PackageSettingBase extends SettingBase {
protected PackageSettingBase updateFrom(PackageSettingBase other) {
super.copyFrom(other);
this.codePath = other.codePath;
this.codePathString = other.codePathString;
this.resourcePath = other.resourcePath;
this.resourcePathString = other.resourcePathString;
setCodePath(other.getCodePath());
this.usesStaticLibraries = other.usesStaticLibraries;
this.usesStaticLibrariesVersions = other.usesStaticLibrariesVersions;
this.legacyNativeLibraryPathString = other.legacyNativeLibraryPathString;

View File

@@ -538,7 +538,7 @@ public final class Settings {
return null;
}
p.getPkgState().setUpdatedSystemApp(false);
PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
PackageSetting ret = addPackageLPw(name, p.realName, p.getCodePath(),
p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
p.secondaryCpuAbiString, p.cpuAbiOverrideString,
p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
@@ -558,7 +558,7 @@ public final class Settings {
mDisabledSysPackages.remove(name);
}
PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
PackageSetting addPackageLPw(String name, String realName, File codePath,
String legacyNativeLibraryPathString, String primaryCpuAbiString,
String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc, int
pkgFlags, int pkgPrivateFlags, String[] usesStaticLibraries,
@@ -572,10 +572,9 @@ public final class Settings {
"Adding duplicate package, keeping first: " + name);
return null;
}
p = new PackageSetting(name, realName, codePath, resourcePath,
legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags,
0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames,
p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, vc, pkgFlags,
pkgPrivateFlags, 0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames,
mimeGroups);
p.appId = uid;
if (registerExistingAppIdLPw(uid, p, name)) {
@@ -635,7 +634,7 @@ public final class Settings {
*/
static @NonNull PackageSetting createNewSetting(String pkgName, PackageSetting originalPkg,
PackageSetting disabledPkg, String realPkgName, SharedUserSetting sharedUser,
File codePath, File resourcePath, String legacyNativeLibraryPath, String primaryCpuAbi,
File codePath, String legacyNativeLibraryPath, String primaryCpuAbi,
String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags,
UserHandle installUser, boolean allowInstall, boolean instantApp,
boolean virtualPreload, UserManagerService userManager,
@@ -646,12 +645,11 @@ public final class Settings {
if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
+ pkgName + " is adopting original package " + originalPkg.name);
pkgSetting = new PackageSetting(originalPkg, pkgName /*realPkgName*/);
pkgSetting.codePath = codePath;
pkgSetting.setCodePath(codePath);
pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
pkgSetting.pkgFlags = pkgFlags;
pkgSetting.pkgPrivateFlags = pkgPrivateFlags;
pkgSetting.primaryCpuAbiString = primaryCpuAbi;
pkgSetting.resourcePath = resourcePath;
pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
// NOTE: Create a deeper copy of the package signatures so we don't
// overwrite the signatures in the original package setting.
@@ -662,7 +660,7 @@ public final class Settings {
// Update new package state.
pkgSetting.setTimeStamp(codePath.lastModified());
} else {
pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath,
pkgSetting = new PackageSetting(pkgName, realPkgName, codePath,
legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
0 /*sharedUserId*/, usesStaticLibraries,
@@ -756,10 +754,9 @@ public final class Settings {
*/
static void updatePackageSetting(@NonNull PackageSetting pkgSetting,
@Nullable PackageSetting disabledPkg, @Nullable SharedUserSetting sharedUser,
@NonNull File codePath, File resourcePath,
@Nullable String legacyNativeLibraryPath, @Nullable String primaryCpuAbi,
@Nullable String secondaryCpuAbi, int pkgFlags, int pkgPrivateFlags,
@NonNull UserManagerService userManager,
@NonNull File codePath, @Nullable String legacyNativeLibraryPath,
@Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi, int pkgFlags,
int pkgPrivateFlags, @NonNull UserManagerService userManager,
@Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions,
@Nullable Set<String> mimeGroupNames)
throws PackageManagerException {
@@ -773,12 +770,12 @@ public final class Settings {
"Updating application package " + pkgName + " failed");
}
if (!pkgSetting.codePath.equals(codePath)) {
if (!pkgSetting.getCodePath().equals(codePath)) {
final boolean isSystem = pkgSetting.isSystem();
Slog.i(PackageManagerService.TAG,
"Update" + (isSystem ? " system" : "")
+ " package " + pkgName
+ " code path from " + pkgSetting.codePathString
+ " code path from " + pkgSetting.getCodePathString()
+ " to " + codePath.toString()
+ "; Retain data and using new");
if (!isSystem) {
@@ -800,19 +797,7 @@ public final class Settings {
// internal to external storage or vice versa.
pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
}
pkgSetting.codePath = codePath;
pkgSetting.codePathString = codePath.toString();
}
if (!pkgSetting.resourcePath.equals(resourcePath)) {
final boolean isSystem = pkgSetting.isSystem();
Slog.i(PackageManagerService.TAG,
"Update" + (isSystem ? " system" : "")
+ " package " + pkgName
+ " resource path from " + pkgSetting.resourcePathString
+ " to " + resourcePath.toString()
+ "; Retain data and using new");
pkgSetting.resourcePath = resourcePath;
pkgSetting.resourcePathString = resourcePath.toString();
pkgSetting.setCodePath(codePath);
}
// If what we are scanning is a system (and possibly privileged) package,
// then make it so, regardless of whether it was previously installed only
@@ -2812,14 +2797,11 @@ public final class Settings {
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
serializer.attribute(null, "codePath", pkg.codePathString);
serializer.attribute(null, "codePath", pkg.getCodePathString());
serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
serializer.attribute(null, "ut", Long.toHexString(pkg.lastUpdateTime));
serializer.attribute(null, "version", String.valueOf(pkg.versionCode));
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
}
if (pkg.legacyNativeLibraryPathString != null) {
serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
}
@@ -2857,10 +2839,7 @@ public final class Settings {
if (pkg.realName != null) {
serializer.attribute(null, "realName", pkg.realName);
}
serializer.attribute(null, "codePath", pkg.codePathString);
if (!pkg.resourcePathString.equals(pkg.codePathString)) {
serializer.attribute(null, "resourcePath", pkg.resourcePathString);
}
serializer.attribute(null, "codePath", pkg.getCodePathString());
if (pkg.legacyNativeLibraryPathString != null) {
serializer.attribute(null, "nativeLibraryPath", pkg.legacyNativeLibraryPathString);
@@ -3559,13 +3538,10 @@ public final class Settings {
String name = parser.getAttributeValue(null, ATTR_NAME);
String realName = parser.getAttributeValue(null, "realName");
String codePathStr = parser.getAttributeValue(null, "codePath");
String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
String legacyCpuAbiStr = parser.getAttributeValue(null, "requiredCpuAbi");
String legacyNativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
String parentPackageName = parser.getAttributeValue(null, "parentPackageName");
String primaryCpuAbiStr = parser.getAttributeValue(null, "primaryCpuAbi");
String secondaryCpuAbiStr = parser.getAttributeValue(null, "secondaryCpuAbi");
String cpuAbiOverrideStr = parser.getAttributeValue(null, "cpuAbiOverride");
@@ -3574,9 +3550,6 @@ public final class Settings {
primaryCpuAbiStr = legacyCpuAbiStr;
}
if (resourcePathStr == null) {
resourcePathStr = codePathStr;
}
String version = parser.getAttributeValue(null, "version");
long versionCode = 0;
if (version != null) {
@@ -3593,9 +3566,8 @@ public final class Settings {
pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
}
PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags,
0 /*sharedUserId*/, null, null, null);
legacyNativeLibraryPathStr, primaryCpuAbiStr, secondaryCpuAbiStr, cpuAbiOverrideStr,
versionCode, pkgFlags, pkgPrivateFlags, 0 /*sharedUserId*/, null, null, null);
String timeStampStr = parser.getAttributeValue(null, "ft");
if (timeStampStr != null) {
try {
@@ -3666,7 +3638,6 @@ public final class Settings {
String idStr = null;
String sharedIdStr = null;
String codePathStr = null;
String resourcePathStr = null;
String legacyCpuAbiString = null;
String legacyNativeLibraryPathStr = null;
String primaryCpuAbiString = null;
@@ -3700,7 +3671,6 @@ public final class Settings {
uidError = parser.getAttributeValue(null, "uidError");
sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
codePathStr = parser.getAttributeValue(null, "codePath");
resourcePathStr = parser.getAttributeValue(null, "resourcePath");
legacyCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
@@ -3818,9 +3788,6 @@ public final class Settings {
+ " sharedUserId=" + sharedIdStr);
final int userId = idStr != null ? Integer.parseInt(idStr) : 0;
final int sharedUserId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
if (resourcePathStr == null) {
resourcePathStr = codePathStr;
}
if (realName != null) {
realName = realName.intern();
}
@@ -3834,10 +3801,10 @@ public final class Settings {
+ parser.getPositionDescription());
} else if (userId > 0) {
packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
pkgPrivateFlags, null /*usesStaticLibraries*/,
null /*usesStaticLibraryVersions*/, null /*mimeGroups*/);
legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
cpuAbiOverrideString, userId, versionCode, pkgFlags, pkgPrivateFlags,
null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/,
null /*mimeGroups*/);
if (PackageManagerService.DEBUG_SETTINGS)
Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
+ userId + " pkg=" + packageSetting);
@@ -3852,8 +3819,8 @@ public final class Settings {
}
} else if (sharedIdStr != null) {
if (sharedUserId > 0) {
packageSetting = new PackageSetting(name.intern(), realName, new File(
codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
packageSetting = new PackageSetting(name.intern(), realName,
new File(codePathStr), legacyNativeLibraryPathStr,
primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
versionCode, pkgFlags, pkgPrivateFlags, sharedUserId,
null /*usesStaticLibraries*/,
@@ -4657,9 +4624,9 @@ public final class Settings {
pw.print(prefix); pw.print(" sharedUser="); pw.println(ps.sharedUser);
}
pw.print(prefix); pw.print(" pkg="); pw.println(pkg);
pw.print(prefix); pw.print(" codePath="); pw.println(ps.codePathString);
pw.print(prefix); pw.print(" codePath="); pw.println(ps.getCodePathString());
if (permissionNames == null) {
pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.resourcePathString);
pw.print(prefix); pw.print(" resourcePath="); pw.println(ps.getCodePathString());
pw.print(prefix); pw.print(" legacyNativeLibraryDir=");
pw.println(ps.legacyNativeLibraryPathString);
pw.print(prefix); pw.print(" primaryCpuAbi="); pw.println(ps.primaryCpuAbiString);

View File

@@ -33,7 +33,6 @@ import com.android.server.pm.parsing.pkg.PackageImpl
import com.android.server.pm.parsing.pkg.ParsedPackage
import com.android.server.pm.permission.PermissionManagerServiceInternal
import com.android.server.pm.test.override.PackageManagerComponentLabelIconOverrideTest.Companion.Params.AppType
import com.android.server.pm.test.override.R
import com.android.server.testutils.TestHandler
import com.android.server.testutils.mock
import com.android.server.testutils.mockThrowOnUnmocked
@@ -266,7 +265,7 @@ class PackageManagerComponentLabelIconOverrideTest {
.hideAsFinal()
private fun makePkgSetting(pkgName: String) = spy(PackageSetting(pkgName, null, File("/test"),
File("/test"), null, null, null, null, 0, 0, 0, 0, null, null, null)) {
null, null, null, null, 0, 0, 0, 0, null, null, null)) {
this.pkgState.isUpdatedSystemApp = params.isUpdatedSystemApp
}

View File

@@ -25,17 +25,28 @@ java_test_host {
],
test_suites: ["general-tests"],
java_resources: [
":PackageManagerDummyAppVersion1",
":PackageManagerDummyAppVersion2",
":PackageManagerDummyAppVersion3",
":PackageManagerDummyAppVersion4",
":PackageManagerDummyAppOriginalOverride",
":PackageManagerServiceHostTestsResources",
]
":PackageManagerTestAppStub",
":PackageManagerTestAppVersion1",
":PackageManagerTestAppVersion2",
":PackageManagerTestAppVersion3",
":PackageManagerTestAppVersion3Invalid",
":PackageManagerTestAppVersion4",
":PackageManagerTestAppOriginalOverride",
],
}
filegroup {
name: "PackageManagerServiceHostTestsResources",
srcs: [ "resources/*" ],
path: "resources/"
genrule {
name: "PackageManagerTestAppVersion3Invalid",
tools: [
"soong_zip",
"zipalign",
],
srcs: [
":PackageManagerTestAppVersion3",
],
out: ["PackageManagerTestAppVersion3Invalid.apk"],
cmd: "mkdir -p $(genDir)/apk && unzip $(in) -d $(genDir)/apk" +
" && truncate -s 800 $(genDir)/apk/META-INF/CERT.RSA" +
" && $(location soong_zip) -o $(genDir)/temp.apk -L 0 -C $(genDir)/apk -D $(genDir)/apk" +
" && $(location zipalign) -f 4 $(genDir)/temp.apk $(out)",
}

View File

@@ -21,8 +21,9 @@ import com.android.tradefed.device.ITestDevice
import java.io.File
import java.io.FileOutputStream
internal fun SystemPreparer.pushApk(file: String, partition: Partition) =
pushResourceFile(file, HostUtils.makePathForApk(file, partition).toString())
internal fun SystemPreparer.pushApk(javaResourceName: String, partition: Partition) =
pushResourceFile(javaResourceName, HostUtils.makePathForApk(javaResourceName, partition)
.toString())
internal fun SystemPreparer.deleteApkFolders(
partition: Partition,
@@ -58,4 +59,55 @@ internal object HostUtils {
}
return file
}
/**
* dumpsys package and therefore device.getAppPackageInfo doesn't work immediately after reboot,
* so the following methods parse the package dump directly to see if the path matches.
*/
fun getCodePaths(device: ITestDevice, pkgName: String) =
device.executeShellCommand("pm dump $pkgName")
.lineSequence()
.map(String::trim)
.filter { it.startsWith("codePath=") }
.map { it.removePrefix("codePath=") }
.toList()
private fun userIdLineSequence(device: ITestDevice, pkgName: String) =
device.executeShellCommand("pm dump $pkgName")
.lineSequence()
.dropWhile { !it.startsWith("Packages:") }
.takeWhile {
!it.startsWith("Hidden system packages:") &&
!it.startsWith("Queries:")
}
.map(String::trim)
.filter { it.startsWith("User ") }
fun getUserIdToPkgEnabledState(device: ITestDevice, pkgName: String) =
userIdLineSequence(device, pkgName).associate {
val userId = it.removePrefix("User ")
.takeWhile(Char::isDigit)
.toInt()
val enabled = it.substringAfter("enabled=")
.takeWhile(Char::isDigit)
.toInt()
.let {
when (it) {
0, 1 -> true
else -> false
}
}
userId to enabled
}
fun getUserIdToPkgInstalledState(device: ITestDevice, pkgName: String) =
userIdLineSequence(device, pkgName).associate {
val userId = it.removePrefix("User ")
.takeWhile(Char::isDigit)
.toInt()
val installed = it.substringAfter("installed=")
.takeWhile { !it.isWhitespace() }
.toBoolean()
userId to installed
}
}

View File

@@ -33,11 +33,11 @@ import org.junit.runner.RunWith
class InvalidNewSystemAppTest : BaseHostJUnit4Test() {
companion object {
private const val TEST_PKG_NAME = "com.android.server.pm.test.dummy_app"
private const val VERSION_ONE = "PackageManagerDummyAppVersion1.apk"
private const val VERSION_TWO = "PackageManagerDummyAppVersion2.apk"
private const val VERSION_THREE_INVALID = "PackageManagerDummyAppVersion3Invalid.apk"
private const val VERSION_FOUR = "PackageManagerDummyAppVersion4.apk"
private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk"
private const val VERSION_TWO = "PackageManagerTestAppVersion2.apk"
private const val VERSION_THREE_INVALID = "PackageManagerTestAppVersion3Invalid.apk"
private const val VERSION_FOUR = "PackageManagerTestAppVersion4.apk"
@get:ClassRule
val deviceRebootRule = SystemPreparer.TestRuleDelegate(true)
@@ -49,14 +49,14 @@ class InvalidNewSystemAppTest : BaseHostJUnit4Test() {
@get:Rule
val rules = RuleChain.outerRule(tempFolder).around(preparer)!!
private val filePath = HostUtils.makePathForApk("PackageManagerDummyApp.apk", Partition.PRODUCT)
private val filePath = HostUtils.makePathForApk("PackageManagerTestApp.apk", Partition.PRODUCT)
@Before
@After
fun removeApk() {
device.uninstallPackage(TEST_PKG_NAME)
device.deleteFile(filePath.parent.toString())
device.reboot()
preparer.deleteFile(filePath.parent.toString())
.reboot()
}
@Test

View File

@@ -33,11 +33,11 @@ import org.junit.runner.RunWith
class OriginalPackageMigrationTest : BaseHostJUnit4Test() {
companion object {
private const val TEST_PKG_NAME = "com.android.server.pm.test.dummy_app"
private const val VERSION_ONE = "PackageManagerDummyAppVersion1.apk"
private const val VERSION_TWO = "PackageManagerDummyAppVersion2.apk"
private const val VERSION_THREE = "PackageManagerDummyAppVersion3.apk"
private const val NEW_PKG = "PackageManagerDummyAppOriginalOverride.apk"
private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk"
private const val VERSION_TWO = "PackageManagerTestAppVersion2.apk"
private const val VERSION_THREE = "PackageManagerTestAppVersion3.apk"
private const val NEW_PKG = "PackageManagerTestAppOriginalOverride.apk"
@get:ClassRule
val deviceRebootRule = SystemPreparer.TestRuleDelegate(true)
@@ -55,6 +55,7 @@ class OriginalPackageMigrationTest : BaseHostJUnit4Test() {
fun deleteApkFolders() {
preparer.deleteApkFolders(Partition.SYSTEM, VERSION_ONE, VERSION_TWO, VERSION_THREE,
NEW_PKG)
.reboot()
}
@Test
@@ -99,9 +100,7 @@ class OriginalPackageMigrationTest : BaseHostJUnit4Test() {
}
private fun assertCodePath(apk: String) {
// dumpsys package and therefore device.getAppPackageInfo doesn't work here for some reason,
// so parse the package dump directly to see if the path matches.
assertThat(device.executeShellCommand("pm dump $TEST_PKG_NAME"))
.contains(HostUtils.makePathForApk(apk, Partition.SYSTEM).parent.toString())
assertThat(HostUtils.getCodePaths(device, TEST_PKG_NAME))
.containsExactly(HostUtils.makePathForApk(apk, Partition.SYSTEM).parent.toString())
}
}

View File

@@ -0,0 +1,650 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm.test
import com.android.internal.util.test.SystemPreparer
import com.android.tradefed.device.ITestDevice
import com.android.tradefed.device.UserInfo
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test
import com.google.common.truth.Truth.assertThat
import org.junit.AfterClass
import org.junit.Before
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import java.io.File
import java.util.zip.GZIPOutputStream
@RunWith(DeviceJUnit4ClassRunner::class)
class SystemStubMultiUserDisableUninstallTest : BaseHostJUnit4Test() {
companion object {
private const val TEST_PKG_NAME = "com.android.server.pm.test.test_app"
private const val VERSION_STUB = "PackageManagerTestAppStub.apk"
private const val VERSION_ONE = "PackageManagerTestAppVersion1.apk"
/**
* How many total users on device to test, including primary. This will clean up any
* users created specifically for this test.
*/
private const val USER_COUNT = 3
/**
* Whether to manually reset state at each test method without rebooting
* for faster iterative development.
*/
private const val DEBUG_NO_REBOOT = false
@get:ClassRule
val deviceRebootRule = SystemPreparer.TestRuleDelegate(true)
private val parentClassName = SystemStubMultiUserDisableUninstallTest::class.java.simpleName
private val deviceCompressedFile =
HostUtils.makePathForApk("$parentClassName.apk", Partition.PRODUCT).parent
.resolve("$parentClassName.apk.gz")
private val stubFile =
HostUtils.makePathForApk("$parentClassName-Stub.apk", Partition.PRODUCT)
private val secondaryUsers = mutableListOf<Int>()
private val usersToRemove = mutableListOf<Int>()
private var savedDevice: ITestDevice? = null
private var savedPreparer: SystemPreparer? = null
private fun setUpUsers(device: ITestDevice) {
if (this.savedDevice != null) return
this.savedDevice = device
secondaryUsers.clear()
secondaryUsers += device.userInfos.values.map(UserInfo::userId).filterNot { it == 0 }
while (secondaryUsers.size < USER_COUNT) {
secondaryUsers += device.createUser(parentClassName + secondaryUsers.size)
.also { usersToRemove += it }
}
}
@JvmStatic
@AfterClass
fun cleanUp() {
savedDevice ?: return
usersToRemove.forEach {
savedDevice?.removeUser(it)
}
savedDevice?.uninstallPackage(TEST_PKG_NAME)
savedDevice?.deleteFile(stubFile.parent.toString())
savedDevice?.deleteFile(deviceCompressedFile.parent.toString())
savedDevice?.reboot()
savedDevice = null
if (DEBUG_NO_REBOOT) {
savedPreparer?.after()
savedPreparer = null
}
}
}
private val tempFolder = TemporaryFolder()
private val preparer: SystemPreparer = SystemPreparer(tempFolder,
SystemPreparer.RebootStrategy.START_STOP, deviceRebootRule) { this.device }
@get:Rule
val rules = RuleChain.outerRule(tempFolder).let {
if (DEBUG_NO_REBOOT) {
it!!
} else {
it.around(preparer)!!
}
}
private var hostCompressedFile: File? = null
private val previousCodePaths = mutableListOf<String>()
@Before
fun ensureUserAndCompressStubAndInstall() {
setUpUsers(device)
val initialized = hostCompressedFile != null
if (!initialized) {
hostCompressedFile = tempFolder.newFile()
hostCompressedFile!!.outputStream().use {
javaClass.classLoader
.getResource(VERSION_ONE)!!
.openStream()
.use { input ->
GZIPOutputStream(it).use { output ->
input.copyTo(output)
}
}
}
}
device.uninstallPackage(TEST_PKG_NAME)
if (!initialized || !DEBUG_NO_REBOOT) {
savedPreparer = preparer
preparer.pushResourceFile(VERSION_STUB, stubFile.toString())
.pushFile(hostCompressedFile, deviceCompressedFile.toString())
.reboot()
}
// This test forces the state to installed/enabled for all users,
// since it only tests the uninstall/disable side.
installExisting(User.PRIMARY)
installExisting(User.SECONDARY)
ensureEnabled()
// Ensure data app isn't re-installed multiple times by comparing against the original path
val codePath = HostUtils.getCodePaths(device, TEST_PKG_NAME).first()
assertThat(codePath).contains("/data/app")
assertThat(codePath).contains(TEST_PKG_NAME)
previousCodePaths.clear()
previousCodePaths += codePath
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun disablePrimaryFirstAndUninstall() {
toggleEnabled(false, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
toggleEnabled(false, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
device.uninstallPackage(TEST_PKG_NAME)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SYSTEM)
)
}
@Test
fun disableSecondaryFirstAndUninstall() {
toggleEnabled(false, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
toggleEnabled(false, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
device.uninstallPackage(TEST_PKG_NAME)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SYSTEM)
)
}
@Test
fun disabledUninstalledEnablePrimaryFirst() {
toggleEnabled(false, User.PRIMARY)
toggleEnabled(false, User.SECONDARY)
device.uninstallPackage(TEST_PKG_NAME)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun disabledUninstalledEnableSecondaryFirst() {
toggleEnabled(false, User.PRIMARY)
toggleEnabled(false, User.SECONDARY)
device.uninstallPackage(TEST_PKG_NAME)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun uninstallPrimaryFirstByUserAndInstallExistingPrimaryFirst() {
uninstall(User.PRIMARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
uninstall(User.SECONDARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
installExisting(User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
installExisting(User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun uninstallSecondaryFirstByUserAndInstallExistingSecondaryFirst() {
uninstall(User.PRIMARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
uninstall(User.SECONDARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
installExisting(User.SECONDARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
installExisting(User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun uninstallUpdatesAndEnablePrimaryFirst() {
device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME")
// Uninstall-system-updates always disables system user 0
// TODO: Is this intentional? There is no user argument for this command.
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = true,
// If any user is enabled when uninstalling updates, /data is re-uncompressed
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
// Test enabling secondary to ensure path does not change, even though it's already enabled
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun uninstallUpdatesAndEnableSecondaryFirst() {
device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME")
// Uninstall-system-updates always disables system user 0
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = true,
// If any user is enabled when uninstalling updates, /data is re-uncompressed
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun disabledUninstallUpdatesAndEnablePrimaryFirst() {
toggleEnabled(false, User.PRIMARY)
toggleEnabled(false, User.SECONDARY)
device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME")
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun disabledUninstallUpdatesAndEnableSecondaryFirst() {
toggleEnabled(false, User.PRIMARY)
toggleEnabled(false, User.SECONDARY)
device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME")
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = false,
codePaths = listOf(CodePath.SYSTEM)
)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = true, primaryEnabled = false,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = true, primaryEnabled = true,
secondaryInstalled = true, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun uninstalledUninstallUpdatesAndEnablePrimaryFirst() {
uninstall(User.PRIMARY)
uninstall(User.SECONDARY)
device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME")
// Uninstall-system-updates always disables system user 0
assertState(
primaryInstalled = false, primaryEnabled = false,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
@Test
fun uninstalledUninstallUpdatesAndEnableSecondaryFirst() {
uninstall(User.PRIMARY)
uninstall(User.SECONDARY)
device.executeShellCommand("pm uninstall-system-updates $TEST_PKG_NAME")
// Uninstall-system-updates always disables system user 0
assertState(
primaryInstalled = false, primaryEnabled = false,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.SYSTEM)
)
toggleEnabled(true, User.SECONDARY)
assertState(
primaryInstalled = false, primaryEnabled = false,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.DIFFERENT, CodePath.SYSTEM)
)
toggleEnabled(true, User.PRIMARY)
assertState(
primaryInstalled = false, primaryEnabled = true,
secondaryInstalled = false, secondaryEnabled = true,
codePaths = listOf(CodePath.SAME, CodePath.SYSTEM)
)
}
private fun ensureEnabled() {
toggleEnabled(true, User.PRIMARY)
toggleEnabled(true, User.SECONDARY)
assertThat(HostUtils.getUserIdToPkgEnabledState(device, TEST_PKG_NAME).all { it.value })
.isTrue()
}
private fun toggleEnabled(enabled: Boolean, user: User, pkgName: String = TEST_PKG_NAME) {
val command = if (enabled) "enable" else "disable"
@Suppress("UNUSED_VARIABLE") val exhaust: Any = when (user) {
User.PRIMARY -> {
device.executeShellCommand("pm $command --user 0 $pkgName")
}
User.SECONDARY -> {
secondaryUsers.forEach {
device.executeShellCommand("pm $command --user $it $pkgName")
}
}
}
}
private fun uninstall(user: User, pkgName: String = TEST_PKG_NAME) {
@Suppress("UNUSED_VARIABLE") val exhaust: Any = when (user) {
User.PRIMARY -> {
device.executeShellCommand("pm uninstall --user 0 $pkgName")
}
User.SECONDARY -> {
secondaryUsers.forEach {
device.executeShellCommand("pm uninstall --user $it $pkgName")
}
}
}
}
private fun installExisting(user: User, pkgName: String = TEST_PKG_NAME) {
@Suppress("UNUSED_VARIABLE") val exhaust: Any = when (user) {
User.PRIMARY -> {
device.executeShellCommand("pm install-existing --user 0 $pkgName")
}
User.SECONDARY -> {
secondaryUsers.forEach {
device.executeShellCommand("pm install-existing --user $it $pkgName")
}
}
}
}
private fun assertState(
primaryInstalled: Boolean,
primaryEnabled: Boolean,
secondaryInstalled: Boolean,
secondaryEnabled: Boolean,
codePaths: List<CodePath>
) {
HostUtils.getUserIdToPkgInstalledState(device, TEST_PKG_NAME)
.forEach { (userId, installed) ->
if (userId == 0) {
assertThat(installed).isEqualTo(primaryInstalled)
} else {
assertThat(installed).isEqualTo(secondaryInstalled)
}
}
HostUtils.getUserIdToPkgEnabledState(device, TEST_PKG_NAME)
.forEach { (userId, enabled) ->
if (userId == 0) {
assertThat(enabled).isEqualTo(primaryEnabled)
} else {
assertThat(enabled).isEqualTo(secondaryEnabled)
}
}
assertCodePaths(codePaths.first(), codePaths.getOrNull(1))
}
private fun assertCodePaths(firstCodePath: CodePath, secondCodePath: CodePath? = null) {
val codePaths = HostUtils.getCodePaths(device, TEST_PKG_NAME)
assertThat(codePaths).hasSize(listOfNotNull(firstCodePath, secondCodePath).size)
when (firstCodePath) {
CodePath.SAME -> {
assertThat(codePaths[0]).contains("/data/app")
assertThat(codePaths[0]).contains(TEST_PKG_NAME)
assertThat(codePaths[0]).isEqualTo(previousCodePaths.last())
}
CodePath.DIFFERENT -> {
assertThat(codePaths[0]).contains("/data/app")
assertThat(codePaths[0]).contains(TEST_PKG_NAME)
assertThat(previousCodePaths).doesNotContain(codePaths[0])
previousCodePaths.add(codePaths[0])
}
CodePath.SYSTEM -> assertThat(codePaths[0]).isEqualTo(stubFile.parent.toString())
}
when (secondCodePath) {
CodePath.SAME, CodePath.DIFFERENT ->
throw AssertionError("secondDataPath cannot be a data path")
CodePath.SYSTEM -> assertThat(codePaths[1]).isEqualTo(stubFile.parent.toString())
}
}
enum class User {
/** The primary system user 0 */
PRIMARY,
/**
* All other users on the device that are not 0. This is split into an enum so that all
* methods that handle secondary act on all non-system users. Some behaviors only occur
* if a package state is marked for all non-primary users on the device, which can be
* more than just 1.
*/
SECONDARY
}
enum class CodePath {
/** The data code path hasn't changed */
SAME,
/** New data code path */
DIFFERENT,
/** The static system code path */
SYSTEM
}
}

View File

@@ -13,26 +13,32 @@
// limitations under the License.
android_test_helper_app {
name: "PackageManagerDummyAppVersion1",
name: "PackageManagerTestAppStub",
manifest: "AndroidManifestVersion1.xml",
srcs: []
}
android_test_helper_app {
name: "PackageManagerTestAppVersion1",
manifest: "AndroidManifestVersion1.xml"
}
android_test_helper_app {
name: "PackageManagerDummyAppVersion2",
name: "PackageManagerTestAppVersion2",
manifest: "AndroidManifestVersion2.xml"
}
android_test_helper_app {
name: "PackageManagerDummyAppVersion3",
name: "PackageManagerTestAppVersion3",
manifest: "AndroidManifestVersion3.xml"
}
android_test_helper_app {
name: "PackageManagerDummyAppVersion4",
name: "PackageManagerTestAppVersion4",
manifest: "AndroidManifestVersion4.xml"
}
android_test_helper_app {
name: "PackageManagerDummyAppOriginalOverride",
name: "PackageManagerTestAppOriginalOverride",
manifest: "AndroidManifestOriginalOverride.xml"
}

View File

@@ -16,10 +16,10 @@
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app.override"
package="com.android.server.pm.test.test_app.override"
android:versionCode="2"
>
<original-package android:name="com.android.server.pm.test.dummy_app"/>
<original-package android:name="com.android.server.pm.test.test_app"/>
</manifest>

View File

@@ -16,12 +16,12 @@
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
package="com.android.server.pm.test.test_app"
android:versionCode="1"
>
<permission
android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
android:name="com.android.server.pm.test.test_app.TEST_PERMISSION"
android:protectionLevel="normal"
/>

View File

@@ -16,12 +16,12 @@
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
package="com.android.server.pm.test.test_app"
android:versionCode="2"
>
<permission
android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
android:name="com.android.server.pm.test.test_app.TEST_PERMISSION"
android:protectionLevel="normal"
/>

View File

@@ -16,12 +16,12 @@
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
package="com.android.server.pm.test.test_app"
android:versionCode="3"
>
<permission
android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
android:name="com.android.server.pm.test.test_app.TEST_PERMISSION"
android:protectionLevel="normal"
/>

View File

@@ -16,12 +16,12 @@
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.server.pm.test.dummy_app"
package="com.android.server.pm.test.test_app"
android:versionCode="4"
>
<permission
android:name="com.android.server.pm.test.dummy_app.TEST_PERMISSION"
android:name="com.android.server.pm.test.test_app.TEST_PERMISSION"
android:protectionLevel="normal"
/>

View File

@@ -550,7 +550,6 @@ public class AppsFilterTest {
.setAppId(DUMMY_TARGET_APPID)
.setName("com.some.package")
.setCodePath("/")
.setResourcePath("/")
.setPVersionCode(1L)
.build();
PackageSetting calling = simulateAddPackage(appsFilter,
@@ -874,7 +873,6 @@ public class AppsFilterTest {
.setAppId(appId)
.setName(newPkg.getPackageName())
.setCodePath("/")
.setResourcePath("/")
.setPVersionCode(1L);
final PackageSetting setting =
(action == null ? settingBuilder : action.withBuilder(settingBuilder)).build();

View File

@@ -38,8 +38,7 @@ public class KeySetManagerServiceTest extends AndroidTestCase {
public PackageSetting generateFakePackageSetting(String name) {
return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"),
new File(mContext.getCacheDir(), "fakeResPath"), "", "", "",
"", 1, 0, 0, 0 /*sharedUserId*/, null /*usesStaticLibraries*/,
"", "", "", "", 1, 0, 0, 0 /*sharedUserId*/, null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/, null /*mimeGroups*/);
}

View File

@@ -86,8 +86,7 @@ public class PackageManagerServiceTest {
// Create a real (non-null) PackageSetting and confirm that the removed
// users are copied properly
setting = new PackageSetting("name", "realName", new File("codePath"),
new File("resourcePath"), "legacyNativeLibraryPathString",
"primaryCpuAbiString", "secondaryCpuAbiString",
"legacyNativeLibraryPathString", "primaryCpuAbiString", "secondaryCpuAbiString",
"cpuAbiOverrideString", 0, 0, 0, 0,
null, null, null);
pri.populateUsers(new int[] {

View File

@@ -439,7 +439,6 @@ public class PackageManagerSettingsTests {
PACKAGE_NAME,
REAL_PACKAGE_NAME,
INITIAL_CODE_PATH /*codePath*/,
INITIAL_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPathString*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
@@ -461,7 +460,6 @@ public class PackageManagerSettingsTests {
PACKAGE_NAME /*pkgName*/,
REAL_PACKAGE_NAME /*realPkgName*/,
INITIAL_CODE_PATH /*codePath*/,
INITIAL_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPathString*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
@@ -477,7 +475,6 @@ public class PackageManagerSettingsTests {
PACKAGE_NAME /*pkgName*/,
REAL_PACKAGE_NAME /*realPkgName*/,
UPDATED_CODE_PATH /*codePath*/,
UPDATED_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPathString*/,
null /*primaryCpuAbiString*/,
null /*secondaryCpuAbiString*/,
@@ -507,7 +504,6 @@ public class PackageManagerSettingsTests {
null /*disabledPkg*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
UPDATED_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
@@ -541,7 +537,6 @@ public class PackageManagerSettingsTests {
null /*disabledPkg*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
UPDATED_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
@@ -581,7 +576,6 @@ public class PackageManagerSettingsTests {
null /*disabledPkg*/,
testUserSetting01 /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
null /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
@@ -609,7 +603,6 @@ public class PackageManagerSettingsTests {
null /*realPkgName*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
UPDATED_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
@@ -624,12 +617,11 @@ public class PackageManagerSettingsTests {
null /*usesStaticLibraries*/,
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.getCodePath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM));
assertThat(testPkgSetting01.pkgPrivateFlags, is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
assertThat(testPkgSetting01.resourcePath, is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
// signatures object must be different
assertNotSame(testPkgSetting01.signatures, originalSignatures);
@@ -649,7 +641,6 @@ public class PackageManagerSettingsTests {
null /*realPkgName*/,
null /*sharedUser*/,
INITIAL_CODE_PATH /*codePath*/,
INITIAL_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
@@ -665,12 +656,11 @@ public class PackageManagerSettingsTests {
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.appId, is(0));
assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.getCodePath(), is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(0));
assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
assertThat(testPkgSetting01.primaryCpuAbiString, is("x86_64"));
assertThat(testPkgSetting01.resourcePath, is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.secondaryCpuAbiString, is("x86"));
assertThat(testPkgSetting01.versionCode, is(INITIAL_VERSION_CODE));
// by default, the package is considered stopped
@@ -695,7 +685,6 @@ public class PackageManagerSettingsTests {
null /*realPkgName*/,
testUserSetting01 /*sharedUser*/,
INITIAL_CODE_PATH /*codePath*/,
INITIAL_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
@@ -711,12 +700,11 @@ public class PackageManagerSettingsTests {
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.appId, is(10064));
assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.getCodePath(), is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(0));
assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
assertThat(testPkgSetting01.primaryCpuAbiString, is("x86_64"));
assertThat(testPkgSetting01.resourcePath, is(INITIAL_CODE_PATH));
assertThat(testPkgSetting01.secondaryCpuAbiString, is("x86"));
assertThat(testPkgSetting01.versionCode, is(INITIAL_VERSION_CODE));
final PackageUserState userState = testPkgSetting01.readUserState(0);
@@ -738,7 +726,6 @@ public class PackageManagerSettingsTests {
null /*realPkgName*/,
null /*sharedUser*/,
UPDATED_CODE_PATH /*codePath*/,
UPDATED_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPath*/,
"arm64-v8a" /*primaryCpuAbi*/,
"armeabi" /*secondaryCpuAbi*/,
@@ -754,12 +741,11 @@ public class PackageManagerSettingsTests {
null /*usesStaticLibrariesVersions*/,
null /*mimeGroups*/);
assertThat(testPkgSetting01.appId, is(10064));
assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.getCodePath(), is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
assertThat(testPkgSetting01.pkgFlags, is(0));
assertThat(testPkgSetting01.pkgPrivateFlags, is(0));
assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
assertThat(testPkgSetting01.resourcePath, is(UPDATED_CODE_PATH));
assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
assertNotSame(testPkgSetting01.signatures, disabledSignatures);
assertThat(testPkgSetting01.versionCode, is(UPDATED_VERSION_CODE));
@@ -806,10 +792,10 @@ public class PackageManagerSettingsTests {
private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) {
assertThat(origPkgSetting, is(not(testPkgSetting)));
assertThat(origPkgSetting.appId, is(testPkgSetting.appId));
assertSame(origPkgSetting.codePath, testPkgSetting.codePath);
assertThat(origPkgSetting.codePath, is(testPkgSetting.codePath));
assertSame(origPkgSetting.codePathString, testPkgSetting.codePathString);
assertThat(origPkgSetting.codePathString, is(testPkgSetting.codePathString));
assertSame(origPkgSetting.getCodePath(), testPkgSetting.getCodePath());
assertThat(origPkgSetting.getCodePath(), is(testPkgSetting.getCodePath()));
assertSame(origPkgSetting.getCodePathString(), testPkgSetting.getCodePathString());
assertThat(origPkgSetting.getCodePathString(), is(testPkgSetting.getCodePathString()));
assertSame(origPkgSetting.cpuAbiOverrideString, testPkgSetting.cpuAbiOverrideString);
assertThat(origPkgSetting.cpuAbiOverrideString, is(testPkgSetting.cpuAbiOverrideString));
assertThat(origPkgSetting.firstInstallTime, is(testPkgSetting.firstInstallTime));
@@ -823,7 +809,9 @@ public class PackageManagerSettingsTests {
testPkgSetting.legacyNativeLibraryPathString);
assertThat(origPkgSetting.legacyNativeLibraryPathString,
is(testPkgSetting.legacyNativeLibraryPathString));
assertNotSame(origPkgSetting.mimeGroups, testPkgSetting.mimeGroups);
if (origPkgSetting.mimeGroups != null) {
assertNotSame(origPkgSetting.mimeGroups, testPkgSetting.mimeGroups);
}
assertThat(origPkgSetting.mimeGroups, is(testPkgSetting.mimeGroups));
assertNotSame(origPkgSetting.mPermissionsState, testPkgSetting.mPermissionsState);
assertThat(origPkgSetting.mPermissionsState, is(testPkgSetting.mPermissionsState));
@@ -839,10 +827,6 @@ public class PackageManagerSettingsTests {
assertSame(origPkgSetting.primaryCpuAbiString, testPkgSetting.primaryCpuAbiString);
assertThat(origPkgSetting.primaryCpuAbiString, is(testPkgSetting.primaryCpuAbiString));
assertThat(origPkgSetting.realName, is(testPkgSetting.realName));
assertSame(origPkgSetting.resourcePath, testPkgSetting.resourcePath);
assertThat(origPkgSetting.resourcePath, is(testPkgSetting.resourcePath));
assertSame(origPkgSetting.resourcePathString, testPkgSetting.resourcePathString);
assertThat(origPkgSetting.resourcePathString, is(testPkgSetting.resourcePathString));
assertSame(origPkgSetting.secondaryCpuAbiString, testPkgSetting.secondaryCpuAbiString);
assertThat(origPkgSetting.secondaryCpuAbiString, is(testPkgSetting.secondaryCpuAbiString));
assertSame(origPkgSetting.sharedUser, testPkgSetting.sharedUser);
@@ -874,7 +858,6 @@ public class PackageManagerSettingsTests {
PACKAGE_NAME,
REAL_PACKAGE_NAME,
INITIAL_CODE_PATH /*codePath*/,
INITIAL_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPathString*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,
@@ -893,7 +876,6 @@ public class PackageManagerSettingsTests {
packageName,
packageName,
INITIAL_CODE_PATH /*codePath*/,
INITIAL_CODE_PATH /*resourcePath*/,
null /*legacyNativeLibraryPathString*/,
"x86_64" /*primaryCpuAbiString*/,
"x86" /*secondaryCpuAbiString*/,

View File

@@ -312,8 +312,7 @@ public class PackageParserTest {
private static PackageSetting mockPkgSetting(AndroidPackage pkg) {
return new PackageSetting(pkg.getPackageName(), pkg.getRealPackage(),
new File(pkg.getCodePath()), new File(pkg.getCodePath()), null,
pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(),
new File(pkg.getCodePath()), null, pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(),
null, pkg.getVersionCode(),
PackageInfoUtils.appInfoFlags(pkg, null),
PackageInfoUtils.appInfoPrivateFlags(pkg, null),

View File

@@ -30,7 +30,6 @@ public class PackageSettingBuilder {
private String mName;
private String mRealName;
private String mCodePath;
private String mResourcePath;
private String mLegacyNativeLibraryPathString;
private String mPrimaryCpuAbiString;
private String mSecondaryCpuAbiString;
@@ -74,11 +73,6 @@ public class PackageSettingBuilder {
return this;
}
public PackageSettingBuilder setResourcePath(String resourcePath) {
this.mResourcePath = resourcePath;
return this;
}
public PackageSettingBuilder setLegacyNativeLibraryPathString(
String legacyNativeLibraryPathString) {
this.mLegacyNativeLibraryPathString = legacyNativeLibraryPathString;
@@ -162,10 +156,10 @@ public class PackageSettingBuilder {
public PackageSetting build() {
final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
new File(mCodePath), new File(mResourcePath),
mLegacyNativeLibraryPathString, mPrimaryCpuAbiString, mSecondaryCpuAbiString,
mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mSharedUserId,
mUsesStaticLibraries, mUsesStaticLibrariesVersions, mMimeGroups);
new File(mCodePath), mLegacyNativeLibraryPathString, mPrimaryCpuAbiString,
mSecondaryCpuAbiString, mCpuAbiOverrideString, mPVersionCode, mPkgFlags,
mPrivateFlags, mSharedUserId, mUsesStaticLibraries, mUsesStaticLibrariesVersions,
mMimeGroups);
packageSetting.signatures = mSigningDetails != null
? new PackageSignatures(mSigningDetails)
: new PackageSignatures();

View File

@@ -465,9 +465,9 @@ public class PackageSignaturesTest {
// Generic PackageSetting object with values from a test app installed on a device to be
// used to test the methods under the PackageSignatures signatures data member.
File appPath = new File("/data/app/app");
PackageSetting result = new PackageSetting("test.app", null, appPath, appPath,
"/data/app/app", null, null, null,
1, 940097092, 0, 0 /*userId*/, null, null, null /*mimeGroups*/);
PackageSetting result = new PackageSetting("test.app", null, appPath,
"/data/app/app", null, null, null, 1, 940097092, 0, 0 /*userId*/, null, null,
null /*mimeGroups*/);
return result;
}
}

View File

@@ -484,8 +484,7 @@ public class ScanTests {
private static PackageSettingBuilder createBasicPackageSettingBuilder(String packageName) {
return new PackageSettingBuilder()
.setName(packageName)
.setCodePath(createCodePath(packageName))
.setResourcePath(createCodePath(packageName));
.setCodePath(createCodePath(packageName));
}
private static ScanRequestBuilder createBasicScanRequestBuilder(ParsingPackage pkg) {
@@ -534,8 +533,7 @@ public class ScanTests {
arrayContaining("some.static.library", "some.other.static.library"));
assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L}));
assertThat(pkgSetting.pkg, is(scanResult.request.parsedPackage));
assertThat(pkgSetting.codePath, is(new File(createCodePath(packageName))));
assertThat(pkgSetting.resourcePath, is(new File(createCodePath(packageName))));
assertThat(pkgSetting.getCodePath(), is(new File(createCodePath(packageName))));
assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345)));
}

View File

@@ -34,6 +34,8 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import javax.annotation.Nullable;
@@ -49,7 +51,7 @@ import javax.annotation.Nullable;
public class SystemPreparer extends ExternalResource {
private static final long OVERLAY_ENABLE_TIMEOUT_MS = 30000;
// The paths of the files pushed onto the device through this rule.
// The paths of the files pushed onto the device through this rule to be removed after.
private ArrayList<String> mPushedFiles = new ArrayList<>();
// The package names of packages installed through this rule.
@@ -81,7 +83,7 @@ public class SystemPreparer extends ExternalResource {
final ITestDevice device = mDeviceProvider.getDevice();
remount();
assertTrue(device.pushFile(copyResourceToTemp(filePath), outputPath));
mPushedFiles.add(outputPath);
addPushedFile(device, outputPath);
return this;
}
@@ -91,10 +93,23 @@ public class SystemPreparer extends ExternalResource {
final ITestDevice device = mDeviceProvider.getDevice();
remount();
assertTrue(device.pushFile(file, outputPath));
mPushedFiles.add(outputPath);
addPushedFile(device, outputPath);
return this;
}
private void addPushedFile(ITestDevice device, String outputPath)
throws DeviceNotAvailableException {
Path pathCreated = Paths.get(outputPath);
// Find the top most parent that is new to the device
while (pathCreated.getParent() != null
&& !device.doesFileExist(pathCreated.getParent().toString())) {
pathCreated = pathCreated.getParent();
}
mPushedFiles.add(pathCreated.toString());
}
/** Deletes the given path from the device */
public SystemPreparer deleteFile(String file) throws DeviceNotAvailableException {
final ITestDevice device = mDeviceProvider.getDevice();
@@ -203,7 +218,7 @@ public class SystemPreparer extends ExternalResource {
/** Removes installed packages and files that were pushed to the device. */
@Override
protected void after() {
public void after() {
final ITestDevice device = mDeviceProvider.getDevice();
try {
remount();