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

Commit a211a54e authored by JW Wang's avatar JW Wang
Browse files

Rewrite some methods using waitForResult (4/n)

We will be able to remove mLock since now all states are modified in the handler thread.

Bug: 145335013
Test: atest CtsRollbackManagerHostTestCases
Test: atest RollbackTest
Test: atest StagedRollbackTest

Change-Id: Id50f54e8315546e474bd482d67238fbac8b74767
parent 26f89e2f
Loading
Loading
Loading
Loading
+47 −56
Original line number Diff line number Diff line
@@ -84,11 +84,10 @@ import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
 * Implementation of service that manages APK level rollbacks.
@@ -301,6 +300,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        registerTimeChangeReceiver();
    }

    private <U> U awaitResult(Supplier<U> supplier) {
        assertNotInWorkerThread();
        try {
            return CompletableFuture.supplyAsync(supplier, mExecutor).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException(e);
        }
    }

    private void awaitResult(Runnable runnable) {
        assertNotInWorkerThread();
        try {
@@ -363,6 +371,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
    public ParceledListSlice getAvailableRollbacks() {
        assertNotInWorkerThread();
        enforceManageRollbacks("getAvailableRollbacks");
        return awaitResult(() -> {
            assertInWorkerThread();
            synchronized (mLock) {
                List<RollbackInfo> rollbacks = new ArrayList<>();
                for (int i = 0; i < mRollbacks.size(); ++i) {
@@ -373,6 +383,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                }
                return new ParceledListSlice<>(rollbacks);
            }
        });
    }

    @ExtThread
@@ -381,6 +392,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        assertNotInWorkerThread();
        enforceManageRollbacks("getRecentlyCommittedRollbacks");

        return awaitResult(() -> {
            assertInWorkerThread();
            synchronized (mLock) {
                List<RollbackInfo> rollbacks = new ArrayList<>();
                for (int i = 0; i < mRollbacks.size(); ++i) {
@@ -391,6 +404,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                }
                return new ParceledListSlice<>(rollbacks);
            }
        });
    }

    @ExtThread
@@ -469,21 +483,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                Manifest.permission.TEST_MANAGE_ROLLBACKS,
                "reloadPersistedData");

        CountDownLatch latch = new CountDownLatch(1);
        getHandler().post(() -> {
        awaitResult(() -> {
            assertInWorkerThread();
            synchronized (mLock) {
                mRollbacks.clear();
                mRollbacks.addAll(mRollbackStore.loadRollbacks());
            }
            latch.countDown();
        });

        try {
            latch.await();
        } catch (InterruptedException ie) {
            throw new IllegalStateException("RollbackManagerHandlerThread interrupted");
        }
    }

    @WorkerThread
@@ -553,8 +559,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        // In order to ensure that no package begins running while a backup or restore is taking
        // place, onUnlockUser must remain blocked until all pending backups and restores have
        // completed.
        CountDownLatch latch = new CountDownLatch(1);
        getHandler().post(() -> {
        awaitResult(() -> {
            assertInWorkerThread();
            final List<Rollback> rollbacks;
            synchronized (mLock) {
@@ -565,15 +570,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                Rollback rollback = rollbacks.get(i);
                rollback.commitPendingBackupAndRestoreForUser(userId, mAppDataRollbackHelper);
            }

            latch.countDown();
        });

        try {
            latch.await();
        } catch (InterruptedException ie) {
            throw new IllegalStateException("RollbackManagerHandlerThread interrupted");
        }
    }

    @WorkerThread
@@ -999,19 +996,17 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
            throw new SecurityException("notifyStagedSession may only be called by the system.");
        }
        final LinkedBlockingQueue<Integer> result = new LinkedBlockingQueue<>();

        // NOTE: We post this runnable on the RollbackManager's binder thread because we'd prefer
        // to preserve the invariant that all operations that modify state happen there.
        getHandler().post(() -> {
        return awaitResult(() -> {
            assertInWorkerThread();
            PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();

            final PackageInstaller.SessionInfo session = installer.getSessionInfo(sessionId);
            if (session == null) {
                Slog.e(TAG, "No matching install session for: " + sessionId);
                result.offer(-1);
                return;
                return -1;
            }

            Rollback newRollback;
@@ -1039,18 +1034,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
            }

            if (!completeEnableRollback(newRollback)) {
                result.offer(-1);
                return -1;
            } else {
                result.offer(newRollback.info.getRollbackId());
                return newRollback.info.getRollbackId();
            }
        });

        try {
            return result.take();
        } catch (InterruptedException ie) {
            Slog.e(TAG, "Interrupted while waiting for notifyStagedSession response");
            return -1;
        }
    }

    @ExtThread
@@ -1318,6 +1306,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;

        IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
        awaitResult(() -> {
            assertInWorkerThread();
            synchronized (mLock) {
                for (Rollback rollback : mRollbacks) {
                    rollback.dump(ipw);
@@ -1325,6 +1315,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
                ipw.println();
                PackageWatchdog.getInstance(mContext).dump(ipw);
            }
        });
    }

    @AnyThread