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

Commit a67d1076 authored by Bernardo Rufino's avatar Bernardo Rufino Committed by Android (Google) Code Review
Browse files

Merge "Binding on-demand #7: PerformInitializeTask usage"

parents ea713a38 79155590
Loading
Loading
Loading
Loading
+27 −25
Original line number Diff line number Diff line
@@ -1086,15 +1086,14 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
    }

    /**
     * Maintain persistent state around whether need to do an initialize operation.
     * Must be called with the queue lock held.
     * Maintain persistent state around whether need to do an initialize operation. This will lock
     * on {@link #getQueueLock()}.
     */
    @GuardedBy("mQueueLock")
    public void recordInitPendingLocked(
    public void recordInitPending(
            boolean isPending, String transportName, String transportDirName) {
        synchronized (mQueueLock) {
            if (MORE_DEBUG) {
            Slog.i(TAG, "recordInitPendingLocked: " + isPending
                    + " on transport " + transportName);
                Slog.i(TAG, "recordInitPending(" + isPending + ") on transport " + transportName);
            }

            File stateDir = new File(mBaseStateDir, transportDirName);
@@ -1116,6 +1115,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
                mPendingInits.remove(transportName);
            }
        }
    }

    // Reset all of our bookkeeping, in response to having been told that
    // the backend data has been wiped [due to idle expiry, for example],
@@ -2321,7 +2321,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
        final long oldId = Binder.clearCallingIdentity();
        try {
            mWakelock.acquire();
            mBackupHandler.post(new PerformInitializeTask(this, transportNames, observer));
            OnTaskFinishedListener listener = caller -> mWakelock.release();
            mBackupHandler.post(
                    new PerformInitializeTask(this, transportNames, observer, listener));
        } finally {
            Binder.restoreCallingIdentity(oldId);
        }
