Merge changes from topic "apex-installers-restriction" into sc-dev am: e8b129351c

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15347597

Change-Id: I744b1572ff539ff8e34c2551e48f0d0efe538a2a
This commit is contained in:
Nikita Ioffe
2021-07-22 17:21:23 +00:00
committed by Automerger Merge Worker
6 changed files with 120 additions and 0 deletions

View File

@@ -2260,6 +2260,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
return;
}
}
if (!params.isStaged) {
// For non-staged APEX installs also check if there is a staged session that
// contains the same APEX. If that's the case, we should fail this session.
synchronized (mLock) {
int sessionId = mStagingManager.getSessionIdByPackageName(mPackageName);
if (sessionId != -1) {
onSessionValidationFailure(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
"Staged session " + sessionId + " already contains "
+ mPackageName);
return;
}
}
}
}
if (params.isStaged) {

View File

@@ -777,6 +777,26 @@ public class StagingManager {
}
}
/**
* Returns id of a committed and non-finalized stated session that contains same
* {@code packageName}, or {@code -1} if no sessions have this {@code packageName} staged.
*/
int getSessionIdByPackageName(@NonNull String packageName) {
synchronized (mStagedSessions) {
for (int i = 0; i < mStagedSessions.size(); i++) {
StagedSession stagedSession = mStagedSessions.valueAt(i);
if (!stagedSession.isCommitted() || stagedSession.isDestroyed()
|| stagedSession.isInTerminalState()) {
continue;
}
if (stagedSession.getPackageName().equals(packageName)) {
return stagedSession.sessionId();
}
}
}
return -1;
}
@VisibleForTesting
void createSession(@NonNull StagedSession sessionInfo) {
synchronized (mStagedSessions) {

View File

@@ -459,6 +459,66 @@ public class StagingManagerTest {
assertThat(apkSession.getErrorMessage()).isEqualTo("Another apex session failed");
}
@Test
public void getSessionIdByPackageName() throws Exception {
FakeStagedSession session = new FakeStagedSession(239);
session.setCommitted(true);
session.setSessionReady();
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(239);
}
@Test
public void getSessionIdByPackageName_appliedSession_ignores() throws Exception {
FakeStagedSession session = new FakeStagedSession(37);
session.setCommitted(true);
session.setSessionApplied();
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_failedSession_ignores() throws Exception {
FakeStagedSession session = new FakeStagedSession(73);
session.setCommitted(true);
session.setSessionFailed(1, "whatevs");
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_destroyedSession_ignores() throws Exception {
FakeStagedSession session = new FakeStagedSession(23);
session.setCommitted(true);
session.setDestroyed(true);
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_noSessions() throws Exception {
assertThat(mStagingManager.getSessionIdByPackageName("com.foo")).isEqualTo(-1);
}
@Test
public void getSessionIdByPackageName_noSessionHasThisPackage() throws Exception {
FakeStagedSession session = new FakeStagedSession(37);
session.setCommitted(true);
session.setSessionApplied();
session.setPackageName("com.foo");
mStagingManager.createSession(session);
assertThat(mStagingManager.getSessionIdByPackageName("com.bar")).isEqualTo(-1);
}
private StagingManager.StagedSession createSession(int sessionId, String packageName,
long committedMillis) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(

View File

@@ -32,6 +32,7 @@ android_test_helper_app {
test_suites: ["general-tests"],
java_resources: [
":com.android.apex.apkrollback.test_v2",
":StagedInstallTestApexV2",
":StagedInstallTestApexV2_WrongSha",
":test.rebootless_apex_v1",
":test.rebootless_apex_v2",

View File

@@ -57,6 +57,9 @@ public class StagedInstallInternalTest {
private static final TestApp APEX_WRONG_SHA_V2 = new TestApp(
"ApexWrongSha2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
"com.android.apex.cts.shim.v2_wrong_sha.apex");
private static final TestApp APEX_V2 = new TestApp(
"ApexV2", SHIM_APEX_PACKAGE_NAME, 2, /* isApex= */ true,
"com.android.apex.cts.shim.v2.apex");
private File mTestStateFile = new File(
InstrumentationRegistry.getInstrumentation().getContext().getFilesDir(),
@@ -388,6 +391,19 @@ public class StagedInstallInternalTest {
}
}
@Test
public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
assertThat(InstallUtils.getInstalledVersion(SHIM_APEX_PACKAGE_NAME)).isEqualTo(1);
int sessionId = Install.single(APEX_V2).setStaged().commit();
assertSessionReady(sessionId);
InstallUtils.commitExpectingFailure(
AssertionError.class,
"Staged session " + sessionId + " already contains " + SHIM_APEX_PACKAGE_NAME,
Install.single(APEX_V2));
}
private static void assertSessionApplied(int sessionId) {
assertSessionState(sessionId, (session) -> {
assertThat(session.isStagedSessionApplied()).isTrue();

View File

@@ -470,6 +470,14 @@ public class StagedInstallInternalTest extends BaseHostJUnit4Test {
runPhase("testRebootlessUpdates");
}
@Test
public void testRebootlessUpdate_hasStagedSessionWithSameApex_fails() throws Exception {
assumeTrue("Device does not support updating APEX",
mHostUtils.isApexUpdateSupported());
runPhase("testRebootlessUpdate_hasStagedSessionWithSameApex_fails");
}
private List<String> getStagingDirectories() throws DeviceNotAvailableException {
String baseDir = "/data/app-staging";
try {