Merge changes I4ee2affc,I81577500
* changes: Fix uninstall/disable with multi-user compressed stubs Refactor PackageSetting codePath and remove resourcePath
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)",
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
|
||||
@@ -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"
|
||||
/>
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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*/);
|
||||
}
|
||||
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
@@ -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*/,
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user