@@ -2812,7 +2814,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter

                        // build the set of transports for which we are posting an init
                        for (int i = 0; i < transportNames.size(); i++) {
                            recordInitPendingLocked(
                            recordInitPending(
                                    true,
                                    transportNames.get(i),
                                    transportDirNames.get(i));
+67 −26
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.backup.internal;

import static com.android.server.backup.RefactoredBackupManagerService.TAG;

import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.backup.BackupTransport;
import android.app.backup.IBackupObserver;
@@ -26,23 +27,63 @@ import android.os.SystemClock;
import android.util.EventLog;
import android.util.Slog;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.server.EventLogTags;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.transport.TransportClient;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * Attempts to call {@link BackupTransport#initializeDevice()} followed by
 * {@link BackupTransport#finishBackup()} for the transport names passed in with the intent of
 * wiping backup data from the transport.
 *
 * If the transport returns error, it will record the operation as pending and schedule it to run in
 * a future time according to {@link BackupTransport#requestBackupTime()}. The result status
 * reported to observers will be the last unsuccessful status reported by the transports. If every
 * operation was successful then it's {@link BackupTransport#TRANSPORT_OK}.
 */
public class PerformInitializeTask implements Runnable {
    private final RefactoredBackupManagerService mBackupManagerService;
    private final TransportManager mTransportManager;
    private final String[] mQueue;
    private final File mBaseStateDir;
    private final OnTaskFinishedListener mListener;
    @Nullable private IBackupObserver mObserver;

    private RefactoredBackupManagerService backupManagerService;
    String[] mQueue;
    IBackupObserver mObserver;
    public PerformInitializeTask(
            RefactoredBackupManagerService backupManagerService,
            String[] transportNames,
            @Nullable IBackupObserver observer,
            OnTaskFinishedListener listener) {
        this(
                backupManagerService,
                backupManagerService.getTransportManager(),
                transportNames,
                observer,
                listener,
                backupManagerService.getBaseStateDir());
    }

    public PerformInitializeTask(RefactoredBackupManagerService backupManagerService,
            String[] transportNames, IBackupObserver observer) {
        this.backupManagerService = backupManagerService;
    @VisibleForTesting
    PerformInitializeTask(
            RefactoredBackupManagerService backupManagerService,
            TransportManager transportManager,
            String[] transportNames,
            @Nullable IBackupObserver observer,
            OnTaskFinishedListener listener,
            File baseStateDir) {
        mBackupManagerService = backupManagerService;
        mTransportManager = transportManager;
        mQueue = transportNames;
        mObserver = observer;
        mListener = listener;
        mBaseStateDir = baseStateDir;
    }

    private void notifyResult(String target, int status) {
@@ -67,21 +108,25 @@ public class PerformInitializeTask implements Runnable {

    public void run() {
        // mWakelock is *acquired* when execution begins here
        String callerLogString = "PerformInitializeTask.run()";
        List<TransportClient> transportClientsToDisposeOf = new ArrayList<>(mQueue.length);
        int result = BackupTransport.TRANSPORT_OK;
        try {
            for (String transportName : mQueue) {
                IBackupTransport transport =
                        backupManagerService.getTransportManager().getTransportBinder(
                                transportName);
                if (transport == null) {
                TransportClient transportClient =
                        mTransportManager.getTransportClient(transportName, callerLogString);
                if (transportClient == null) {
                    Slog.e(TAG, "Requested init for " + transportName + " but not found");
                    continue;
                }
                transportClientsToDisposeOf.add(transportClient);

                Slog.i(TAG, "Initializing (wiping) backup transport storage: " + transportName);
                String transportDirName = transport.transportDirName();
                String transportDirName = transportClient.getTransportDirName();
                EventLog.writeEvent(EventLogTags.BACKUP_START, transportDirName);
                long startRealtime = SystemClock.elapsedRealtime();

                IBackupTransport transport = transportClient.connectOrThrow(callerLogString);
                int status = transport.initializeDevice();

                if (status == BackupTransport.TRANSPORT_OK) {
@@ -93,42 +138,38 @@ public class PerformInitializeTask implements Runnable {
                    Slog.i(TAG, "Device init successful");
                    int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
                    EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
                    backupManagerService
                            .resetBackupState(new File(backupManagerService.getBaseStateDir(),
                                    transportDirName));
                    File stateFileDir = new File(mBaseStateDir, transportDirName);
                    mBackupManagerService.resetBackupState(stateFileDir);
                    EventLog.writeEvent(EventLogTags.BACKUP_SUCCESS, 0, millis);
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.recordInitPendingLocked(
                                false, transportName, transportDirName);
                    }
                    mBackupManagerService.recordInitPending(false, transportName, transportDirName);
                    notifyResult(transportName, BackupTransport.TRANSPORT_OK);
                } else {
                    // If this didn't work, requeue this one and try again
                    // after a suitable interval
                    Slog.e(TAG, "Transport error in initializeDevice()");
                    EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.recordInitPendingLocked(
                                true, transportName, transportDirName);
                    }
                    mBackupManagerService.recordInitPending(true, transportName, transportDirName);
                    notifyResult(transportName, status);
                    result = status;

                    // do this via another alarm to make sure of the wakelock states
                    long delay = transport.requestBackupTime();
                    Slog.w(TAG, "Init failed on " + transportName + " resched in " + delay);
                    backupManagerService.getAlarmManager().set(AlarmManager.RTC_WAKEUP,
                    mBackupManagerService.getAlarmManager().set(
                            AlarmManager.RTC_WAKEUP,
                            System.currentTimeMillis() + delay,
                            backupManagerService.getRunInitIntent());
                            mBackupManagerService.getRunInitIntent());
                }
            }
        } catch (Exception e) {
            Slog.e(TAG, "Unexpected error performing init", e);
            result = BackupTransport.TRANSPORT_ERROR;
        } finally {
            // Done; release the wakelock
            for (TransportClient transportClient : transportClientsToDisposeOf) {
                mTransportManager.disposeOfTransportClient(transportClient, callerLogString);
            }
            notifyFinished(result);
            backupManagerService.getWakelock().release();
            mListener.onFinished(callerLogString);
        }
    }
}
+18 −14
Original line number Diff line number Diff line
@@ -23,37 +23,41 @@ import static com.android.server.backup.RefactoredBackupManagerService.TAG;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.util.ArraySet;
import android.util.Slog;

import com.android.server.backup.RefactoredBackupManagerService;

public class RunInitializeReceiver extends BroadcastReceiver {

    private RefactoredBackupManagerService backupManagerService;
    private final RefactoredBackupManagerService mBackupManagerService;

    public RunInitializeReceiver(RefactoredBackupManagerService backupManagerService) {
        this.backupManagerService = backupManagerService;
        mBackupManagerService = backupManagerService;
    }

    public void onReceive(Context context, Intent intent) {
        if (RUN_INITIALIZE_ACTION.equals(intent.getAction())) {
            synchronized (backupManagerService.getQueueLock()) {
                final ArraySet<String> pendingInits = backupManagerService.getPendingInits();
            synchronized (mBackupManagerService.getQueueLock()) {
                final ArraySet<String> pendingInits = mBackupManagerService.getPendingInits();
                if (DEBUG) {
                    Slog.v(TAG, "Running a device init; " + pendingInits.size() + " pending");
                }

                if (pendingInits.size() > 0) {
                    final String[] transports = pendingInits.toArray(new String[pendingInits.size()]);
                    PerformInitializeTask initTask = new PerformInitializeTask(backupManagerService,
                            transports, null);

                    // Acquire the wakelock and pass it to the init thread.  it will
                    // be released once init concludes.
                    backupManagerService.clearPendingInits();
                    backupManagerService.getWakelock().acquire();
                    backupManagerService.getBackupHandler().post(initTask);
                    final String[] transports =
                            pendingInits.toArray(new String[pendingInits.size()]);

                    mBackupManagerService.clearPendingInits();

                    PowerManager.WakeLock wakelock = mBackupManagerService.getWakelock();
                    wakelock.acquire();
                    OnTaskFinishedListener listener = caller -> wakelock.release();

                    Runnable task =
                            new PerformInitializeTask(
                                    mBackupManagerService, transports, null, listener);
                    mBackupManagerService.getBackupHandler().post(task);
                }
            }
        }
+0 −3
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.server.backup;

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

import static junit.framework.Assert.fail;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.robolectric.shadow.api.Shadow.extract;
@@ -58,7 +56,6 @@ import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowLog;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.shadows.ShadowPackageManager;
import org.testng.Assert.ThrowingRunnable;

import java.util.ArrayList;
import java.util.Arrays;
+411 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading