From bb981e391cffbccc0b5592851932c904e134199b Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Thu, 6 Jun 2019 14:01:41 +0100 Subject: [PATCH 01/14] Reduce ENABLE_ROLLBACK timeout to 0 for timeout test. testEnableRollbackTimeoutFailsRollback works by setting the enable rollback timeout to 1 millisecond so that we will always time out, but the test is failing some times because apparently we enable rollback within the 1 millisecond limit. Reduce the timeout to 0 milliseconds to try and reduce test flakiness. Before lowering the timeout, the test failure was easy to reproduce locally. After lowering the timeout I have not once been able to reproduce the test failure locally. Bug: 134373106 Test: atest RollbackTest:com.android.tests.rollback.RollbackTest#testEnableRollbackTimeoutFailsRollback Change-Id: I44f9e786d2a2285475ee423e34d06f5b5a5271e1 Merged-In: Ia25561831616dd2f2644743a399b49e35d5d4ea4 --- .../src/com/android/tests/rollback/RollbackTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 1b002cadb07fc..09a9b9b0319e9 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -35,7 +35,6 @@ import android.content.pm.VersionedPackage; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.provider.DeviceConfig; -import android.provider.Settings; import android.util.Log; import androidx.test.InstrumentationRegistry; @@ -973,7 +972,7 @@ public class RollbackTest { //setting the timeout to a very short amount that will definitely be triggered DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS, - Long.toString(1), false /* makeDefault*/); + Long.toString(0), false /* makeDefault*/); RollbackManager rm = RollbackTestUtils.getRollbackManager(); RollbackTestUtils.uninstall(TEST_APP_A); From f25aed466801ff743ed0fdcfd26971d36fcc8fea Mon Sep 17 00:00:00 2001 From: shafik Date: Thu, 30 May 2019 15:15:43 +0100 Subject: [PATCH 02/14] Add host side test for secondary user rollback Run RollbackTest#testBasic only under a secondary user. The host-driven test adds a new user and then installs the TEST (not the test app) for that new user. Note: this was the missing step in the previous attempt to test RollbackTest under a secondary user. Test: atest SecondaryUserRollbackTest Test: test failed when multiuser support was removed from rollback manager Test: adb shell pm list packages --user 11 | grep rollback while running the test in order to make sure the test is installing packages for the right user Bug: 133852817 Bug: 129747710 Change-Id: I9e13f2cdaf825a53846765fa52bc425045f41df1 Merged-In: Id1e54769cc2a9631d1464c07bad2b685f78689bc --- .../com/android/server/rollback/TEST_MAPPING | 9 +- tests/RollbackTest/Android.bp | 8 ++ .../android/tests/rollback/RollbackTest.java | 12 ++- .../SecondaryUserRollbackTest.xml | 25 +++++ .../host/SecondaryUserRollbackTest.java | 92 +++++++++++++++++++ tests/RollbackTest/TEST_MAPPING | 3 + 6 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 tests/RollbackTest/SecondaryUserRollbackTest.xml create mode 100644 tests/RollbackTest/SecondaryUserRollbackTest/src/com/android/tests/rollback/host/SecondaryUserRollbackTest.java diff --git a/services/core/java/com/android/server/rollback/TEST_MAPPING b/services/core/java/com/android/server/rollback/TEST_MAPPING index 8c7b5acf5c3ab..2cc931bfac5b1 100644 --- a/services/core/java/com/android/server/rollback/TEST_MAPPING +++ b/services/core/java/com/android/server/rollback/TEST_MAPPING @@ -1,11 +1,5 @@ { "presubmit": [ - { - "name": "RollbackTest" - }, - { - "name": "StagedRollbackTest" - }, { "name": "FrameworksServicesTests", "options": [ @@ -21,6 +15,9 @@ }, { "path": "cts/hostsidetests/rollback" + }, + { + "path": "frameworks/base/tests/RollbackTest" } ] } diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp index aec40558ad51e..5172935e60744 100644 --- a/tests/RollbackTest/Android.bp +++ b/tests/RollbackTest/Android.bp @@ -105,3 +105,11 @@ java_test_host { test_suites: ["general-tests"], test_config: "StagedRollbackTest.xml", } + +java_test_host { + name: "SecondaryUserRollbackTest", + srcs: ["SecondaryUserRollbackTest/src/**/*.java"], + libs: ["tradefed"], + test_suites: ["general-tests"], + test_config: "SecondaryUserRollbackTest.xml", +} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 09a9b9b0319e9..4665d63037c97 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -147,9 +147,15 @@ public class RollbackTest { // TODO: Race condition between the timeout and when the broadcast is // received could lead to test flakiness. Intent broadcast = broadcastReceiver.poll(5, TimeUnit.SECONDS); - assertNotNull(broadcast); - assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS)); - + if (context.getUser().isSystem()) { + // Only system user should receive those broadcasts. + assertNotNull(broadcast); + assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS)); + } else { + // This is in case the test was running under a secondary user, in which case + // the broadcast won't be received here. + assertNull(broadcast); + } // Verify the recent rollback has been recorded. rollback = getUniqueRollbackInfoForPackage( rm.getRecentlyCommittedRollbacks(), TEST_APP_A); diff --git a/tests/RollbackTest/SecondaryUserRollbackTest.xml b/tests/RollbackTest/SecondaryUserRollbackTest.xml new file mode 100644 index 0000000000000..ad3761018a255 --- /dev/null +++ b/tests/RollbackTest/SecondaryUserRollbackTest.xml @@ -0,0 +1,25 @@ + + + + diff --git a/tests/RollbackTest/SecondaryUserRollbackTest/src/com/android/tests/rollback/host/SecondaryUserRollbackTest.java b/tests/RollbackTest/SecondaryUserRollbackTest/src/com/android/tests/rollback/host/SecondaryUserRollbackTest.java new file mode 100644 index 0000000000000..11fe964229d72 --- /dev/null +++ b/tests/RollbackTest/SecondaryUserRollbackTest/src/com/android/tests/rollback/host/SecondaryUserRollbackTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2019 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.tests.rollback.host; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Runs rollback tests from a secondary user. + */ +@RunWith(DeviceJUnit4ClassRunner.class) +public class SecondaryUserRollbackTest extends BaseHostJUnit4Test { + private static final int SYSTEM_USER_ID = 0; + // The user that was running originally when the test starts. + private int mOriginalUser = SYSTEM_USER_ID; + private int mSecondaryUserId = -1; + private static final long SWITCH_USER_COMPLETED_NUMBER_OF_POLLS = 60; + private static final long SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS = 1000; + + + @After + public void tearDown() throws Exception { + getDevice().switchUser(mOriginalUser); + getDevice().executeShellCommand("pm uninstall com.android.tests.rollback.testapp.A"); + getDevice().executeShellCommand("pm uninstall com.android.tests.rollback.testapp.B"); + removeSecondaryUserIfNecessary(); + } + + @Before + public void setup() throws Exception { + createAndSwitchToSecondaryUserIfNecessary(); + installPackageAsUser("RollbackTest.apk", true, mSecondaryUserId, "--user current"); + } + + @Test + public void testBasic() throws Exception { + assertTrue(runDeviceTests("com.android.tests.rollback", + "com.android.tests.rollback.RollbackTest", + "testBasic")); + } + + private void removeSecondaryUserIfNecessary() throws Exception { + if (mSecondaryUserId != -1) { + getDevice().removeUser(mSecondaryUserId); + mSecondaryUserId = -1; + } + } + + private void createAndSwitchToSecondaryUserIfNecessary() throws Exception { + if (mSecondaryUserId == -1) { + mOriginalUser = getDevice().getCurrentUser(); + mSecondaryUserId = getDevice().createUser("SecondaryUserRollbackTest_User"); + assertTrue(getDevice().switchUser(mSecondaryUserId)); + // give time for user to be switched + waitForSwitchUserCompleted(mSecondaryUserId); + } + } + + private void waitForSwitchUserCompleted(int userId) throws Exception { + for (int i = 0; i < SWITCH_USER_COMPLETED_NUMBER_OF_POLLS; ++i) { + String logs = getDevice().executeAdbCommand("logcat", "-v", "brief", "-d", + "ActivityManager:D"); + if (logs.contains("Posting BOOT_COMPLETED user #" + userId)) { + return; + } + Thread.sleep(SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS); + } + fail("User switch to user " + userId + " timed out"); + } +} diff --git a/tests/RollbackTest/TEST_MAPPING b/tests/RollbackTest/TEST_MAPPING index 6be93a0a199b6..7ae03e68decc4 100644 --- a/tests/RollbackTest/TEST_MAPPING +++ b/tests/RollbackTest/TEST_MAPPING @@ -5,6 +5,9 @@ }, { "name": "StagedRollbackTest" + }, + { + "name": "SecondaryUserRollbackTest" } ] } From 73f1771d27f3268d7bd1348fff689ac4bf5a3f02 Mon Sep 17 00:00:00 2001 From: Mohammad Samiul Islam Date: Fri, 5 Jul 2019 14:47:17 +0100 Subject: [PATCH 03/14] Add .apex suffix to apex files during validation Previously, the apex file being installed was moved into the staging directory as same name provided during installation, due to which, when the source apex file of installation did not have .apex suffix in its file name, it failed validation in apexd. Now, if an apex file does not have proper suffix, it will be concatenated during validation in PackageInstallerSession. Bug: 124837227 Test: atest CtsStagedInstallHostTestCases Test: atest StagedInstallTest#testInstallStagedApexWithoutApexSuffix Exempt-From-Owner-Approval: Already approved in https://googleplex-android-review.git.corp.google.com/c/platform/frameworks/base/+/8528906 Change-Id: I0095c1f985839de8247d9e6aebae948e0e834e7e Merged-In: Ice41f601dc42736ca0cdf2bad0817f0c00f50648 --- .../android/content/pm/PackageParser.java | 2 ++ .../server/pm/PackageInstallerSession.java | 25 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 5c5c13d566c58..c53b644449254 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -254,6 +254,8 @@ public class PackageParser { /** @hide */ public static final String APK_FILE_EXTENSION = ".apk"; + /** @hide */ + public static final String APEX_FILE_EXTENSION = ".apex"; /** @hide */ public static class NewPermissionInfo { diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6f9a918d105c9..4eddb9301a69f 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -23,6 +23,7 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STOR import static android.content.pm.PackageManager.INSTALL_FAILED_INTERNAL_ERROR; import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK; import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SPLIT; +import static android.content.pm.PackageParser.APEX_FILE_EXTENSION; import static android.content.pm.PackageParser.APK_FILE_EXTENSION; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDONLY; @@ -1484,7 +1485,29 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { "Too many files for apex install"); } - mResolvedBaseFile = addedFiles[0]; + try { + resolveStageDirLocked(); + } catch (IOException e) { + throw new PackageManagerException(INSTALL_FAILED_CONTAINER_ERROR, + "Failed to resolve stage location", e); + } + + File addedFile = addedFiles[0]; // there is only one file + + // Ensure file name has proper suffix + final String sourceName = addedFile.getName(); + final String targetName = sourceName.endsWith(APEX_FILE_EXTENSION) + ? sourceName + : sourceName + APEX_FILE_EXTENSION; + if (!FileUtils.isValidExtFilename(targetName)) { + throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, + "Invalid filename: " + targetName); + } + + final File targetFile = new File(mResolvedStageDir, targetName); + resolveAndStageFile(addedFile, targetFile); + + mResolvedBaseFile = targetFile; } /** From af4df0e7c6fc49bdd919ca005f9efd99d07e90b2 Mon Sep 17 00:00:00 2001 From: shafik Date: Thu, 6 Jun 2019 19:16:39 +0100 Subject: [PATCH 04/14] Migrate RollbackTest and StagedRollbackTest to cts utils Replace the usage of RollbackTestUtils with the API offered by com.android.cts.install.lib and com.android.cts.rollback.lib. Test: atest RollbackTest Test: atest StagedRollbackTest #testBadApkOnly Bug: 132757394 Bug: 132422403 Change-Id: I1d6789b4fb7ae94ebf7066a6fd215e4ac48c04df Merged-In: I25cb9dca103852d7ee3691e4df927e1fc5848074 --- tests/RollbackTest/Android.bp | 78 +- .../RollbackTest/AndroidManifest.xml | 2 +- .../tests/rollback/LocalIntentSender.java | 60 -- .../rollback/RollbackBroadcastReceiver.java | 78 -- .../android/tests/rollback/RollbackTest.java | 739 ++++++++++-------- .../tests/rollback/RollbackTestUtils.java | 547 ------------- .../tests/rollback/StagedRollbackTest.java | 100 +-- tests/RollbackTest/TestApp/ACrashingV2.xml | 36 - tests/RollbackTest/TestApp/Av1.xml | 35 - tests/RollbackTest/TestApp/Av2.xml | 35 - tests/RollbackTest/TestApp/Av3.xml | 35 - tests/RollbackTest/TestApp/Bv1.xml | 35 - tests/RollbackTest/TestApp/Bv2.xml | 35 - .../TestApp/res_v1/values-anydpi/values.xml | 19 - .../TestApp/res_v1/values/values.xml | 20 - .../TestApp/res_v2/values-anydpi/values.xml | 19 - .../TestApp/res_v2/values/values.xml | 20 - .../TestApp/res_v3/values-anydpi/values.xml | 19 - .../TestApp/res_v3/values/values.xml | 20 - .../testapp/CrashingMainActivity.java | 46 -- .../tests/rollback/testapp/MainActivity.java | 37 - .../rollback/testapp/ProcessUserData.java | 111 --- 22 files changed, 455 insertions(+), 1671 deletions(-) delete mode 100644 tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java delete mode 100644 tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java delete mode 100644 tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java delete mode 100644 tests/RollbackTest/TestApp/ACrashingV2.xml delete mode 100644 tests/RollbackTest/TestApp/Av1.xml delete mode 100644 tests/RollbackTest/TestApp/Av2.xml delete mode 100644 tests/RollbackTest/TestApp/Av3.xml delete mode 100644 tests/RollbackTest/TestApp/Bv1.xml delete mode 100644 tests/RollbackTest/TestApp/Bv2.xml delete mode 100644 tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml delete mode 100644 tests/RollbackTest/TestApp/res_v1/values/values.xml delete mode 100644 tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml delete mode 100644 tests/RollbackTest/TestApp/res_v2/values/values.xml delete mode 100644 tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml delete mode 100644 tests/RollbackTest/TestApp/res_v3/values/values.xml delete mode 100644 tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java delete mode 100644 tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java delete mode 100644 tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp index 5172935e60744..2bd5931eccbe1 100644 --- a/tests/RollbackTest/Android.bp +++ b/tests/RollbackTest/Android.bp @@ -12,88 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -android_test_helper_app { - name: "RollbackTestAppAv1", - manifest: "TestApp/Av1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v1"], -} - -android_test_helper_app { - name: "RollbackTestAppAv2", - manifest: "TestApp/Av2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], -} - -android_test_helper_app { - name: "RollbackTestAppAv3", - manifest: "TestApp/Av3.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v3"], -} - -android_test_helper_app { - name: "RollbackTestAppACrashingV2", - manifest: "TestApp/ACrashingV2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], -} - -android_test_helper_app { - name: "RollbackTestAppBv1", - manifest: "TestApp/Bv1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v1"], -} - -android_test_helper_app { - name: "RollbackTestAppBv2", - manifest: "TestApp/Bv2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], -} - -android_test_helper_app { - name: "RollbackTestAppASplitV1", - manifest: "TestApp/Av1.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v1"], - package_splits: ["anydpi"], -} - -android_test_helper_app { - name: "RollbackTestAppASplitV2", - manifest: "TestApp/Av2.xml", - sdk_version: "current", - srcs: ["TestApp/src/**/*.java"], - resource_dirs: ["TestApp/res_v2"], - package_splits: ["anydpi"], -} - android_test { name: "RollbackTest", manifest: "RollbackTest/AndroidManifest.xml", srcs: ["RollbackTest/src/**/*.java"], - static_libs: ["androidx.test.rules"], + static_libs: ["androidx.test.rules", "cts-rollback-lib", "cts-install-lib"], test_suites: ["general-tests"], - java_resources: [ - ":RollbackTestAppAv1", - ":RollbackTestAppAv2", - ":RollbackTestAppAv3", - ":RollbackTestAppACrashingV2", - ":RollbackTestAppBv1", - ":RollbackTestAppBv2", - ":RollbackTestAppASplitV1", - ":RollbackTestAppASplitV2", - ], test_config: "RollbackTest.xml", // TODO: sdk_version: "test_current" when Intent#resolveSystemservice is TestApi } diff --git a/tests/RollbackTest/RollbackTest/AndroidManifest.xml b/tests/RollbackTest/RollbackTest/AndroidManifest.xml index 5380dc9fc8cdd..2b8c96484210e 100644 --- a/tests/RollbackTest/RollbackTest/AndroidManifest.xml +++ b/tests/RollbackTest/RollbackTest/AndroidManifest.xml @@ -18,7 +18,7 @@ package="com.android.tests.rollback" > - diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java deleted file mode 100644 index 267ef7377b36e..0000000000000 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/LocalIntentSender.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentSender; - -import androidx.test.InstrumentationRegistry; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * Make IntentSender that sends intent locally. - */ -public class LocalIntentSender extends BroadcastReceiver { - - private static final String TAG = "RollbackTest"; - - private static final BlockingQueue sIntentSenderResults = new LinkedBlockingQueue<>(); - - @Override - public void onReceive(Context context, Intent intent) { - sIntentSenderResults.add(intent); - } - - /** - * Get a LocalIntentSender. - */ - static IntentSender getIntentSender() { - Context context = InstrumentationRegistry.getContext(); - Intent intent = new Intent(context, LocalIntentSender.class); - PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, 0); - return pending.getIntentSender(); - } - - /** - * Returns the most recent Intent sent by a LocalIntentSender. - */ - static Intent getIntentSenderResult() throws InterruptedException { - return sIntentSenderResults.take(); - } -} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java deleted file mode 100644 index ebe54187ddb6a..0000000000000 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackBroadcastReceiver.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -/** - * A broadcast receiver that can be used to get - * ACTION_ROLLBACK_COMMITTED broadcasts. - */ -class RollbackBroadcastReceiver extends BroadcastReceiver { - - private static final String TAG = "RollbackTest"; - - private final BlockingQueue mRollbackBroadcasts = new LinkedBlockingQueue<>(); - - /** - * Creates a RollbackBroadcastReceiver and registers it with the given - * context. - */ - RollbackBroadcastReceiver() { - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_ROLLBACK_COMMITTED); - InstrumentationRegistry.getContext().registerReceiver(this, filter); - } - - @Override - public void onReceive(Context context, Intent intent) { - Log.i(TAG, "Received rollback broadcast intent"); - mRollbackBroadcasts.add(intent); - } - - /** - * Polls for at most the given amount of time for the next rollback - * broadcast. - */ - Intent poll(long timeout, TimeUnit unit) throws InterruptedException { - return mRollbackBroadcasts.poll(timeout, unit); - } - - /** - * Waits forever for the next rollback broadcast. - */ - Intent take() throws InterruptedException { - return mRollbackBroadcasts.take(); - } - - /** - * Unregisters this broadcast receiver. - */ - void unregister() { - InstrumentationRegistry.getContext().unregisterReceiver(this); - } -} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index 4665d63037c97..ebf09b848dabf 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -16,14 +16,12 @@ package com.android.tests.rollback; -import static com.android.tests.rollback.RollbackTestUtils.assertPackageRollbackInfoEquals; -import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals; -import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage; -import static com.android.tests.rollback.RollbackTestUtils.processUserData; +import static com.android.cts.install.lib.InstallUtils.processUserData; +import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat; +import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage; + +import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; import android.Manifest; @@ -31,7 +29,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.VersionedPackage; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import android.provider.DeviceConfig; @@ -39,6 +36,14 @@ import android.util.Log; import androidx.test.InstrumentationRegistry; +import com.android.cts.install.lib.Install; +import com.android.cts.install.lib.InstallUtils; +import com.android.cts.install.lib.TestApp; +import com.android.cts.install.lib.Uninstall; +import com.android.cts.rollback.lib.Rollback; +import com.android.cts.rollback.lib.RollbackBroadcastReceiver; +import com.android.cts.rollback.lib.RollbackUtils; + import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -56,8 +61,6 @@ public class RollbackTest { private static final String TAG = "RollbackTest"; - private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A"; - private static final String TEST_APP_B = "com.android.tests.rollback.testapp.B"; private static final String INSTRUMENTED_APP = "com.android.tests.rollback"; // copied from PackageManagerService#PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS @@ -87,7 +90,7 @@ public class RollbackTest { context.registerReceiver(enableRollbackReceiver, enableRollbackFilter); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -96,18 +99,18 @@ public class RollbackTest { // Register a broadcast receiver for notification when the // rollback has been committed. RollbackBroadcastReceiver broadcastReceiver = new RollbackBroadcastReceiver(); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - // Uninstall TEST_APP_A - RollbackTestUtils.uninstall(TEST_APP_A); - assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + // Uninstall TestApp.A + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); // TODO: There is currently a race condition between when the app is // uninstalled and when rollback manager deletes the rollback. Fix it // so that's not the case! for (int i = 0; i < 5; ++i) { RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TestApp.A); if (rollback != null) { Log.i(TAG, "Sleeping 1 second to wait for uninstall to take effect."); Thread.sleep(1000); @@ -115,33 +118,37 @@ public class RollbackTest { } // The app should not be available for rollback. - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); // There should be no recently committed rollbacks for this package. - assertNull(getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A)); + assertThat(getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A)).isNull(); // Install v1 of the app (without rollbacks enabled). - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Upgrade from v1 to v2, with rollbacks enabled. - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo available = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + assertThat(available).isNotNull(); + assertThat(available).isNotStaged(); + assertThat(available).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // We should not have received any rollback requests yet. // TODO: Possibly flaky if, by chance, some other app on device // happens to be rolled back at the same time? - assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS)); + assertThat(broadcastReceiver.poll(0, TimeUnit.SECONDS)).isNull(); // Roll back the app. - RollbackTestUtils.rollback(rollback.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackUtils.rollback(available.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Verify we received a broadcast for the rollback. // TODO: Race condition between the timeout and when the broadcast is @@ -149,22 +156,27 @@ public class RollbackTest { Intent broadcast = broadcastReceiver.poll(5, TimeUnit.SECONDS); if (context.getUser().isSystem()) { // Only system user should receive those broadcasts. - assertNotNull(broadcast); - assertNull(broadcastReceiver.poll(0, TimeUnit.SECONDS)); + assertThat(broadcast).isNotNull(); + assertThat(broadcastReceiver.poll(0, TimeUnit.SECONDS)).isNull(); } else { // This is in case the test was running under a secondary user, in which case // the broadcast won't be received here. - assertNull(broadcast); + assertThat(broadcast).isNull(); } + // Verify the recent rollback has been recorded. - rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + RollbackInfo committed = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committed).isNotNull(); + assertThat(committed).isNotStaged(); + assertThat(committed).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(committed).hasRollbackId(available.getRollbackId()); broadcastReceiver.unregister(); context.unregisterReceiver(enableRollbackReceiver); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -174,50 +186,58 @@ public class RollbackTest { @Test public void testAvailableRollbackPersistence() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.B); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback. RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollbackA).isNotNull(); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + rm.getAvailableRollbacks(), TestApp.B); + assertThat(rollbackB).isNotNull(); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Reload the persisted data. rm.reloadPersistedData(); // The apps should still be available for rollback. rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollbackA).isNotNull(); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + rm.getAvailableRollbacks(), TestApp.B); + assertThat(rollbackB).isNotNull(); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Rollback of B should not rollback A - RollbackTestUtils.rollback(rollbackB.getRollbackId()); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollbackB.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -227,49 +247,78 @@ public class RollbackTest { @Test public void testAvailableMultiPackageRollbackPersistence() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.installMultiPackage(false, - "RollbackTestAppAv1.apk", - "RollbackTestAppBv1.apk"); - RollbackTestUtils.installMultiPackage(true, - "RollbackTestAppAv2.apk", - "RollbackTestAppBv2.apk"); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.A, TestApp.B); + Install.multi(TestApp.A1, TestApp.B1).commit(); + Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit(); + + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoForAandB(rollbackA); + RollbackInfo availableA = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + assertThat(availableA).isNotNull(); + assertThat(availableA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); - RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoForAandB(rollbackB); + RollbackInfo availableB = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B); + assertThat(availableB).isNotNull(); + assertThat(availableB).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + // Assert they're both the same rollback + assertThat(availableA).hasRollbackId(availableB.getRollbackId()); // Reload the persisted data. rm.reloadPersistedData(); // The apps should still be available for rollback. - rollbackA = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoForAandB(rollbackA); + availableA = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A); + assertThat(availableA).isNotNull(); + assertThat(availableA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); - rollbackB = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoForAandB(rollbackB); + availableB = getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.B); + assertThat(availableB).isNotNull(); + assertThat(availableB).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); // Rollback of B should rollback A as well - RollbackTestUtils.rollback(rollbackB.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(availableB.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); + + RollbackInfo committedA = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committedA).isNotNull(); + assertThat(committedA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + RollbackInfo committedB = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committedB).isNotNull(); + assertThat(committedB).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); + + // Assert they're both the same rollback + assertThat(committedA).hasRollbackId(committedB.getRollbackId()); + assertThat(committedA).hasRollbackId(availableA.getRollbackId()); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -279,42 +328,50 @@ public class RollbackTest { @Test public void testRecentlyCommittedRollbackPersistence() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); + RollbackInfo available = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + assertThat(available).isNotNull(); // Roll back the app. - VersionedPackage cause = new VersionedPackage( - "com.android.tests.rollback.testapp.Foo", 42); - RollbackTestUtils.rollback(rollback.getRollbackId(), cause); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + TestApp cause = new TestApp("Foo", "com.android.tests.rollback.testapp.Foo", + /*versionCode*/ 42, /*isApex*/ false); + RollbackUtils.rollback(available.getRollbackId(), cause); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Verify the recent rollback has been recorded. - rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, cause); + RollbackInfo committed = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committed).isNotNull(); + assertThat(committed).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(committed).causePackagesContainsExactly(cause); // Reload the persisted data. rm.reloadPersistedData(); // Verify the recent rollback is still recorded. - rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, cause); + committed = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(committed).isNotNull(); + assertThat(committed).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(committed).causePackagesContainsExactly(cause); + assertThat(committed).hasRollbackId(available.getRollbackId()); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -325,10 +382,10 @@ public class RollbackTest { public void testRollbackExpiresAfterLifetime() throws Exception { long expirationTime = TimeUnit.SECONDS.toMillis(30); long defaultExpirationTime = TimeUnit.HOURS.toMillis(48); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -341,39 +398,45 @@ public class RollbackTest { // Pull the new expiration time from DeviceConfig rm.reloadPersistedData(); - // Uninstall TEST_APP_A - RollbackTestUtils.uninstall(TEST_APP_A); - assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + // Uninstall TestApp.A + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); // Install v1 of the app (without rollbacks enabled). - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Upgrade from v1 to v2, with rollbacks enabled. - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // Check that the rollback data has not expired Thread.sleep(1000); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Give it a little more time, but still not the long enough to expire Thread.sleep(expirationTime / 2); rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Check that the data has expired after the expiration time (with a buffer of 1 second) Thread.sleep(expirationTime / 2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNull(); } finally { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT, RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS, Long.toString(defaultExpirationTime), false /* makeDefault*/); - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -385,10 +448,10 @@ public class RollbackTest { public void testTimeChangeDoesNotAffectLifetime() throws Exception { long expirationTime = TimeUnit.SECONDS.toMillis(30); long defaultExpirationTime = TimeUnit.HOURS.toMillis(48); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -403,24 +466,25 @@ public class RollbackTest { rm.reloadPersistedData(); // Install app A with rollback enabled - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); Thread.sleep(expirationTime / 2); // Install app B with rollback enabled - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.B); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); + // 1 second buffer Thread.sleep(1000); try { // Change the time - RollbackTestUtils.forwardTimeBy(expirationTime); + RollbackUtils.forwardTimeBy(expirationTime); // 1 second buffer to allow Rollback Manager to handle time change before loading // persisted data @@ -432,24 +496,31 @@ public class RollbackTest { // Wait until rollback for app A has expired // This will trigger an expiration run that should expire app A but not B Thread.sleep(expirationTime / 2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + RollbackInfo rollback = + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNull(); // Rollback for app B should not be expired - RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollback); + rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Wait until rollback for app B has expired Thread.sleep(expirationTime / 2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_B)); + rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B); + // Rollback should be expired by now + assertThat(rollback).isNull(); } finally { - RollbackTestUtils.forwardTimeBy(-expirationTime); + RollbackUtils.forwardTimeBy(-expirationTime); } } finally { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK_BOOT, RollbackManager.PROPERTY_ROLLBACK_LIFETIME_MILLIS, Long.toString(defaultExpirationTime), false /* makeDefault*/); - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -460,30 +531,32 @@ public class RollbackTest { @Test public void testRollbackExpiration() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackManager rm = RollbackUtils.getRollbackManager(); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); // The app should now be available for rollback. RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Expire the rollback. - rm.expireRollbackForPackage(TEST_APP_A); + rm.expireRollbackForPackage(TestApp.A); // The rollback should no longer be available. - assertNull(getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A)); + assertThat(getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -493,24 +566,24 @@ public class RollbackTest { @Test public void testUserDataRollback() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - processUserData(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - processUserData(TEST_APP_A); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + processUserData(TestApp.A); + Install.single(TestApp.A2).setEnableRollback().commit(); + processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - RollbackTestUtils.rollback(rollback.getRollbackId()); - processUserData(TEST_APP_A); + rm.getAvailableRollbacks(), TestApp.A); + RollbackUtils.rollback(rollback.getRollbackId()); + processUserData(TestApp.A); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -520,30 +593,26 @@ public class RollbackTest { @Test public void testRollbackWithSplits() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.installSplit(false, - "RollbackTestAppASplitV1.apk", - "RollbackTestAppASplitV1_anydpi.apk"); - processUserData(TEST_APP_A); + Uninstall.packages(TestApp.A); + Install.single(TestApp.ASplit1).commit(); + processUserData(TestApp.A); - RollbackTestUtils.installSplit(true, - "RollbackTestAppASplitV2.apk", - "RollbackTestAppASplitV2_anydpi.apk"); - processUserData(TEST_APP_A); + Install.single(TestApp.ASplit2).setEnableRollback().commit(); + processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertNotNull(rollback); - RollbackTestUtils.rollback(rollback.getRollbackId()); - processUserData(TEST_APP_A); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + RollbackUtils.rollback(rollback.getRollbackId()); + processUserData(TestApp.A); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -564,7 +633,7 @@ public class RollbackTest { // Confirm that we really haven't received the broadcast. // TODO: How long to wait for the expected timeout? - assertNull(broadcastReceiver.poll(5, TimeUnit.SECONDS)); + assertThat(broadcastReceiver.poll(5, TimeUnit.SECONDS)).isNull(); // TODO: Do we need to do this? Do we need to ensure this is always // called, even when the test fails? @@ -578,48 +647,52 @@ public class RollbackTest { @Test public void testMultipleRollbackAvailable() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); // Prep installation of the test apps. - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.B); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback, and the // RollbackInfo returned for the rollbacks should be correct. RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollbackA).isNotNull(); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + rm.getAvailableRollbacks(), TestApp.B); + assertThat(rollbackB).isNotNull(); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Executing rollback should roll back the correct package. - RollbackTestUtils.rollback(rollbackA.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollbackA.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.rollback(rollbackB.getRollbackId()); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollbackB.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -631,7 +704,7 @@ public class RollbackTest { public void testManageRollbacksPermission() throws Exception { // We shouldn't be allowed to call any of the RollbackManager APIs // without the MANAGE_ROLLBACKS permission. - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); try { rm.getAvailableRollbacks(); @@ -664,7 +737,7 @@ public class RollbackTest { } try { - rm.expireRollbackForPackage(TEST_APP_A); + rm.expireRollbackForPackage(TestApp.A); fail("expected SecurityException"); } catch (SecurityException e) { // Expected. @@ -678,26 +751,27 @@ public class RollbackTest { @Test public void testEnableRollbackPermission() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); - RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true); + Install.single(TestApp.A2).setEnableRollback().commit(); // We expect v2 of the app was installed, but rollback has not // been enabled. - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -708,25 +782,26 @@ public class RollbackTest { @Test public void testNonModuleEnableRollback() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.MANAGE_ROLLBACKS); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", /* enableRollback */ false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); - RollbackTestUtils.install("RollbackTestAppAv2.apk", /* enableRollback */ true); + Install.single(TestApp.A2).setEnableRollback().commit(); // We expect v2 of the app was installed, but rollback has not // been enabled because the test app is not a module. - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -736,54 +811,54 @@ public class RollbackTest { @Test public void testMultiPackage() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); // Prep installation of the test apps. - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.installMultiPackage(false, - "RollbackTestAppAv1.apk", - "RollbackTestAppBv1.apk"); - processUserData(TEST_APP_A); - processUserData(TEST_APP_B); - RollbackTestUtils.installMultiPackage(true, - "RollbackTestAppAv2.apk", - "RollbackTestAppBv2.apk"); - processUserData(TEST_APP_A); - processUserData(TEST_APP_B); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Uninstall.packages(TestApp.A, TestApp.B); + Install.multi(TestApp.A1, TestApp.B1).commit(); + processUserData(TestApp.A); + processUserData(TestApp.B); + Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit(); + processUserData(TestApp.A); + processUserData(TestApp.B); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); - // TEST_APP_A should now be available for rollback. + // TestApp.A should now be available for rollback. RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoForAandB(rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); // Rollback the app. It should cause both test apps to be rolled // back. - RollbackTestUtils.rollback(rollback.getRollbackId()); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + RollbackUtils.rollback(rollback.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(1); // We should see recent rollbacks listed for both A and B. Thread.sleep(1000); RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); + rm.getRecentlyCommittedRollbacks(), TestApp.A); RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_B); - assertRollbackInfoForAandB(rollbackB); + rm.getRecentlyCommittedRollbacks(), TestApp.B); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1), + Rollback.from(TestApp.B2).to(TestApp.B1)); - assertEquals(rollbackA.getRollbackId(), rollbackB.getRollbackId()); + assertThat(rollbackA).hasRollbackId(rollbackB.getRollbackId()); - processUserData(TEST_APP_A); - processUserData(TEST_APP_B); + processUserData(TestApp.A); + processUserData(TestApp.B); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -795,31 +870,27 @@ public class RollbackTest { @Test public void testMultiPackageEnableFail() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); + RollbackManager rm = RollbackUtils.getRollbackManager(); + Uninstall.packages(TestApp.A, TestApp.B); + Install.single(TestApp.A1).commit(); // We should fail to enable rollback here because TestApp B is not // already installed. - RollbackTestUtils.installMultiPackage(true, - "RollbackTestAppAv2.apk", - "RollbackTestAppBv2.apk"); + Install.multi(TestApp.A2, TestApp.B2).setEnableRollback().commit(); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); - assertNull(getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A)); - assertNull(getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B)); + assertThat(getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A)).isNull(); + assertThat(getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.B)).isNull(); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -830,30 +901,33 @@ public class RollbackTest { */ public void testSameVersionUpdate() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - RollbackTestUtils.install("RollbackTestAppACrashingV2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + Install.single(TestApp.ACrashing2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 2, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A2)); - RollbackTestUtils.rollback(rollback.getRollbackId()); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + RollbackUtils.rollback(rollback.getRollbackId()); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 2, rollback); + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A2)); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -865,54 +939,55 @@ public class RollbackTest { BroadcastReceiver crashCountReceiver = null; Context context = InstrumentationRegistry.getContext(); try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.MANAGE_ROLLBACKS, Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.KILL_BACKGROUND_PROCESSES, Manifest.permission.RESTART_PACKAGES); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); // Prep installation of the test apps. - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppACrashingV2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A, TestApp.B); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.ACrashing2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - RollbackTestUtils.uninstall(TEST_APP_B); - RollbackTestUtils.install("RollbackTestAppBv1.apk", false); - RollbackTestUtils.install("RollbackTestAppBv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + Install.single(TestApp.B1).commit(); + Install.single(TestApp.B2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); // Both test apps should now be available for rollback, and the // targetPackage returned for rollback should be correct. RollbackInfo rollbackA = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollbackA); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollbackA).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); RollbackInfo rollbackB = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_B); - assertRollbackInfoEquals(TEST_APP_B, 2, 1, rollbackB); + rm.getAvailableRollbacks(), TestApp.B); + assertThat(rollbackB).packagesContainsExactly( + Rollback.from(TestApp.B2).to(TestApp.B1)); // Register rollback committed receiver RollbackBroadcastReceiver rollbackReceiver = new RollbackBroadcastReceiver(); - // Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback - crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5); + // Crash TestApp.A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback + crashCountReceiver = RollbackUtils.sendCrashBroadcast(context, TestApp.A, 5); // Verify we received a broadcast for the rollback. rollbackReceiver.take(); - // TEST_APP_A is automatically rolled back by the RollbackPackageHealthObserver - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + // TestApp.A is automatically rolled back by the RollbackPackageHealthObserver + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); // Instrumented app is still the package installer - String installer = context.getPackageManager().getInstallerPackageName(TEST_APP_A); - assertEquals(INSTRUMENTED_APP, installer); - // TEST_APP_B is untouched - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_B)); + String installer = context.getPackageManager().getInstallerPackageName(TestApp.A); + assertThat(installer).isEqualTo(INSTRUMENTED_APP); + // TestApp.B is untouched + assertThat(InstallUtils.getInstalledVersion(TestApp.B)).isEqualTo(2); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); if (crashCountReceiver != null) { context.unregisterReceiver(crashCountReceiver); } @@ -925,31 +1000,32 @@ public class RollbackTest { @Test public void testRollForwardRace() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, Manifest.permission.MANAGE_ROLLBACKS); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); // Install a new version of package A, then immediately rollback // the previous version. We expect the rollback to fail, because // it is no longer available. // There are a couple different ways this could fail depending on // thread interleaving, so don't ignore flaky failures. - RollbackTestUtils.install("RollbackTestAppAv3.apk", false); + Install.single(TestApp.A3).commit(); try { - RollbackTestUtils.rollback(rollback.getRollbackId()); + RollbackUtils.rollback(rollback.getRollbackId()); // Note: Don't ignore flaky failures here. fail("Expected rollback to fail, but it did not."); } catch (AssertionError e) { @@ -958,9 +1034,9 @@ public class RollbackTest { } // Note: Don't ignore flaky failures here. - assertEquals(3, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(3); } finally { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } } @@ -968,7 +1044,7 @@ public class RollbackTest { @Ignore("b/136605788") public void testEnableRollbackTimeoutFailsRollback() throws Exception { try { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -979,35 +1055,22 @@ public class RollbackTest { DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS, Long.toString(0), false /* makeDefault*/); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); - RollbackTestUtils.uninstall(TEST_APP_A); - RollbackTestUtils.install("RollbackTestAppAv1.apk", false); - RollbackTestUtils.install("RollbackTestAppAv2.apk", true); + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + Install.single(TestApp.A2).setEnableRollback().commit(); - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TEST_APP_A)); + assertThat( + getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), TestApp.A)).isNull(); } finally { //setting the timeout back to default DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, PROPERTY_ENABLE_ROLLBACK_TIMEOUT_MILLIS, null, false /* makeDefault*/); - RollbackTestUtils.dropShellPermissionIdentity(); - } - } - - // Helper function to test that the given rollback info is a rollback for - // the atomic set {A2, B2} -> {A1, B1}. - private void assertRollbackInfoForAandB(RollbackInfo rollback) { - assertNotNull(rollback); - assertEquals(2, rollback.getPackages().size()); - if (TEST_APP_A.equals(rollback.getPackages().get(0).getPackageName())) { - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(0)); - assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollback.getPackages().get(1)); - } else { - assertPackageRollbackInfoEquals(TEST_APP_B, 2, 1, rollback.getPackages().get(0)); - assertPackageRollbackInfoEquals(TEST_APP_A, 2, 1, rollback.getPackages().get(1)); + InstallUtils.dropShellPermissionIdentity(); } } } diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java deleted file mode 100644 index a9e20cdb191b4..0000000000000 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -import android.app.ActivityManager; -import android.app.AlarmManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageInstaller; -import android.content.pm.PackageManager; -import android.content.pm.VersionedPackage; -import android.content.rollback.PackageRollbackInfo; -import android.content.rollback.RollbackInfo; -import android.content.rollback.RollbackManager; -import android.os.Handler; -import android.os.HandlerThread; -import android.util.Log; - -import androidx.test.InstrumentationRegistry; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.SynchronousQueue; - -/** - * Utilities to facilitate testing rollbacks. - */ -class RollbackTestUtils { - - private static final String TAG = "RollbackTest"; - - static RollbackManager getRollbackManager() { - Context context = InstrumentationRegistry.getContext(); - RollbackManager rm = (RollbackManager) context.getSystemService(Context.ROLLBACK_SERVICE); - if (rm == null) { - throw new AssertionError("Failed to get RollbackManager"); - } - return rm; - } - - private static void setTime(long millis) { - Context context = InstrumentationRegistry.getContext(); - AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); - am.setTime(millis); - } - - static void forwardTimeBy(long offsetMillis) { - setTime(System.currentTimeMillis() + offsetMillis); - Log.i(TAG, "Forwarded time on device by " + offsetMillis + " millis"); - } - - /** - * Returns the version of the given package installed on device. - * Returns -1 if the package is not currently installed. - */ - static long getInstalledVersion(String packageName) { - PackageInfo pi = getPackageInfo(packageName); - if (pi == null) { - return -1; - } else { - return pi.getLongVersionCode(); - } - } - - private static boolean isSystemAppWithoutUpdate(String packageName) { - PackageInfo pi = getPackageInfo(packageName); - if (pi == null) { - return false; - } else { - return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) - && ((pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0); - } - } - - private static PackageInfo getPackageInfo(String packageName) { - Context context = InstrumentationRegistry.getContext(); - PackageManager pm = context.getPackageManager(); - try { - return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX); - } catch (PackageManager.NameNotFoundException e) { - return null; - } - } - - private static void assertStatusSuccess(Intent result) { - int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS, - PackageInstaller.STATUS_FAILURE); - if (status == -1) { - throw new AssertionError("PENDING USER ACTION"); - } else if (status > 0) { - String message = result.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE); - throw new AssertionError(message == null ? "UNKNOWN FAILURE" : message); - } - } - - /** - * Uninstalls the given package. - * Does nothing if the package is not installed. - * @throws AssertionError if package can't be uninstalled. - */ - static void uninstall(String packageName) throws InterruptedException, IOException { - // No need to uninstall if the package isn't installed or is installed on /system. - if (getInstalledVersion(packageName) == -1 || isSystemAppWithoutUpdate(packageName)) { - return; - } - - Context context = InstrumentationRegistry.getContext(); - PackageManager packageManager = context.getPackageManager(); - PackageInstaller packageInstaller = packageManager.getPackageInstaller(); - packageInstaller.uninstall(packageName, LocalIntentSender.getIntentSender()); - assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); - } - - /** - * Commit the given rollback. - * @throws AssertionError if the rollback fails. - */ - static void rollback(int rollbackId, VersionedPackage... causePackages) - throws InterruptedException { - RollbackManager rm = getRollbackManager(); - rm.commitRollback(rollbackId, Arrays.asList(causePackages), - LocalIntentSender.getIntentSender()); - Intent result = LocalIntentSender.getIntentSenderResult(); - int status = result.getIntExtra(RollbackManager.EXTRA_STATUS, - RollbackManager.STATUS_FAILURE); - if (status != RollbackManager.STATUS_SUCCESS) { - String message = result.getStringExtra(RollbackManager.EXTRA_STATUS_MESSAGE); - throw new AssertionError(message); - } - } - - /** - * Installs the apk with the given name. - * - * @param resourceName name of class loader resource for the apk to - * install. - * @param enableRollback if rollback should be enabled. - * @throws AssertionError if the installation fails. - */ - static void install(String resourceName, boolean enableRollback) - throws InterruptedException, IOException { - installSplit(enableRollback, resourceName); - } - - /** - * Installs the apk with the given name and its splits. - * - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of class loader resources for the apk and - * its splits to install. - * @throws AssertionError if the installation fails. - */ - static void installSplit(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { - Context context = InstrumentationRegistry.getContext(); - PackageInstaller.Session session = null; - PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); - PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - params.setEnableRollback(enableRollback); - int sessionId = packageInstaller.createSession(params); - session = packageInstaller.openSession(sessionId); - - ClassLoader loader = RollbackTest.class.getClassLoader(); - for (String resourceName : resourceNames) { - try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1); - InputStream is = loader.getResourceAsStream(resourceName);) { - byte[] buffer = new byte[4096]; - int n; - while ((n = is.read(buffer)) >= 0) { - packageInSession.write(buffer, 0, n); - } - } - } - - // Commit the session (this will start the installation workflow). - session.commit(LocalIntentSender.getIntentSender()); - assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); - } - - /** Launches {@code packageName} with {@link Intent#ACTION_MAIN}. */ - private static void launchPackage(String packageName) - throws InterruptedException, IOException { - Context context = InstrumentationRegistry.getContext(); - Intent intent = new Intent(Intent.ACTION_MAIN); - intent.setPackage(packageName); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.addCategory(Intent.CATEGORY_LAUNCHER); - context.startActivity(intent); - } - - /** - * Installs the APKs or APEXs with the given resource names as an atomic - * set. A resource is assumed to be an APEX if it has the .apex extension. - *

