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

Commit 57ee724e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Offload teardown logic after BackupAgent crash to a worker thread" into...

Merge "Offload teardown logic after BackupAgent crash to a worker thread" into tm-qpr-dev am: 8f24026d

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



Change-Id: Ie68bd8de52f81ecc9480f82f8657292cd10af0cb
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 9c0d9e71 8f24026d
Loading
Loading
Loading
Loading
+23 −10
Original line number Original line Diff line number Diff line
@@ -3721,6 +3721,10 @@ public class UserBackupManagerService {
            Slog.w(TAG, "agentDisconnected: the backup agent for " + packageName
            Slog.w(TAG, "agentDisconnected: the backup agent for " + packageName
                    + " died: cancel current operations");
                    + " died: cancel current operations");


            // Offload operation cancellation off the main thread as the cancellation callbacks
            // might call out to BackupTransport. Other operations started on the same package
            // before the cancellation callback has executed will also be cancelled by the callback.
            Runnable cancellationRunnable = () -> {
                // handleCancel() causes the PerformFullTransportBackupTask to go on to
                // handleCancel() causes the PerformFullTransportBackupTask to go on to
                // tearDownAgentAndKill: that will unbindBackupAgent in the Activity Manager, so
                // tearDownAgentAndKill: that will unbindBackupAgent in the Activity Manager, so
                // that the package being backed up doesn't get stuck in restricted mode until the
                // that the package being backed up doesn't get stuck in restricted mode until the
@@ -3732,10 +3736,19 @@ public class UserBackupManagerService {
                    }
                    }
                    handleCancel(token, true /* cancelAll */);
                    handleCancel(token, true /* cancelAll */);
                }
                }
            };
            getThreadForAsyncOperation(/* operationName */ "agent-disconnected",
                    cancellationRunnable).start();

            mAgentConnectLock.notifyAll();
            mAgentConnectLock.notifyAll();
        }
        }
    }
    }


    @VisibleForTesting
    Thread getThreadForAsyncOperation(String operationName, Runnable operation) {
        return new Thread(operation, operationName);
    }

    /**
    /**
     * An application being installed will need a restore pass, then the {@link PackageManager} will
     * An application being installed will need a restore pass, then the {@link PackageManager} will
     * need to be told when the restore is finished.
     * need to be told when the restore is finished.
+23 −0
Original line number Original line Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.backup;


import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertThat;


import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -61,6 +62,7 @@ import java.util.function.IntConsumer;
public class UserBackupManagerServiceTest {
public class UserBackupManagerServiceTest {
    private static final String TEST_PACKAGE = "package1";
    private static final String TEST_PACKAGE = "package1";
    private static final String[] TEST_PACKAGES = new String[] { TEST_PACKAGE };
    private static final String[] TEST_PACKAGES = new String[] { TEST_PACKAGE };
    private static final int WORKER_THREAD_TIMEOUT_MILLISECONDS = 1;


    @Mock Context mContext;
    @Mock Context mContext;
    @Mock IBackupManagerMonitor mBackupManagerMonitor;
    @Mock IBackupManagerMonitor mBackupManagerMonitor;
@@ -179,6 +181,7 @@ public class UserBackupManagerServiceTest {


        mService.agentDisconnected("com.android.foo");
        mService.agentDisconnected("com.android.foo");


        mService.waitForAsyncOperation();
        verify(mOperationStorage).cancelOperation(eq(123), eq(true), any(IntConsumer.class));
        verify(mOperationStorage).cancelOperation(eq(123), eq(true), any(IntConsumer.class));
        verify(mOperationStorage).cancelOperation(eq(456), eq(true), any());
        verify(mOperationStorage).cancelOperation(eq(456), eq(true), any());
        verify(mOperationStorage).cancelOperation(eq(789), eq(true), any());
        verify(mOperationStorage).cancelOperation(eq(789), eq(true), any());
@@ -207,6 +210,8 @@ public class UserBackupManagerServiceTest {
        boolean isEnabledStatePersisted = false;
        boolean isEnabledStatePersisted = false;
        boolean shouldUseNewBackupEligibilityRules = false;
        boolean shouldUseNewBackupEligibilityRules = false;


        private volatile Thread mWorkerThread = null;

        TestBackupService(Context context, PackageManager packageManager,
        TestBackupService(Context context, PackageManager packageManager,
                LifecycleOperationStorage operationStorage) {
                LifecycleOperationStorage operationStorage) {
            super(context, packageManager, operationStorage);
            super(context, packageManager, operationStorage);
@@ -229,5 +234,23 @@ public class UserBackupManagerServiceTest {
        boolean shouldUseNewBackupEligibilityRules() {
        boolean shouldUseNewBackupEligibilityRules() {
            return shouldUseNewBackupEligibilityRules;
            return shouldUseNewBackupEligibilityRules;
        }
        }

        @Override
        Thread getThreadForAsyncOperation(String operationName, Runnable operation) {
            mWorkerThread = super.getThreadForAsyncOperation(operationName, operation);
            return mWorkerThread;
        }

        private void waitForAsyncOperation() {
            if (mWorkerThread == null) {
                return;
            }

            try {
                mWorkerThread.join(/* millis */ WORKER_THREAD_TIMEOUT_MILLISECONDS);
            } catch (InterruptedException e) {
                fail("Failed waiting for worker thread to complete: " + e.getMessage());
            }
        }
    }
    }
}
}