Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e27c922 authored by Neil Fuller's avatar Neil Fuller
Browse files

Fix a no-op uninstall being treated as a failure

Treat a stageUninstall() doing nothing as a success, not a
failure. This prevents the system retrying the uninstall
later.

Unit tests run with:

make -j30 FrameworksServicesTests
adb install -r -g \
  "out/target/product/marlin/data/app/FrameworksServicesTests/FrameworksServicesTests.apk"
adb shell am instrument -e package com.android.server.timezone -w \
  com.android.frameworks.servicestests \
  "com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner"

Test: See above
Test: Manual testing, adb dumpsys timezone
Test: PTS: run pts -m PtsTimeZoneTestCases
Bug: 65657176
Change-Id: Ifd205da90e848552711ac3f4207cd22ad2c2747b
parent 8ccd08c7
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -343,16 +343,20 @@ public final class RulesManagerService extends IRulesManager.Stub {
        @Override
        public void run() {
            EventLogTags.writeTimezoneUninstallStarted(toStringOrNull(mCheckToken));
            boolean success = false;
            boolean packageTrackerStatus = false;
            try {
                success = mInstaller.stageUninstall();
                // Right now we just have success (0) / failure (1). All clients should be checking
                // against SUCCESS. More granular failures may be added in future.
                int resultCode = success ? Callback.SUCCESS
                        : Callback.ERROR_UNKNOWN_FAILURE;
                int uninstallResult = mInstaller.stageUninstall();
                packageTrackerStatus = (uninstallResult == TimeZoneDistroInstaller.UNINSTALL_SUCCESS
                        || uninstallResult == TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);

                // Right now we just have Callback.SUCCESS / Callback.ERROR_UNKNOWN_FAILURE for
                // uninstall. All clients should be checking against SUCCESS. More granular failures
                // may be added in future.
                int callbackResultCode =
                        packageTrackerStatus ? Callback.SUCCESS : Callback.ERROR_UNKNOWN_FAILURE;
                EventLogTags.writeTimezoneUninstallComplete(
                        toStringOrNull(mCheckToken), resultCode);
                sendFinishedStatus(mCallback, resultCode);
                        toStringOrNull(mCheckToken), callbackResultCode);
                sendFinishedStatus(mCallback, callbackResultCode);
            } catch (Exception e) {
                EventLogTags.writeTimezoneUninstallComplete(
                        toStringOrNull(mCheckToken), Callback.ERROR_UNKNOWN_FAILURE);
@@ -360,7 +364,7 @@ public final class RulesManagerService extends IRulesManager.Stub {
                sendFinishedStatus(mCallback, Callback.ERROR_UNKNOWN_FAILURE);
            } finally {
                // Notify the package tracker that the operation is now complete.
                mPackageTracker.recordCheckResult(mCheckToken, success);
                mPackageTracker.recordCheckResult(mCheckToken, packageTrackerStatus);

                mOperationInProgress.set(false);
            }
+37 −5
Original line number Diff line number Diff line
@@ -585,7 +585,39 @@ public class RulesManagerServiceTest {
        verifyNoPackageTrackerCallsMade();

        // Set up the installer.
        configureStageUninstallExpectation(true /* success */);
        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);

        // Simulate the async execution.
        mFakeExecutor.simulateAsyncExecutionOfLastCommand();

        // Verify the expected calls were made to other components.
        verifyStageUninstallCalled();
        verifyPackageTrackerCalled(token, true /* success */);

        // Check the callback was called.
        callback.assertResultReceived(Callback.SUCCESS);
    }

    @Test
    public void requestUninstall_asyncNothingInstalled() throws Exception {
        configureCallerHasPermission();

        CheckToken token = createArbitraryToken();
        byte[] tokenBytes = token.toByteArray();

        TestCallback callback = new TestCallback();

        // Request the uninstall.
        assertEquals(RulesManager.SUCCESS,
                mRulesManagerService.requestUninstall(tokenBytes, callback));

        // Assert nothing has happened yet.
        callback.assertNoResultReceived();
        verifyNoInstallerCallsMade();
        verifyNoPackageTrackerCallsMade();

        // Set up the installer.
        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_NOTHING_INSTALLED);

        // Simulate the async execution.
        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
@@ -613,7 +645,7 @@ public class RulesManagerServiceTest {
        callback.assertNoResultReceived();

        // Set up the installer.
        configureStageUninstallExpectation(true /* success */);
        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_SUCCESS);

        // Simulate the async execution.
        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
@@ -644,7 +676,7 @@ public class RulesManagerServiceTest {
        callback.assertNoResultReceived();

        // Set up the installer.
        configureStageUninstallExpectation(false /* success */);
        configureStageUninstallExpectation(TimeZoneDistroInstaller.UNINSTALL_FAIL);

        // Simulate the async execution.
        mFakeExecutor.simulateAsyncExecutionOfLastCommand();
@@ -849,8 +881,8 @@ public class RulesManagerServiceTest {
                .thenReturn(resultCode);
    }

    private void configureStageUninstallExpectation(boolean success) throws Exception {
        doReturn(success).when(mMockTimeZoneDistroInstaller).stageUninstall();
    private void configureStageUninstallExpectation(int resultCode) throws Exception {
        doReturn(resultCode).when(mMockTimeZoneDistroInstaller).stageUninstall();
    }

    private void verifyStageInstallCalled() throws Exception {