On reboot session handling.
- re-seal regular sessions,
- re-seal+validate APEX sessions.
Previously we were validating them as well. This is unnecessary as
validation will happen on commit/transfer calls later.
This was introduced in 43f1af9dd9 when we
were using mSealed flag for both sealing and validation. It's not the
case anymore and we can safely deffer validation to commit/transfer.
Test: atest PackageManagerShellCommandTest SplitTests StagedRollbackTest CtsAtomicInstallTestCases PackageInstallerSessionTest InstallSessionTransferTest
Bug: b/136132412
Change-Id: I1ccb29ad41e25561f4f54ea51da3b9a725dd5647
This commit is contained in:
@@ -402,10 +402,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
|
||||
} finally {
|
||||
IoUtils.closeQuietly(fis);
|
||||
}
|
||||
// After all of the sessions were loaded, they are ready to be sealed and validated
|
||||
// After reboot housekeeping.
|
||||
for (int i = 0; i < mSessions.size(); ++i) {
|
||||
PackageInstallerSession session = mSessions.valueAt(i);
|
||||
session.sealAndValidateIfNecessary();
|
||||
session.onAfterSessionRead();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
// TODO(b/146080380): merge file list with Callback installation.
|
||||
private IncrementalFileStorages mIncrementalFileStorages;
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[]{};
|
||||
|
||||
private static final FileFilter sAddedFilter = new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
@@ -713,7 +715,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
@GuardedBy("mLock")
|
||||
private String[] getNamesLocked() {
|
||||
if (!isDataLoaderInstallation()) {
|
||||
return stageDir.list();
|
||||
String[] result = stageDir.list();
|
||||
if (result == null) {
|
||||
result = EMPTY_STRING_ARRAY;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return mFiles.stream().map(fileInfo -> fileInfo.name).toArray(String[]::new);
|
||||
}
|
||||
@@ -1339,7 +1345,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
|
||||
prepareDataLoader();
|
||||
|
||||
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
|
||||
if (isApexInstallation()) {
|
||||
validateApexInstallLocked();
|
||||
} else {
|
||||
validateApkInstallLocked(pkgInfo);
|
||||
@@ -1370,15 +1376,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
|
||||
/**
|
||||
* If session should be sealed, then it's sealed to prevent further modification
|
||||
* and then it's validated.
|
||||
* If session should be sealed, then it's sealed to prevent further modification.
|
||||
* If the session can't be sealed then it's destroyed.
|
||||
*
|
||||
* If the session was sealed but something went wrong then it's destroyed.
|
||||
* Additionally for staged APEX sessions read+validate the package and populate req'd fields.
|
||||
*
|
||||
* <p> This is meant to be called after all of the sessions are loaded and added to
|
||||
* PackageInstallerService
|
||||
*/
|
||||
void sealAndValidateIfNecessary() {
|
||||
void onAfterSessionRead() {
|
||||
synchronized (mLock) {
|
||||
if (!mShouldBeSealed || isStagedAndInTerminalState()) {
|
||||
return;
|
||||
@@ -1387,9 +1393,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
List<PackageInstallerSession> childSessions = getChildSessions();
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
sealAndValidateLocked(childSessions);
|
||||
} catch (StreamingException e) {
|
||||
Slog.e(TAG, "Streaming failed", e);
|
||||
sealLocked(childSessions);
|
||||
|
||||
if (isApexInstallation()) {
|
||||
// APEX installations rely on certain fields to be populated after reboot.
|
||||
// E.g. mPackageName.
|
||||
validateApexInstallLocked();
|
||||
}
|
||||
} catch (PackageManagerException e) {
|
||||
Slog.e(TAG, "Package not valid", e);
|
||||
}
|
||||
@@ -1465,7 +1475,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
|
||||
if (isApexInstallation()) {
|
||||
destroyInternal();
|
||||
dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
|
||||
"APEX packages can only be installed using staged sessions.", null);
|
||||
@@ -1549,7 +1559,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
}
|
||||
|
||||
final IPackageInstallObserver2 localObserver;
|
||||
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
|
||||
if (isApexInstallation()) {
|
||||
localObserver = null;
|
||||
} else {
|
||||
if (!params.isMultiPackage) {
|
||||
@@ -1683,6 +1693,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
|
||||
(params.installFlags & PackageManager.DONT_KILL_APP) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the session is installing an APEX package.
|
||||
*/
|
||||
private boolean isApexInstallation() {
|
||||
return (params.installFlags & PackageManager.INSTALL_APEX) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate apex install.
|
||||
* <p>
|
||||
|
||||
Reference in New Issue
Block a user