- * In case of staged installs, this function will return succesfully after - * the staged install has been committed and is ready for the device to - * reboot. - * - * @param staged if the rollback should be staged. - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of the class loader resource for the apks to - * install. - * @throws AssertionError if the installation fails. - */ - private static void install(boolean staged, boolean enableRollback, - String... resourceNames) throws InterruptedException, IOException { - Context context = InstrumentationRegistry.getContext(); - PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller(); - - PackageInstaller.SessionParams multiPackageParams = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - multiPackageParams.setMultiPackage(); - if (staged) { - multiPackageParams.setStaged(); - } - // TODO: Do we set this on the parent params, the child params, or - // both? - multiPackageParams.setEnableRollback(enableRollback); - int multiPackageId = packageInstaller.createSession(multiPackageParams); - PackageInstaller.Session multiPackage = packageInstaller.openSession(multiPackageId); - - for (String resourceName : resourceNames) { - PackageInstaller.Session session = null; - PackageInstaller.SessionParams params = new PackageInstaller.SessionParams( - PackageInstaller.SessionParams.MODE_FULL_INSTALL); - if (staged) { - params.setStaged(); - } - if (resourceName.endsWith(".apex")) { - params.setInstallAsApex(); - } - params.setEnableRollback(enableRollback); - int sessionId = packageInstaller.createSession(params); - session = packageInstaller.openSession(sessionId); - - ClassLoader loader = RollbackTest.class.getClassLoader(); - try (OutputStream packageInSession = session.openWrite(resourceName, 0, -1); - InputStream is = loader.getResourceAsStream(resourceName);) { - byte[] buffer = new byte[4096]; - int n; - while ((n = is.read(buffer)) >= 0) { - packageInSession.write(buffer, 0, n); - } - } - multiPackage.addChildSessionId(sessionId); - } - - // Commit the session (this will start the installation workflow). - multiPackage.commit(LocalIntentSender.getIntentSender()); - assertStatusSuccess(LocalIntentSender.getIntentSenderResult()); - - if (staged) { - waitForSessionReady(multiPackageId); - } - } - - /** - * Installs the apks with the given resource names as an atomic set. - * - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of the class loader resource for the apks to - * install. - * @throws AssertionError if the installation fails. - */ - static void installMultiPackage(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { - install(false, enableRollback, resourceNames); - } - - /** - * Installs the APKs or APEXs with the given resource names as a staged - * atomic set. A resource is assumed to be an APEX if it has the .apex - * extension. - * - * @param enableRollback if rollback should be enabled. - * @param resourceNames names of the class loader resource for the apks to - * install. - * @throws AssertionError if the installation fails. - */ - static void installStaged(boolean enableRollback, String... resourceNames) - throws InterruptedException, IOException { - install(true, enableRollback, resourceNames); - } - - static void adoptShellPermissionIdentity(String... permissions) { - InstrumentationRegistry - .getInstrumentation() - .getUiAutomation() - .adoptShellPermissionIdentity(permissions); - } - - static void dropShellPermissionIdentity() { - InstrumentationRegistry - .getInstrumentation() - .getUiAutomation() - .dropShellPermissionIdentity(); - } - - /** - * Returns the RollbackInfo with a given package in the list of rollbacks. - * Throws an assertion failure if there is more than one such rollback - * info. Returns null if there are no such rollback infos. - */ - static RollbackInfo getUniqueRollbackInfoForPackage(List rollbacks, - String packageName) { - RollbackInfo found = null; - for (RollbackInfo rollback : rollbacks) { - for (PackageRollbackInfo info : rollback.getPackages()) { - if (packageName.equals(info.getPackageName())) { - assertNull(found); - found = rollback; - break; - } - } - } - return found; - } - - /** - * Asserts that the given PackageRollbackInfo has the expected package - * name and versions. - */ - static void assertPackageRollbackInfoEquals(String packageName, - long versionRolledBackFrom, long versionRolledBackTo, - PackageRollbackInfo info) { - assertEquals(packageName, info.getPackageName()); - assertEquals(packageName, info.getVersionRolledBackFrom().getPackageName()); - assertEquals(versionRolledBackFrom, info.getVersionRolledBackFrom().getLongVersionCode()); - assertEquals(packageName, info.getVersionRolledBackTo().getPackageName()); - assertEquals(versionRolledBackTo, info.getVersionRolledBackTo().getLongVersionCode()); - } - - /** - * Asserts that the given RollbackInfo has the given packages with expected - * package names and all are rolled to and from the same given versions. - */ - static void assertRollbackInfoEquals(String[] packageNames, - long versionRolledBackFrom, long versionRolledBackTo, - RollbackInfo info, VersionedPackage... causePackages) { - assertNotNull(info); - assertEquals(packageNames.length, info.getPackages().size()); - int foundPackages = 0; - for (String packageName : packageNames) { - for (PackageRollbackInfo pkgRollbackInfo : info.getPackages()) { - if (packageName.equals(pkgRollbackInfo.getPackageName())) { - foundPackages++; - assertPackageRollbackInfoEquals(packageName, versionRolledBackFrom, - versionRolledBackTo, pkgRollbackInfo); - break; - } - } - } - assertEquals(packageNames.length, foundPackages); - assertEquals(causePackages.length, info.getCausePackages().size()); - for (int i = 0; i < causePackages.length; ++i) { - assertEquals(causePackages[i].getPackageName(), - info.getCausePackages().get(i).getPackageName()); - assertEquals(causePackages[i].getLongVersionCode(), - info.getCausePackages().get(i).getLongVersionCode()); - } - } - - /** - * Asserts that the given RollbackInfo has a single package with expected - * package name and versions. - */ - static void assertRollbackInfoEquals(String packageName, - long versionRolledBackFrom, long versionRolledBackTo, - RollbackInfo info, VersionedPackage... causePackages) { - String[] packageNames = {packageName}; - assertRollbackInfoEquals(packageNames, versionRolledBackFrom, versionRolledBackTo, info, - causePackages); - } - - /** - * Waits for the given session to be marked as ready. - * Throws an assertion if the session fails. - */ - static void waitForSessionReady(int sessionId) { - BlockingQueue sessionStatus = new LinkedBlockingQueue<>(); - BroadcastReceiver sessionUpdatedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - PackageInstaller.SessionInfo info = - intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION); - if (info != null && info.getSessionId() == sessionId) { - if (info.isStagedSessionReady() || info.isStagedSessionFailed()) { - try { - sessionStatus.put(info); - } catch (InterruptedException e) { - Log.e(TAG, "Failed to put session info.", e); - } - } - } - } - }; - IntentFilter sessionUpdatedFilter = - new IntentFilter(PackageInstaller.ACTION_SESSION_UPDATED); - - Context context = InstrumentationRegistry.getContext(); - context.registerReceiver(sessionUpdatedReceiver, sessionUpdatedFilter); - - PackageInstaller installer = context.getPackageManager().getPackageInstaller(); - PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId); - - try { - if (info.isStagedSessionReady() || info.isStagedSessionFailed()) { - sessionStatus.put(info); - } - - info = sessionStatus.take(); - context.unregisterReceiver(sessionUpdatedReceiver); - if (info.isStagedSessionFailed()) { - throw new AssertionError(info.getStagedSessionErrorMessage()); - } - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - - private static final String NO_RESPONSE = "NO RESPONSE"; - - /** - * Calls into the test app to process user data. - * Asserts if the user data could not be processed or was version - * incompatible with the previously processed user data. - */ - static void processUserData(String packageName) { - Intent intent = new Intent(); - intent.setComponent(new ComponentName(packageName, - "com.android.tests.rollback.testapp.ProcessUserData")); - Context context = InstrumentationRegistry.getContext(); - - HandlerThread handlerThread = new HandlerThread("RollbackTestHandlerThread"); - handlerThread.start(); - - // It can sometimes take a while after rollback before the app will - // receive this broadcast, so try a few times in a loop. - String result = NO_RESPONSE; - for (int i = 0; result.equals(NO_RESPONSE) && i < 5; ++i) { - BlockingQueue resultQueue = new LinkedBlockingQueue<>(); - context.sendOrderedBroadcast(intent, null, new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (getResultCode() == 1) { - resultQueue.add("OK"); - } else { - // If the test app doesn't receive the broadcast or - // fails to set the result data, then getResultData - // here returns the initial NO_RESPONSE data passed to - // the sendOrderedBroadcast call. - resultQueue.add(getResultData()); - } - } - }, new Handler(handlerThread.getLooper()), 0, NO_RESPONSE, null); - - try { - result = resultQueue.take(); - } catch (InterruptedException e) { - throw new AssertionError(e); - } - } - - handlerThread.quit(); - if (!"OK".equals(result)) { - fail(result); - } - } - - /** - * Return the rollback info for a recently committed rollback, by matching the rollback id, or - * return null if no matching rollback is found. - */ - static RollbackInfo getRecentlyCommittedRollbackInfoById(int getRollbackId) { - for (RollbackInfo info : getRollbackManager().getRecentlyCommittedRollbacks()) { - if (info.getRollbackId() == getRollbackId) { - return info; - } - } - return null; - } - - /** - * Send broadcast to crash {@code packageName} {@code count} times. If {@code count} is at least - * {@link PackageWatchdog#TRIGGER_FAILURE_COUNT}, watchdog crash detection will be triggered. - */ - static BroadcastReceiver sendCrashBroadcast(Context context, String packageName, int count) - throws InterruptedException, IOException { - BlockingQueue crashQueue = new SynchronousQueue<>(); - IntentFilter crashCountFilter = new IntentFilter(); - crashCountFilter.addAction("com.android.tests.rollback.CRASH"); - crashCountFilter.addCategory(Intent.CATEGORY_DEFAULT); - - BroadcastReceiver crashCountReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - try { - // Sleep long enough for packagewatchdog to be notified of crash - Thread.sleep(1000); - // Kill app and close AppErrorDialog - ActivityManager am = context.getSystemService(ActivityManager.class); - am.killBackgroundProcesses(packageName); - // Allow another package launch - crashQueue.put(intent.getIntExtra("count", 0)); - } catch (InterruptedException e) { - fail("Failed to communicate with test app"); - } - } - }; - context.registerReceiver(crashCountReceiver, crashCountFilter); - - do { - launchPackage(packageName); - } while(crashQueue.take() < count); - return crashCountReceiver; - } -} diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 1a29c4c114579..a67bf3ca0b5dd 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -16,25 +16,28 @@ package com.android.tests.rollback; -import static com.android.tests.rollback.RollbackTestUtils.assertRollbackInfoEquals; -import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfoForPackage; +import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat; +import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage; + +import static com.google.common.truth.Truth.assertThat; import android.Manifest; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.pm.VersionedPackage; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; import androidx.test.InstrumentationRegistry; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import com.android.cts.install.lib.Install; +import com.android.cts.install.lib.InstallUtils; +import com.android.cts.install.lib.TestApp; +import com.android.cts.install.lib.Uninstall; +import com.android.cts.rollback.lib.Rollback; +import com.android.cts.rollback.lib.RollbackUtils; + import static org.junit.Assert.fail; import org.junit.After; @@ -55,9 +58,6 @@ import org.junit.runners.JUnit4; public class StagedRollbackTest { private static final String TAG = "RollbackTest"; - private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A"; - private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk"; - private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk"; private static final String NETWORK_STACK_CONNECTOR_CLASS = "android.net.INetworkStackConnector"; @@ -66,7 +66,7 @@ public class StagedRollbackTest { */ @Before public void adoptShellPermissions() { - RollbackTestUtils.adoptShellPermissionIdentity( + InstallUtils.adoptShellPermissionIdentity( Manifest.permission.INSTALL_PACKAGES, Manifest.permission.DELETE_PACKAGES, Manifest.permission.TEST_MANAGE_ROLLBACKS, @@ -78,7 +78,7 @@ public class StagedRollbackTest { */ @After public void dropShellPermissions() { - RollbackTestUtils.dropShellPermissionIdentity(); + InstallUtils.dropShellPermissionIdentity(); } /** @@ -87,14 +87,14 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyEnableRollback() throws Exception { - RollbackTestUtils.uninstall(TEST_APP_A); - assertEquals(-1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); + Uninstall.packages(TestApp.A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); - RollbackTestUtils.install(TEST_APP_A_V1, false); - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - RollbackTestUtils.processUserData(TEST_APP_A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); - RollbackTestUtils.installStaged(true, TEST_APP_A_CRASHING_V2); + Install.single(TestApp.ACrashing2).setEnableRollback().setStaged().commit(); // At this point, the host test driver will reboot the device and run // testBadApkOnlyConfirmEnableRollback(). @@ -106,14 +106,16 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyConfirmEnableRollback() throws Exception { - assertEquals(2, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - RollbackTestUtils.processUserData(TEST_APP_A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + InstallUtils.processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getAvailableRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback); - assertTrue(rollback.isStaged()); + rm.getAvailableRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(rollback.isStaged()).isTrue(); // At this point, the host test driver will run // testBadApkOnlyTriggerRollback(). @@ -128,11 +130,10 @@ public class StagedRollbackTest { public void testBadApkOnlyTriggerRollback() throws Exception { BroadcastReceiver crashCountReceiver = null; Context context = InstrumentationRegistry.getContext(); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); try { - // Crash TEST_APP_A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback - crashCountReceiver = RollbackTestUtils.sendCrashBroadcast(context, TEST_APP_A, 5); + // Crash TestApp.A PackageWatchdog#TRIGGER_FAILURE_COUNT times to trigger rollback + crashCountReceiver = RollbackUtils.sendCrashBroadcast(context, TestApp.A, 5); } finally { if (crashCountReceiver != null) { context.unregisterReceiver(crashCountReceiver); @@ -153,48 +154,51 @@ public class StagedRollbackTest { */ @Test public void testBadApkOnlyConfirmRollback() throws Exception { - assertEquals(1, RollbackTestUtils.getInstalledVersion(TEST_APP_A)); - RollbackTestUtils.processUserData(TEST_APP_A); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); RollbackInfo rollback = getUniqueRollbackInfoForPackage( - rm.getRecentlyCommittedRollbacks(), TEST_APP_A); - assertRollbackInfoEquals(TEST_APP_A, 2, 1, rollback, new VersionedPackage(TEST_APP_A, 2)); - assertTrue(rollback.isStaged()); - assertNotEquals(-1, rollback.getCommittedSessionId()); + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(rollback).causePackagesContainsExactly(TestApp.ACrashing2); + assertThat(rollback).isStaged(); + assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1); } @Test public void resetNetworkStack() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); + RollbackManager rm = RollbackUtils.getRollbackManager(); String networkStack = getNetworkStackPackageName(); rm.expireRollbackForPackage(networkStack); - RollbackTestUtils.uninstall(networkStack); + Uninstall.packages(networkStack); - assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), - networkStack)); + assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), + networkStack)).isNull(); } @Test public void assertNetworkStackRollbackAvailable() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNotNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), - getNetworkStackPackageName())); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(), + getNetworkStackPackageName())).isNotNull(); } @Test public void assertNetworkStackRollbackCommitted() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNotNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), - getNetworkStackPackageName())); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), + getNetworkStackPackageName())).isNotNull(); } @Test public void assertNoNetworkStackRollbackCommitted() throws Exception { - RollbackManager rm = RollbackTestUtils.getRollbackManager(); - assertNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), - getNetworkStackPackageName())); + RollbackManager rm = RollbackUtils.getRollbackManager(); + assertThat(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(), + getNetworkStackPackageName())).isNull(); } private String getNetworkStackPackageName() { diff --git a/tests/RollbackTest/TestApp/ACrashingV2.xml b/tests/RollbackTest/TestApp/ACrashingV2.xml deleted file mode 100644 index 77bfd4e0f9a0a..0000000000000 --- a/tests/RollbackTest/TestApp/ACrashingV2.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/RollbackTest/TestApp/Av1.xml b/tests/RollbackTest/TestApp/Av1.xml deleted file mode 100644 index 63729fbaaf281..0000000000000 --- a/tests/RollbackTest/TestApp/Av1.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/tests/RollbackTest/TestApp/Av2.xml b/tests/RollbackTest/TestApp/Av2.xml deleted file mode 100644 index f0e909feabf30..0000000000000 --- a/tests/RollbackTest/TestApp/Av2.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/tests/RollbackTest/TestApp/Av3.xml b/tests/RollbackTest/TestApp/Av3.xml deleted file mode 100644 index 9725c9f7cf9e5..0000000000000 --- a/tests/RollbackTest/TestApp/Av3.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/tests/RollbackTest/TestApp/Bv1.xml b/tests/RollbackTest/TestApp/Bv1.xml deleted file mode 100644 index ca9c2ec47a207..0000000000000 --- a/tests/RollbackTest/TestApp/Bv1.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/tests/RollbackTest/TestApp/Bv2.xml b/tests/RollbackTest/TestApp/Bv2.xml deleted file mode 100644 index bd3e6133f6f67..0000000000000 --- a/tests/RollbackTest/TestApp/Bv2.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml b/tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml deleted file mode 100644 index 90d3da2565cca..0000000000000 --- a/tests/RollbackTest/TestApp/res_v1/values-anydpi/values.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 1 - diff --git a/tests/RollbackTest/TestApp/res_v1/values/values.xml b/tests/RollbackTest/TestApp/res_v1/values/values.xml deleted file mode 100644 index 0447c74a79a68..0000000000000 --- a/tests/RollbackTest/TestApp/res_v1/values/values.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - 1 - 0 - diff --git a/tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml b/tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml deleted file mode 100644 index 9a1aa7fd8461f..0000000000000 --- a/tests/RollbackTest/TestApp/res_v2/values-anydpi/values.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 2 - diff --git a/tests/RollbackTest/TestApp/res_v2/values/values.xml b/tests/RollbackTest/TestApp/res_v2/values/values.xml deleted file mode 100644 index fd988f597f61e..0000000000000 --- a/tests/RollbackTest/TestApp/res_v2/values/values.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - 2 - 0 - diff --git a/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml b/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml deleted file mode 100644 index f2d8992bee378..0000000000000 --- a/tests/RollbackTest/TestApp/res_v3/values-anydpi/values.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - 3 - diff --git a/tests/RollbackTest/TestApp/res_v3/values/values.xml b/tests/RollbackTest/TestApp/res_v3/values/values.xml deleted file mode 100644 index 968168a4bf063..0000000000000 --- a/tests/RollbackTest/TestApp/res_v3/values/values.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - 3 - 0 - diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java deleted file mode 100644 index 97958acde21b8..0000000000000 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/CrashingMainActivity.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2019 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.tests.rollback.testapp; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.os.Bundle; - -/** - * A crashing test app for testing apk rollback support. - */ -public class CrashingMainActivity extends Activity { - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - incrementCountAndBroadcast(); - throw new RuntimeException("Intended force crash"); - } - - private void incrementCountAndBroadcast() { - SharedPreferences preferences = getSharedPreferences("prefs", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - int count = preferences.getInt("crash_count", 0); - editor.putInt("crash_count", ++count).commit(); - - Intent intent = new Intent("com.android.tests.rollback.CRASH"); - intent.putExtra("count", count); - sendBroadcast(intent); - } -} diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java deleted file mode 100644 index 9f1a0609d3f1d..0000000000000 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/MainActivity.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback.testapp; - -import android.app.Activity; -import android.os.Bundle; - -/** - * A test app for testing apk rollback support. - */ -public class MainActivity extends Activity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - try { - new ProcessUserData().processUserData(this); - } catch (ProcessUserData.UserDataException e) { - throw new AssertionError("Failed to process app user data", e); - } - } -} diff --git a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java b/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java deleted file mode 100644 index 38c658e795aa6..0000000000000 --- a/tests/RollbackTest/TestApp/src/com/android/tests/rollback/testapp/ProcessUserData.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2018 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.tests.rollback.testapp; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Scanner; - -/** - * A broadcast reciever to check for and update user app data version - * compatibility. - */ -public class ProcessUserData extends BroadcastReceiver { - - private static final String TAG = "RollbackTestApp"; - - /** - * Exception thrown in case of issue with user data. - */ - public static class UserDataException extends Exception { - public UserDataException(String message) { - super(message); - } - - public UserDataException(String message, Throwable cause) { - super(message, cause); - } - } - - @Override - public void onReceive(Context context, Intent intent) { - try { - processUserData(context); - setResultCode(1); - } catch (UserDataException e) { - setResultCode(0); - setResultData(e.getMessage()); - } - } - - /** - * Update the app's user data version to match the app version. - * - * @param context The application context. - * @throws UserDataException in case of problems with app user data. - */ - public void processUserData(Context context) throws UserDataException { - Resources res = context.getResources(); - String packageName = context.getPackageName(); - - int appVersionId = res.getIdentifier("app_version", "integer", packageName); - int appVersion = res.getInteger(appVersionId); - - int splitVersionId = res.getIdentifier("split_version", "integer", packageName); - int splitVersion = res.getInteger(splitVersionId); - - // Make sure the app version and split versions are compatible. - if (appVersion != splitVersion) { - throw new UserDataException("Split version " + splitVersion - + " does not match app version " + appVersion); - } - - // Read the version of the app's user data and ensure it is compatible - // with our version of the application. - File versionFile = new File(context.getFilesDir(), "version.txt"); - try { - Scanner s = new Scanner(versionFile); - int userDataVersion = s.nextInt(); - s.close(); - - if (userDataVersion > appVersion) { - throw new UserDataException("User data is from version " + userDataVersion - + ", which is not compatible with this version " + appVersion - + " of the RollbackTestApp"); - } - } catch (FileNotFoundException e) { - // No problem. This is a fresh install of the app or the user data - // has been wiped. - } - - // Record the current version of the app in the user data. - try { - PrintWriter pw = new PrintWriter(versionFile); - pw.println(appVersion); - pw.close(); - } catch (IOException e) { - throw new UserDataException("Unable to write user data.", e); - } - } -} From 895901357e76ab1db3354864335d9e64f4dfafbf Mon Sep 17 00:00:00 2001 From: shafik Date: Mon, 1 Jul 2019 20:28:25 +0100 Subject: [PATCH 05/14] Make setRequestDowngrade @TestApi Test: build Bug: 134653708 Exempt-From-Owner-Approval: Already approved in https://googleplex-android-review.git.corp.google.com/c/platform/frameworks/base/+/8350817/ Change-Id: I732aca8011490fa5815199451566ac8b0b1a2204 Merged-In: Idf99e0810e2e9040f49f06a00722567ac15bbe18 --- api/test-current.txt | 1 + core/java/android/content/pm/PackageInstaller.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/test-current.txt b/api/test-current.txt index 989e877f81a3f..27114cb7d0d9b 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -694,6 +694,7 @@ package android.content.pm { method public void setEnableRollback(boolean); method @RequiresPermission("android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS") public void setGrantedRuntimePermissions(String[]); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex(); + method public void setRequestDowngrade(boolean); method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged(); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 3cecd7f880456..1099d8bdc7ddf 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1565,7 +1565,7 @@ public class PackageInstaller { } /** {@hide} */ - @SystemApi + @SystemApi @TestApi public void setRequestDowngrade(boolean requestDowngrade) { if (requestDowngrade) { installFlags |= PackageManager.INSTALL_REQUEST_DOWNGRADE; From 7ad5775fd870bf0db21772ef8484233634e29fd5 Mon Sep 17 00:00:00 2001 From: shafik Date: Wed, 5 Jun 2019 14:59:57 +0100 Subject: [PATCH 06/14] Use Slog in RollbackManager, not Log Test: build Bug: 132763443 Change-Id: I03becc6d2b960a98ff0c2b468a7f6eba21edca48 Merged-In: I2f5f5927bfd8a9cf8b506936f74aeb5d0908923e --- .../rollback/AppDataRollbackHelper.java | 14 ++--- .../rollback/RollbackManagerServiceImpl.java | 56 +++++++++---------- .../server/rollback/RollbackStore.java | 4 +- 3 files changed, 37 insertions(+), 37 deletions(-) diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java index 56e1d080a988c..f5f7d67ba0b11 100644 --- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java +++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java @@ -20,7 +20,7 @@ import android.content.rollback.PackageRollbackInfo; import android.content.rollback.PackageRollbackInfo.RestoreInfo; import android.os.storage.StorageManager; import android.util.IntArray; -import android.util.Log; +import android.util.Slog; import android.util.SparseLongArray; import com.android.internal.annotations.VisibleForTesting; @@ -62,7 +62,7 @@ public class AppDataRollbackHelper { if (isUserCredentialLocked(user)) { // We've encountered a user that hasn't unlocked on a FBE device, so we can't copy // across app user data until the user unlocks their device. - Log.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup."); + Slog.v(TAG, "User: " + user + " isn't unlocked, skipping CE userdata backup."); storageFlags = Installer.FLAG_STORAGE_DE; packageRollbackInfo.addPendingBackup(user); } else { @@ -76,7 +76,7 @@ public class AppDataRollbackHelper { packageRollbackInfo.putCeSnapshotInode(user, ceSnapshotInode); } } catch (InstallerException ie) { - Log.e(TAG, "Unable to create app data snapshot for: " + Slog.e(TAG, "Unable to create app data snapshot for: " + packageRollbackInfo.getPackageName() + ", userId: " + user, ie); } } @@ -122,7 +122,7 @@ public class AppDataRollbackHelper { mInstaller.restoreAppDataSnapshot(packageRollbackInfo.getPackageName(), appId, seInfo, userId, rollbackId, storageFlags); } catch (InstallerException ie) { - Log.e(TAG, "Unable to restore app data snapshot: " + Slog.e(TAG, "Unable to restore app data snapshot: " + packageRollbackInfo.getPackageName(), ie); } @@ -148,7 +148,7 @@ public class AppDataRollbackHelper { ceSnapshotInodes.delete(user); } } catch (InstallerException ie) { - Log.e(TAG, "Unable to delete app data snapshot for " + Slog.e(TAG, "Unable to delete app data snapshot for " + packageRollbackInfo.getPackageName(), ie); } } @@ -257,7 +257,7 @@ public class AppDataRollbackHelper { info.putCeSnapshotInode(userId, ceSnapshotInode); pendingBackupUsers.remove(idx); } catch (InstallerException ie) { - Log.e(TAG, + Slog.e(TAG, "Unable to create app data snapshot for: " + info.getPackageName() + ", userId: " + userId, ie); } @@ -277,7 +277,7 @@ public class AppDataRollbackHelper { Installer.FLAG_STORAGE_CE); info.removeRestoreInfo(ri); } catch (InstallerException ie) { - Log.e(TAG, "Unable to restore app data snapshot for: " + Slog.e(TAG, "Unable to restore app data snapshot for: " + info.getPackageName(), ie); } } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index e107c9aedf38b..505e89df55caa 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -52,7 +52,7 @@ import android.os.UserHandle; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.IntArray; -import android.util.Log; +import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseLongArray; @@ -171,7 +171,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { enableRollbackFilter.addDataType("application/vnd.android.package-archive"); } catch (IntentFilter.MalformedMimeTypeException e) { - Log.e(TAG, "addDataType", e); + Slog.e(TAG, "addDataType", e); } mContext.registerReceiver(new BroadcastReceiver() { @@ -251,7 +251,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private void registerUserCallbacks(UserHandle user) { Context context = getContextAsUser(user); if (context == null) { - Log.e(TAG, "Unable to register user callbacks for user " + user); + Slog.e(TAG, "Unable to register user callbacks for user " + user); return; } @@ -290,7 +290,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { public ParceledListSlice getAvailableRollbacks() { enforceManageRollbacks("getAvailableRollbacks"); if (Thread.currentThread().equals(mHandlerThread)) { - Log.wtf(TAG, "Calling getAvailableRollbacks from mHandlerThread " + Slog.wtf(TAG, "Calling getAvailableRollbacks from mHandlerThread " + "causes a deadlock"); throw new IllegalStateException("Cannot call RollbackManager#getAvailableRollbacks " + "from the handler thread!"); @@ -309,7 +309,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // We may not get the most up-to-date information, but whatever we // can get now is better than nothing, so log but otherwise ignore // the exception. - Log.w(TAG, "Interrupted while waiting for handler thread in getAvailableRollbacks"); + Slog.w(TAG, "Interrupted while waiting for handler thread in getAvailableRollbacks"); } synchronized (mLock) { @@ -393,7 +393,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ private void commitRollbackInternal(int rollbackId, List causePackages, String callerPackageName, IntentSender statusReceiver) { - Log.i(TAG, "Initiating rollback"); + Slog.i(TAG, "Initiating rollback"); RollbackData data = getRollbackForId(rollbackId); if (data == null || data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) { @@ -532,7 +532,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } parentSession.commit(receiver.getIntentSender()); } catch (IOException e) { - Log.e(TAG, "Rollback failed", e); + Slog.e(TAG, "Rollback failed", e); sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE, "IOException: " + e.toString()); return; @@ -761,7 +761,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ private void sendFailure(IntentSender statusReceiver, @RollbackManager.Status int status, String message) { - Log.e(TAG, message); + Slog.e(TAG, message); try { final Intent fillIn = new Intent(); fillIn.putExtra(RollbackManager.EXTRA_STATUS, status); @@ -876,7 +876,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // session. final Context context = getContextAsUser(UserHandle.of(user)); if (context == null) { - Log.e(TAG, "Unable to create context for install session user."); + Slog.e(TAG, "Unable to create context for install session user."); return false; } @@ -903,7 +903,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } if (parentSession == null || packageSession == null) { - Log.e(TAG, "Unable to find session for enabled rollback."); + Slog.e(TAG, "Unable to find session for enabled rollback."); return false; } @@ -930,7 +930,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { newPackage = PackageParser.parsePackageLite( new File(packageSession.resolvedBaseCodePath), 0); } catch (PackageParser.PackageParserException e) { - Log.e(TAG, "Unable to parse new package", e); + Slog.e(TAG, "Unable to parse new package", e); return false; } String packageName = newPackage.packageName; @@ -940,7 +940,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { return true; } } - Log.e(TAG, "Unable to find package in apk session"); + Slog.e(TAG, "Unable to find package in apk session"); return false; } @@ -972,16 +972,16 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // TODO: Don't attempt to enable rollback for split installs. final int installFlags = session.installFlags; if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) { - Log.e(TAG, "Rollback is not enabled."); + Slog.e(TAG, "Rollback is not enabled."); return false; } if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) { - Log.e(TAG, "Rollbacks not supported for instant app install"); + Slog.e(TAG, "Rollbacks not supported for instant app install"); return false; } if (session.resolvedBaseCodePath == null) { - Log.e(TAG, "Session code path has not been resolved."); + Slog.e(TAG, "Session code path has not been resolved."); return false; } @@ -990,17 +990,17 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { newPackage = PackageParser.parsePackageLite(new File(session.resolvedBaseCodePath), 0); } catch (PackageParser.PackageParserException e) { - Log.e(TAG, "Unable to parse new package", e); + Slog.e(TAG, "Unable to parse new package", e); return false; } String packageName = newPackage.packageName; - Log.i(TAG, "Enabling rollback for install of " + packageName + Slog.i(TAG, "Enabling rollback for install of " + packageName + ", session:" + session.sessionId); String installerPackageName = session.getInstallerPackageName(); if (!enableRollbackAllowed(installerPackageName, packageName)) { - Log.e(TAG, "Installer " + installerPackageName + Slog.e(TAG, "Installer " + installerPackageName + " is not allowed to enable rollback on " + packageName); return false; } @@ -1016,7 +1016,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } catch (PackageManager.NameNotFoundException e) { // TODO: Support rolling back fresh package installs rather than // fail here. Test this case. - Log.e(TAG, packageName + " is not installed"); + Slog.e(TAG, packageName + " is not installed"); return false; } @@ -1038,7 +1038,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } } } catch (IOException e) { - Log.e(TAG, "Unable to copy package for rollback for " + packageName, e); + Slog.e(TAG, "Unable to copy package for rollback for " + packageName, e); return false; } @@ -1143,7 +1143,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { final PackageInstaller.SessionInfo session = installer.getSessionInfo(sessionId); if (session == null) { - Log.e(TAG, "No matching install session for: " + sessionId); + Slog.e(TAG, "No matching install session for: " + sessionId); result.offer(false); return; } @@ -1156,7 +1156,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { if (!session.isMultiPackage()) { if (!enableRollbackForPackageSession(newRollback.data, session, new int[0])) { - Log.e(TAG, "Unable to enable rollback for session: " + sessionId); + Slog.e(TAG, "Unable to enable rollback for session: " + sessionId); result.offer(false); return; } @@ -1165,13 +1165,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { final PackageInstaller.SessionInfo childSession = installer.getSessionInfo(childSessionId); if (childSession == null) { - Log.e(TAG, "No matching child install session for: " + childSessionId); + Slog.e(TAG, "No matching child install session for: " + childSessionId); result.offer(false); return; } if (!enableRollbackForPackageSession(newRollback.data, childSession, new int[0])) { - Log.e(TAG, "Unable to enable rollback for session: " + sessionId); + Slog.e(TAG, "Unable to enable rollback for session: " + sessionId); result.offer(false); return; } @@ -1184,7 +1184,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { return result.take(); } catch (InterruptedException ie) { - Log.e(TAG, "Interrupted while waiting for notifyStagedSession response"); + Slog.e(TAG, "Interrupted while waiting for notifyStagedSession response"); return false; } } @@ -1342,7 +1342,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { return null; } if (newRollback.isCancelled) { - Log.e(TAG, "Rollback has been cancelled by PackageManager"); + Slog.e(TAG, "Rollback has been cancelled by PackageManager"); deleteRollback(data); return null; } @@ -1351,7 +1351,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // this is running on the handler thread and all changes to the // data.info occur on the handler thread. if (data.info.getPackages().size() != newRollback.packageSessionIds.length) { - Log.e(TAG, "Failed to enable rollback for all packages in session."); + Slog.e(TAG, "Failed to enable rollback for all packages in session."); deleteRollback(data); return null; } @@ -1471,7 +1471,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { mRollbackStore.saveRollbackData(rollbackData); } catch (IOException ioe) { - Log.e(TAG, "Unable to save rollback info for: " + Slog.e(TAG, "Unable to save rollback info for: " + rollbackData.info.getRollbackId(), ioe); } } diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java index 8a26368c3e133..1c36dc7791e69 100644 --- a/services/core/java/com/android/server/rollback/RollbackStore.java +++ b/services/core/java/com/android/server/rollback/RollbackStore.java @@ -25,7 +25,7 @@ import android.content.rollback.PackageRollbackInfo; import android.content.rollback.PackageRollbackInfo.RestoreInfo; import android.content.rollback.RollbackInfo; import android.util.IntArray; -import android.util.Log; +import android.util.Slog; import android.util.SparseLongArray; import libcore.io.IoUtils; @@ -83,7 +83,7 @@ class RollbackStore { try { rollbacks.add(loadRollbackData(rollbackDir)); } catch (IOException e) { - Log.e(TAG, "Unable to read rollback data at " + rollbackDir, e); + Slog.e(TAG, "Unable to read rollback data at " + rollbackDir, e); removeFile(rollbackDir); } } From 0c48af84fe68b396c0a1f2bb3f31e4be4fd8558a Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Fri, 7 Jun 2019 14:04:43 +0100 Subject: [PATCH 07/14] Add TestApi to block the RollbackManagerHandlerThread. To eliminate flakiness when testing timeout conditions for RollbackTest.testEnableRollbackTimeoutFailsRollback. Test: atest RollbackTest.testEnableRollbackTimeoutFailsRollback in a loop Bug: 134373106 Change-Id: I2d1de148a83231f3fd48cc05b7320fa5fdf091ce Merged-In: I01f3e769711ffa51fa714ff4bc81e70887f427ad --- api/test-current.txt | 1 + .../content/rollback/IRollbackManager.aidl | 3 +++ .../content/rollback/RollbackManager.java | 21 +++++++++++++++++++ .../rollback/RollbackManagerServiceImpl.java | 17 +++++++++++++-- .../android/tests/rollback/RollbackTest.java | 4 ++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/api/test-current.txt b/api/test-current.txt index 27114cb7d0d9b..b34791198df4e 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -796,6 +796,7 @@ package android.content.rollback { } public final class RollbackManager { + method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long); method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List, @NonNull android.content.IntentSender); method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public java.util.List getAvailableRollbacks(); diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl index 1b84f2987a8f9..b0e31c8578b9a 100644 --- a/core/java/android/content/rollback/IRollbackManager.aidl +++ b/core/java/android/content/rollback/IRollbackManager.aidl @@ -51,4 +51,7 @@ interface IRollbackManager { // Used by the staging manager to notify the RollbackManager of the apk // session for a staged session. void notifyStagedApkSession(int originalSessionId, int apkSessionId); + + // For test purposes only. + void blockRollbackManager(long millis); } diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index 9a10a0c4766b8..b8811aa1225e2 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -250,4 +250,25 @@ public final class RollbackManager { throw e.rethrowFromSystemServer(); } } + + /** + * Block the RollbackManager for a specified amount of time. + * This API is meant to facilitate testing of race conditions in + * RollbackManager. Blocks RollbackManager from processing anything for + * the given number of milliseconds. + * + * @param millis number of milliseconds to block the RollbackManager for + * @throws SecurityException if the caller does not have appropriate permissions. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) + @TestApi + public void blockRollbackManager(long millis) { + try { + mBinder.blockRollbackManager(millis); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 505e89df55caa..f5639a9f76f18 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -45,10 +45,9 @@ import android.os.Handler; import android.os.HandlerThread; import android.os.ParcelFileDescriptor; import android.os.Process; -import android.os.UserHandle; // duped to avoid merge conflict -import android.os.UserManager; // out of order to avoid merge conflict import android.os.SystemClock; import android.os.UserHandle; +import android.os.UserManager; import android.provider.DeviceConfig; import android.util.ArraySet; import android.util.IntArray; @@ -575,6 +574,20 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } } + @Override + public void blockRollbackManager(long millis) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.TEST_MANAGE_ROLLBACKS, + "blockRollbackManager"); + getHandler().post(() -> { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + // ignored. + } + }); + } + void onUnlockUser(int userId) { getHandler().post(() -> { final List rollbacks; diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java index ebf09b848dabf..b57bd4d64dc2f 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java @@ -1059,6 +1059,10 @@ public class RollbackTest { Uninstall.packages(TestApp.A); Install.single(TestApp.A1).commit(); + + // Block the RollbackManager to make extra sure it will not be + // able to enable the rollback in time. + rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(1)); Install.single(TestApp.A2).setEnableRollback().commit(); assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); From fcf64e8dbea761fc3c7a9801fded61b427f85829 Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Fri, 28 Jun 2019 10:55:45 +0100 Subject: [PATCH 08/14] Use "commit" for rollbacks instead of "execute". Fix a couple lingering references to "executing" rollbacks. We've long since switched to the terminology "commit", to highlight that a staged rollback that has been committed will not take effect until the device reboots. Fixes: 136044234 Test: atest RollbackTest Change-Id: If548b0340101db13f4fdce7c2de3fe1e8283a260 Merged-In: Ic364778c253ff59af8206824a66df72569ab1307 --- core/java/android/content/rollback/IRollbackManager.aidl | 2 +- core/java/android/content/rollback/RollbackManager.java | 2 +- .../server/rollback/RollbackManagerServiceImpl.java | 7 +++---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl index b0e31c8578b9a..8c2a65faf8edb 100644 --- a/core/java/android/content/rollback/IRollbackManager.aidl +++ b/core/java/android/content/rollback/IRollbackManager.aidl @@ -24,7 +24,7 @@ import android.content.IntentSender; interface IRollbackManager { ParceledListSlice getAvailableRollbacks(); - ParceledListSlice getRecentlyExecutedRollbacks(); + ParceledListSlice getRecentlyCommittedRollbacks(); void commitRollback(int rollbackId, in ParceledListSlice causePackages, String callerPackageName, in IntentSender statusReceiver); diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java index b8811aa1225e2..73b8a48d9153c 100644 --- a/core/java/android/content/rollback/RollbackManager.java +++ b/core/java/android/content/rollback/RollbackManager.java @@ -114,7 +114,7 @@ public final class RollbackManager { }) public @NonNull List getRecentlyCommittedRollbacks() { try { - return mBinder.getRecentlyExecutedRollbacks().getList(); + return mBinder.getRecentlyCommittedRollbacks().getList(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index f5639a9f76f18..de3e89f031d8e 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -325,7 +325,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { } @Override - public ParceledListSlice getRecentlyExecutedRollbacks() { + public ParceledListSlice getRecentlyCommittedRollbacks() { enforceManageRollbacks("getRecentlyCommittedRollbacks"); synchronized (mLock) { @@ -344,7 +344,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { @Override public void commitRollback(int rollbackId, ParceledListSlice causePackages, String callerPackageName, IntentSender statusReceiver) { - enforceManageRollbacks("executeRollback"); + enforceManageRollbacks("commitRollback"); final int callingUid = Binder.getCallingUid(); AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); @@ -690,8 +690,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { /** * Load rollback data from storage if it has not already been loaded. - * After calling this funciton, mAvailableRollbacks and - * mRecentlyExecutedRollbacks will be non-null. + * After calling this function, mRollbacks will be non-null. */ private void ensureRollbackDataLoaded() { synchronized (mLock) { From 32830a37a5968b5dae4c6f6ee7f477e0143b0dcb Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Mon, 1 Jul 2019 15:21:44 +0100 Subject: [PATCH 09/14] Load rollback data in RollbackManagerServiceImpl constructor. Load the rollback data from persistent storage in the RollbackManagerServiceImpl constructor instead of lazily. This way we don't have to remember to ensureRollbackDataLoaded every time we access the rollback data. In the vast majority of cases we expect there to be no data to load, so this shouldn't impact boot time. Change reloadPeristentData to block until the data has been reloaded. Consistently throw IllegalStateException in case of InterruptedException. There shouldn't be anyone calling Thread.interrupt() on the RollbackManagerHandlerThread. If it turns out someone does call Thread.interrupt() on the RollbackManagerHandlerThread, throwing IllegalStateException instead of ignoring the exception will help debug; then we can update the logic for handling InterruptedException in whatever way makes most sense. Test: atest RollbackTest Bug: 136241838 Change-Id: I9dc51268db39b9ba29aedbcbd09ab9111b294a7b Merged-In: Ia5e73b0786b93064f8f80138d3e162b9613f2d55 --- .../rollback/RollbackManagerServiceImpl.java | 111 +++++------------- 1 file changed, 31 insertions(+), 80 deletions(-) diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index de3e89f031d8e..1579f3080bc4c 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -75,6 +75,7 @@ import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.Set; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.TimeUnit; @@ -114,9 +115,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private final Set mNewRollbacks = new ArraySet<>(); // The list of all rollbacks, including available and committed rollbacks. - // This list is null until the rollback data has been loaded. @GuardedBy("mLock") - private List mRollbacks; + private final List mRollbacks; private final RollbackStore mRollbackStore; @@ -138,25 +138,24 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // SystemService#onStart. mInstaller = new Installer(mContext); mInstaller.onStart(); - mHandlerThread = new HandlerThread("RollbackManagerServiceHandler"); - mHandlerThread.start(); - - // Monitor the handler thread - Watchdog.getInstance().addThread(getHandler(), HANDLER_THREAD_TIMEOUT_DURATION_MILLIS); mRollbackStore = new RollbackStore(new File(Environment.getDataDirectory(), "rollback")); mPackageHealthObserver = new RollbackPackageHealthObserver(mContext); mAppDataRollbackHelper = new AppDataRollbackHelper(mInstaller); - // Kick off loading of the rollback data from strorage in a background - // thread. - // TODO: Consider loading the rollback data directly here instead, to - // avoid the need to call ensureRollbackDataLoaded every time before - // accessing the rollback data? - // TODO: Test that this kicks off initial scheduling of rollback - // expiration. - getHandler().post(() -> ensureRollbackDataLoaded()); + // Load rollback data from device storage. + synchronized (mLock) { + mRollbacks = mRollbackStore.loadAllRollbackData(); + for (RollbackData data : mRollbacks) { + mAllocatedRollbackIds.put(data.info.getRollbackId(), true); + } + } + + // Kick off and start monitoring the handler thread. + mHandlerThread = new HandlerThread("RollbackManagerServiceHandler"); + mHandlerThread.start(); + Watchdog.getInstance().addThread(getHandler(), HANDLER_THREAD_TIMEOUT_DURATION_MILLIS); // TODO: Make sure to register these call backs when a new user is // added too. @@ -299,20 +298,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // to get the most up-to-date results. This is intended to reduce test // flakiness when checking available rollbacks immediately after // installing a package with rollback enabled. - final LinkedBlockingQueue result = new LinkedBlockingQueue<>(); - getHandler().post(() -> result.offer(true)); - + CountDownLatch latch = new CountDownLatch(1); + getHandler().post(() -> latch.countDown()); try { - result.take(); + latch.await(); } catch (InterruptedException ie) { - // We may not get the most up-to-date information, but whatever we - // can get now is better than nothing, so log but otherwise ignore - // the exception. - Slog.w(TAG, "Interrupted while waiting for handler thread in getAvailableRollbacks"); + throw new IllegalStateException("RollbackManagerHandlerThread interrupted"); } synchronized (mLock) { - ensureRollbackDataLoadedLocked(); List rollbacks = new ArrayList<>(); for (int i = 0; i < mRollbacks.size(); ++i) { RollbackData data = mRollbacks.get(i); @@ -329,7 +323,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { enforceManageRollbacks("getRecentlyCommittedRollbacks"); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); List rollbacks = new ArrayList<>(); for (int i = 0; i < mRollbacks.size(); ++i) { RollbackData data = mRollbacks.get(i); @@ -364,8 +357,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { final long timeDifference = mRelativeBootTime - oldRelativeBootTime; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - Iterator iter = mRollbacks.iterator(); while (iter.hasNext()) { RollbackData data = iter.next(); @@ -544,13 +535,21 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Manifest.permission.TEST_MANAGE_ROLLBACKS, "reloadPersistedData"); - synchronized (mLock) { - mRollbacks = null; - } + CountDownLatch latch = new CountDownLatch(1); getHandler().post(() -> { updateRollbackLifetimeDurationInMillis(); - ensureRollbackDataLoaded(); + synchronized (mLock) { + mRollbacks.clear(); + mRollbacks.addAll(mRollbackStore.loadAllRollbackData()); + } + latch.countDown(); }); + + try { + latch.await(); + } catch (InterruptedException ie) { + throw new IllegalStateException("RollbackManagerHandlerThread interrupted"); + } } @Override @@ -559,7 +558,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Manifest.permission.TEST_MANAGE_ROLLBACKS, "expireRollbackForPackage"); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); Iterator iter = mRollbacks.iterator(); while (iter.hasNext()) { RollbackData data = iter.next(); @@ -583,7 +581,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { try { Thread.sleep(millis); } catch (InterruptedException e) { - // ignored. + throw new IllegalStateException("RollbackManagerHandlerThread interrupted"); } }); } @@ -626,7 +624,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { List restoreInProgress = new ArrayList<>(); Set apexPackageNames = new HashSet<>(); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (RollbackData data : mRollbacks) { if (data.isStaged()) { if (data.state == RollbackData.ROLLBACK_STATE_ENABLING) { @@ -688,41 +685,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { }); } - /** - * Load rollback data from storage if it has not already been loaded. - * After calling this function, mRollbacks will be non-null. - */ - private void ensureRollbackDataLoaded() { - synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - } - } - - /** - * Load rollback data from storage if it has not already been loaded. - * After calling this function, mRollbacks will be non-null. - */ - @GuardedBy("mLock") - private void ensureRollbackDataLoadedLocked() { - if (mRollbacks == null) { - loadAllRollbackDataLocked(); - } - } - - /** - * Load all rollback data from storage. - * Note: We do potentially heavy IO here while holding mLock, because we - * have to have the rollback data loaded before we can do anything else - * meaningful. - */ - @GuardedBy("mLock") - private void loadAllRollbackDataLocked() { - mRollbacks = mRollbackStore.loadAllRollbackData(); - for (RollbackData data : mRollbacks) { - mAllocatedRollbackIds.put(data.info.getRollbackId(), true); - } - } - /** * Called when a package has been replaced with a different version. * Removes all backups for the package not matching the currently @@ -734,7 +696,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { VersionedPackage installedVersion = getInstalledPackageVersion(packageName); synchronized (mLock) { - ensureRollbackDataLoadedLocked(); Iterator iter = mRollbacks.iterator(); while (iter.hasNext()) { RollbackData data = iter.next(); @@ -803,8 +764,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { Instant now = Instant.now(); Instant oldest = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); - Iterator iter = mRollbacks.iterator(); while (iter.hasNext()) { RollbackData data = iter.next(); @@ -924,7 +883,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // TODO: This check could be made more efficient. RollbackData rd = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { RollbackData data = mRollbacks.get(i); if (data.apkSessionId == parentSession.getSessionId()) { @@ -1080,7 +1038,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { private void snapshotUserDataInternal(String packageName) { synchronized (mLock) { // staged installs - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); i++) { RollbackData data = mRollbacks.get(i); if (data.state != RollbackData.ROLLBACK_STATE_ENABLING) { @@ -1113,7 +1070,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { PackageRollbackInfo info = null; RollbackData rollbackData = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { RollbackData data = mRollbacks.get(i); if (data.restoreUserDataInProgress) { @@ -1209,7 +1165,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { getHandler().post(() -> { RollbackData rd = null; synchronized (mLock) { - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { RollbackData data = mRollbacks.get(i); if (data.stagedSessionId == originalSessionId) { @@ -1380,7 +1335,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // device reboots between when the session is // committed and this point. Revisit this after // adding support for rollback of staged installs. - ensureRollbackDataLoadedLocked(); mRollbacks.add(data); } @@ -1417,9 +1371,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { */ private RollbackData getRollbackForId(int rollbackId) { synchronized (mLock) { - // TODO: Have ensureRollbackDataLoadedLocked return the list of - // available rollbacks, to hopefully avoid forgetting to call it? - ensureRollbackDataLoadedLocked(); for (int i = 0; i < mRollbacks.size(); ++i) { RollbackData data = mRollbacks.get(i); if (data.info.getRollbackId() == rollbackId) { From bcf89b81f505660eecc9980f2fdb0c95184197d5 Mon Sep 17 00:00:00 2001 From: Gavin Corkery Date: Thu, 6 Jun 2019 18:17:30 +0100 Subject: [PATCH 10/14] Add test for rollback of userdata with multiple rollbacks This test ensures that if a staged install is abandoned, and then staged again, the userdata snapshot will match the correct rollback. Since there will be multiple rollbacks in the ENABLING state for the same package, it is important to ensure that the userdata for the abandoned rollback is not used. Test: atest StagedRollbackTest Bug: 134035054 Change-Id: Ic977e747103c9a9a44592846de73287788cbac6d Merged-In: Icae7226dfb393c5ffc31dd0116f61141e84f5a42 --- .../tests/rollback/StagedRollbackTest.java | 40 ++++++++++++++++++- .../rollback/host/StagedRollbackTest.java | 12 ++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index a67bf3ca0b5dd..1f1eac1fd46eb 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -26,6 +26,7 @@ import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageInstaller; import android.content.rollback.RollbackInfo; import android.content.rollback.RollbackManager; @@ -33,6 +34,7 @@ import androidx.test.InstrumentationRegistry; import com.android.cts.install.lib.Install; import com.android.cts.install.lib.InstallUtils; +import com.android.cts.install.lib.LocalIntentSender; import com.android.cts.install.lib.TestApp; import com.android.cts.install.lib.Uninstall; import com.android.cts.rollback.lib.Rollback; @@ -207,4 +209,40 @@ public class StagedRollbackTest { InstrumentationRegistry.getContext().getPackageManager(), 0); return comp.getPackageName(); } -} + + @Test + public void testPreviouslyAbandonedRollbacksEnableRollback() throws Exception { + Uninstall.packages(TestApp.A); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + + int sessionId = Install.single(TestApp.A2).setStaged().setEnableRollback().commit(); + PackageInstaller pi = InstrumentationRegistry.getContext().getPackageManager() + .getPackageInstaller(); + pi.abandonSession(sessionId); + + // Remove the first intent sender result, so that the next staged install session does not + // erroneously think that it has itself been abandoned. + // TODO(b/136260017): Restructure LocalIntentSender to negate the need for this step. + LocalIntentSender.getIntentSenderResult(); + Install.single(TestApp.A2).setStaged().setEnableRollback().commit(); + } + + @Test + public void testPreviouslyAbandonedRollbacksCommitRollback() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + InstallUtils.processUserData(TestApp.A); + + RollbackManager rm = RollbackUtils.getRollbackManager(); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getAvailableRollbacks(), TestApp.A); + RollbackUtils.rollback(rollback.getRollbackId()); + } + + @Test + public void testPreviouslyAbandonedRollbacksCheckUserdataRollback() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); + Uninstall.packages(TestApp.A); + } +} \ No newline at end of file diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index b767b0842f786..71a1e7d27aba3 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -167,6 +167,18 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { runPhase("assertNoNetworkStackRollbackCommitted"); } + /** + * Tests rolling back user data where there are multiple rollbacks for that package. + */ + @Test + public void testPreviouslyAbandonedRollbacks() throws Exception { + runPhase("testPreviouslyAbandonedRollbacksEnableRollback"); + getDevice().reboot(); + runPhase("testPreviouslyAbandonedRollbacksCommitRollback"); + getDevice().reboot(); + runPhase("testPreviouslyAbandonedRollbacksCheckUserdataRollback"); + } + private String getNetworkStackPath() throws DeviceNotAvailableException { // Find the NetworkStack path (can be NetworkStack.apk or NetworkStackNext.apk) return getDevice().executeShellCommand("ls /system/priv-app/NetworkStack*/*.apk"); From 1d5db7776ecb158302fed124f6ef75ea1324a47a Mon Sep 17 00:00:00 2001 From: Richard Uhler Date: Mon, 1 Jul 2019 16:27:43 +0100 Subject: [PATCH 11/14] delete ENABLING rollback if we can't get session info for it. If we can't get the SessionInfo for a rollback in ENABLE state on boot, then presumably we'll never be able to get SessionInfo for it, so delete the rollback. Test: adb install TestAppAv1.apk; adb install --enable-rollback --staged TestAppAv2.apk dumpsys rollback adb shell pm install-abandon adb reboot, confirm /data/rollback/ does not exist adb reboot dumpsys rollback, confirm rollback is no longer listed. Bug: 134652027 Change-Id: I3c5114e0e6b1fa877cd9e7bd2b4cd18c53d6b3ef Merged-In: Ie583536d0ec75c442bd4c9e4456bee120050728c --- .../rollback/RollbackManagerServiceImpl.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 1579f3080bc4c..eb2f648e82782 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -645,17 +645,14 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { PackageInstaller installer = mContext.getPackageManager().getPackageInstaller(); PackageInstaller.SessionInfo session = installer.getSessionInfo( data.stagedSessionId); - // TODO: What if session is null? - if (session != null) { - if (session.isStagedSessionApplied()) { - makeRollbackAvailable(data); - } else if (session.isStagedSessionFailed()) { - // TODO: Do we need to remove this from - // mRollbacks, or is it okay to leave as - // unavailable until the next reboot when it will go - // away on its own? - deleteRollback(data); - } + if (session == null || session.isStagedSessionFailed()) { + // TODO: Do we need to remove this from + // mRollbacks, or is it okay to leave as + // unavailable until the next reboot when it will go + // away on its own? + deleteRollback(data); + } else if (session.isStagedSessionApplied()) { + makeRollbackAvailable(data); } } From b9f1521715dba80031c8144ec9be3edee44e9f1e Mon Sep 17 00:00:00 2001 From: shafik Date: Tue, 2 Jul 2019 11:32:59 +0100 Subject: [PATCH 12/14] Uninstall testapps before running SecondaryUserRollbackTest Add target_preparer for uninstalling TestApp.A and TestApp.B before running SecondaryUserRollbackTest. Also, fix the tearDown command after each case to uninstall the right apps. Test: atest SecondaryUserRollbackTest ; atest SecondaryUserRollbackTest Bug: 136538996 Change-Id: I35edde58eb8b520f167bace7848956d091155158 Merged-In: I3d5decae03bf9d2f9d78a534399214da05a6d372 --- tests/RollbackTest/SecondaryUserRollbackTest.xml | 4 ++++ .../tests/rollback/host/SecondaryUserRollbackTest.java | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/RollbackTest/SecondaryUserRollbackTest.xml b/tests/RollbackTest/SecondaryUserRollbackTest.xml index ad3761018a255..6b3f05c429836 100644 --- a/tests/RollbackTest/SecondaryUserRollbackTest.xml +++ b/tests/RollbackTest/SecondaryUserRollbackTest.xml @@ -19,6 +19,10 @@