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

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

Merge "Binding on-demand #1: TransportClient infra + PerformBackupTask usage"

parents 81d33e9b af547f4a
Loading
Loading
Loading
Loading
+27 −4
Original line number Original line Diff line number Diff line
@@ -48,7 +48,6 @@ import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.backup.SelectBackupTransportCallback;
import android.content.ActivityNotFoundException;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ComponentName;
@@ -103,6 +102,7 @@ import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.internal.BackupHandler;
import com.android.server.backup.internal.BackupHandler;
import com.android.server.backup.internal.BackupRequest;
import com.android.server.backup.internal.BackupRequest;
import com.android.server.backup.internal.ClearDataObserver;
import com.android.server.backup.internal.ClearDataObserver;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.internal.Operation;
import com.android.server.backup.internal.Operation;
import com.android.server.backup.internal.PerformInitializeTask;
import com.android.server.backup.internal.PerformInitializeTask;
import com.android.server.backup.internal.ProvisionedObserver;
import com.android.server.backup.internal.ProvisionedObserver;
@@ -117,6 +117,7 @@ import com.android.server.backup.params.ClearRetryParams;
import com.android.server.backup.params.RestoreParams;
import com.android.server.backup.params.RestoreParams;
import com.android.server.backup.restore.ActiveRestoreSession;
import com.android.server.backup.restore.ActiveRestoreSession;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupObserverUtils;
import com.android.server.backup.utils.BackupObserverUtils;
@@ -1585,8 +1586,27 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
            return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
            return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
        }
        }


        // We're using pieces of the new binding on-demand infra-structure and the old always-bound
        // infra-structure below this comment. The TransportManager.getCurrentTransportClient() line
        // is using the new one and TransportManager.getCurrentTransportBinder() is using the old.
        // This is weird but there is a reason.
        // This is the natural place to put TransportManager.getCurrentTransportClient() because of
        // the null handling below that should be the same for TransportClient.
        // TransportClient.connect() would return a IBackupTransport for us (instead of using the
        // old infra), but it may block and we don't want this in this thread.
        // The only usage of transport in this method is for transport.transportDirName(). When the
        // push-from-transport part of binding on-demand is in place we will replace the calls for
        // IBackupTransport.transportDirName() with calls for
        // TransportManager.transportDirName(transportName) or similar. So we'll leave the old piece
        // here until we implement that.
        // TODO(brufino): Remove always-bound code mTransportManager.getCurrentTransportBinder()
        TransportClient transportClient =
                mTransportManager.getCurrentTransportClient("BMS.requestBackup()");
        IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
        IBackupTransport transport = mTransportManager.getCurrentTransportBinder();
        if (transport == null) {
        if (transportClient == null || transport == null) {
            if (transportClient != null) {
                mTransportManager.disposeOfTransportClient(transportClient, "BMS.requestBackup()");
            }
            BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
            BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
            monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
            monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
                    BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
                    BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
@@ -1594,6 +1614,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
            return BackupManager.ERROR_TRANSPORT_ABORTED;
            return BackupManager.ERROR_TRANSPORT_ABORTED;
        }
        }


        OnTaskFinishedListener listener =
                caller -> mTransportManager.disposeOfTransportClient(transportClient, caller);

        ArrayList<String> fullBackupList = new ArrayList<>();
        ArrayList<String> fullBackupList = new ArrayList<>();
        ArrayList<String> kvBackupList = new ArrayList<>();
        ArrayList<String> kvBackupList = new ArrayList<>();
        for (String packageName : packages) {
        for (String packageName : packages) {
@@ -1640,8 +1663,8 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
        boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0;
        boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0;


        Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP);
        Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP);
        msg.obj = new BackupParams(transport, dirName, kvBackupList, fullBackupList, observer,
        msg.obj = new BackupParams(transportClient, dirName, kvBackupList, fullBackupList, observer,
                monitor, true, nonIncrementalBackup);
                monitor, listener, true, nonIncrementalBackup);
        mBackupHandler.sendMessage(msg);
        mBackupHandler.sendMessage(msg);
        return BackupManager.SUCCESS;
        return BackupManager.SUCCESS;
    }
    }
+75 −5
Original line number Original line Diff line number Diff line
@@ -16,8 +16,9 @@


package com.android.server.backup;
package com.android.server.backup;


import android.annotation.Nullable;
import android.app.backup.BackupManager;
import android.app.backup.BackupManager;
import android.app.backup.SelectBackupTransportCallback;
import android.app.backup.BackupTransport;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
@@ -44,9 +45,11 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IBackupTransport;
import com.android.server.EventLogTags;
import com.android.server.EventLogTags;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportClientManager;
import com.android.server.backup.transport.TransportConnectionListener;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.Iterator;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
@@ -60,8 +63,7 @@ public class TransportManager {
    private static final String TAG = "BackupTransportManager";
    private static final String TAG = "BackupTransportManager";


    @VisibleForTesting
    @VisibleForTesting
    /* package */ static final String SERVICE_ACTION_TRANSPORT_HOST =
    public static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST";
            "android.backup.TRANSPORT_HOST";


    private static final long REBINDING_TIMEOUT_UNPROVISIONED_MS = 30 * 1000; // 30 sec
    private static final long REBINDING_TIMEOUT_UNPROVISIONED_MS = 30 * 1000; // 30 sec
    private static final long REBINDING_TIMEOUT_PROVISIONED_MS = 5 * 60 * 1000; // 5 mins
    private static final long REBINDING_TIMEOUT_PROVISIONED_MS = 5 * 60 * 1000; // 5 mins
@@ -72,6 +74,7 @@ public class TransportManager {
    private final PackageManager mPackageManager;
    private final PackageManager mPackageManager;
    private final Set<ComponentName> mTransportWhitelist;
    private final Set<ComponentName> mTransportWhitelist;
    private final Handler mHandler;
    private final Handler mHandler;
    private final TransportClientManager mTransportClientManager;


    /**
    /**
     * This listener is called after we bind to any transport. If it returns true, this is a valid
     * This listener is called after we bind to any transport. If it returns true, this is a valid
@@ -95,6 +98,10 @@ public class TransportManager {
    @GuardedBy("mTransportLock")
    @GuardedBy("mTransportLock")
    private final Map<String, ComponentName> mBoundTransports = new ArrayMap<>();
    private final Map<String, ComponentName> mBoundTransports = new ArrayMap<>();


    /** Names of transports we've bound to at least once */
    @GuardedBy("mTransportLock")
    private final Map<String, ComponentName> mTransportsByName = new ArrayMap<>();

    /**
    /**
     * Callback interface for {@link #ensureTransportReady(ComponentName, TransportReadyCallback)}.
     * Callback interface for {@link #ensureTransportReady(ComponentName, TransportReadyCallback)}.
     */
     */
@@ -123,6 +130,7 @@ public class TransportManager {
        mCurrentTransportName = defaultTransport;
        mCurrentTransportName = defaultTransport;
        mTransportBoundListener = listener;
        mTransportBoundListener = listener;
        mHandler = new RebindOnTimeoutHandler(looper);
        mHandler = new RebindOnTimeoutHandler(looper);
        mTransportClientManager = new TransportClientManager(context);
    }
    }


    void onPackageAdded(String packageName) {
    void onPackageAdded(String packageName) {
@@ -204,6 +212,67 @@ public class TransportManager {
        return null;
        return null;
    }
    }


    /**
     * Returns the transport name associated with {@param transportClient} or {@code null} if not
     * found.
     */
    @Nullable
    public String getTransportName(TransportClient transportClient) {
        ComponentName transportComponent = transportClient.getTransportComponent();
        synchronized (mTransportLock) {
            for (Map.Entry<String, ComponentName> transportEntry : mTransportsByName.entrySet()) {
                if (transportEntry.getValue().equals(transportComponent)) {
                    return transportEntry.getKey();
                }
            }
            return null;
        }
    }

    /**
     * Returns a {@link TransportClient} for {@param transportName} or {@code null} if not found.
     *
     * @param transportName The name of the transport as returned by {@link BackupTransport#name()}.
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
     *     details.
     * @return A {@link TransportClient} or null if not found.
     */
    @Nullable
    public TransportClient getTransportClient(String transportName, String caller) {
        ComponentName transportComponent = mTransportsByName.get(transportName);
        if (transportComponent == null) {
            Slog.w(TAG, "Transport " + transportName + " not registered");
            return null;
        }
        return mTransportClientManager.getTransportClient(transportComponent, caller);
    }

    /**
     * Returns a {@link TransportClient} for the current transport or null if not found.
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
     *     details.
     * @return A {@link TransportClient} or null if not found.
     */
    @Nullable
    public TransportClient getCurrentTransportClient(String caller) {
        return getTransportClient(mCurrentTransportName, caller);
    }

    /**
     * Disposes of the {@link TransportClient}.
     *
     * @param transportClient The {@link TransportClient} to be disposed of.
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
     *     details.
     */
    public void disposeOfTransportClient(TransportClient transportClient, String caller) {
        mTransportClientManager.disposeOfTransportClient(transportClient, caller);
    }

    String[] getBoundTransportNames() {
    String[] getBoundTransportNames() {
        synchronized (mTransportLock) {
        synchronized (mTransportLock) {
            return mBoundTransports.keySet().toArray(new String[mBoundTransports.size()]);
            return mBoundTransports.keySet().toArray(new String[mBoundTransports.size()]);
@@ -374,6 +443,7 @@ public class TransportManager {
                    String componentShortString = component.flattenToShortString().intern();
                    String componentShortString = component.flattenToShortString().intern();
                    if (success) {
                    if (success) {
                        Slog.d(TAG, "Bound to transport: " + componentShortString);
                        Slog.d(TAG, "Bound to transport: " + componentShortString);
                        mTransportsByName.put(mTransportName, component);
                        mBoundTransports.put(mTransportName, component);
                        mBoundTransports.put(mTransportName, component);
                        for (TransportReadyCallback listener : mListeners) {
                        for (TransportReadyCallback listener : mListeners) {
                            listener.onSuccess(mTransportName);
                            listener.onSuccess(mTransportName);
@@ -528,7 +598,7 @@ public class TransportManager {
    // These only exists to make it testable with Robolectric, which is not updated to API level 24
    // These only exists to make it testable with Robolectric, which is not updated to API level 24
    // yet.
    // yet.
    // TODO: Get rid of this once Robolectric is updated.
    // TODO: Get rid of this once Robolectric is updated.
    private static UserHandle createSystemUserHandle() {
    public static UserHandle createSystemUserHandle() {
        return new UserHandle(UserHandle.USER_SYSTEM);
        return new UserHandle(UserHandle.USER_SYSTEM);
    }
    }
}
}
+24 −9
Original line number Original line Diff line number Diff line
@@ -38,6 +38,8 @@ import com.android.server.EventLogTags;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.DataChangedJournal;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.RefactoredBackupManagerService;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.TransportManager;
import com.android.server.backup.fullbackup.PerformAdbBackupTask;
import com.android.server.backup.fullbackup.PerformAdbBackupTask;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.fullbackup.PerformFullTransportBackupTask;
import com.android.server.backup.params.AdbBackupParams;
import com.android.server.backup.params.AdbBackupParams;
@@ -51,10 +53,8 @@ import com.android.server.backup.params.RestoreParams;
import com.android.server.backup.restore.PerformAdbRestoreTask;
import com.android.server.backup.restore.PerformAdbRestoreTask;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;


import java.io.File;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Collections;
import java.util.HashSet;


/**
/**
 * Asynchronous backup/restore handler thread.
 * Asynchronous backup/restore handler thread.
@@ -81,7 +81,7 @@ public class BackupHandler extends Handler {
    public static final int MSG_BACKUP_RESTORE_STEP = 20;
    public static final int MSG_BACKUP_RESTORE_STEP = 20;
    public static final int MSG_OP_COMPLETE = 21;
    public static final int MSG_OP_COMPLETE = 21;


    private RefactoredBackupManagerService backupManagerService;
    private final RefactoredBackupManagerService backupManagerService;


    public BackupHandler(
    public BackupHandler(
            RefactoredBackupManagerService backupManagerService, Looper looper) {
            RefactoredBackupManagerService backupManagerService, Looper looper) {
@@ -91,13 +91,23 @@ public class BackupHandler extends Handler {


    public void handleMessage(Message msg) {
    public void handleMessage(Message msg) {


        TransportManager transportManager = backupManagerService.getTransportManager();
        switch (msg.what) {
        switch (msg.what) {
            case MSG_RUN_BACKUP: {
            case MSG_RUN_BACKUP: {
                backupManagerService.setLastBackupPass(System.currentTimeMillis());
                backupManagerService.setLastBackupPass(System.currentTimeMillis());


                String callerLogString = "BH/MSG_RUN_BACKUP";
                TransportClient transportClient =
                        transportManager.getCurrentTransportClient(callerLogString);
                IBackupTransport transport =
                IBackupTransport transport =
                        backupManagerService.getTransportManager().getCurrentTransportBinder();
                        transportClient != null
                                ? transportClient.connect(callerLogString)
                                : null;
                if (transport == null) {
                if (transport == null) {
                    if (transportClient != null) {
                        transportManager
                                .disposeOfTransportClient(transportClient, callerLogString);
                    }
                    Slog.v(TAG, "Backup requested but no transport available");
                    Slog.v(TAG, "Backup requested but no transport available");
                    synchronized (backupManagerService.getQueueLock()) {
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.setBackupRunning(false);
                        backupManagerService.setBackupRunning(false);
@@ -138,9 +148,13 @@ public class BackupHandler extends Handler {
                    // Spin up a backup state sequence and set it running
                    // Spin up a backup state sequence and set it running
                    try {
                    try {
                        String dirName = transport.transportDirName();
                        String dirName = transport.transportDirName();
                        OnTaskFinishedListener listener =
                                caller ->
                                        transportManager
                                                .disposeOfTransportClient(transportClient, caller);
                        PerformBackupTask pbt = new PerformBackupTask(
                        PerformBackupTask pbt = new PerformBackupTask(
                                backupManagerService, transport, dirName, queue,
                                backupManagerService, transportClient, dirName, queue,
                                oldJournal, null, null, Collections.<String>emptyList(), false,
                                oldJournal, null, null, listener, Collections.emptyList(), false,
                                false /* nonIncremental */);
                                false /* nonIncremental */);
                        Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                        Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                        sendMessage(pbtMessage);
                        sendMessage(pbtMessage);
@@ -157,6 +171,7 @@ public class BackupHandler extends Handler {
                }
                }


                if (!staged) {
                if (!staged) {
                    transportManager.disposeOfTransportClient(transportClient, callerLogString);
                    // if we didn't actually hand off the wakelock, rewind until next time
                    // if we didn't actually hand off the wakelock, rewind until next time
                    synchronized (backupManagerService.getQueueLock()) {
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.setBackupRunning(false);
                        backupManagerService.setBackupRunning(false);
@@ -382,9 +397,9 @@ public class BackupHandler extends Handler {


                PerformBackupTask pbt = new PerformBackupTask(
                PerformBackupTask pbt = new PerformBackupTask(
                        backupManagerService,
                        backupManagerService,
                        params.transport, params.dirName,
                        params.transportClient, params.dirName,
                        kvQueue, null, params.observer, params.monitor, params.fullPackages, true,
                        kvQueue, null, params.observer, params.monitor, params.listener,
                        params.nonIncrementalBackup);
                        params.fullPackages, true, params.nonIncrementalBackup);
                Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                sendMessage(pbtMessage);
                sendMessage(pbtMessage);
                break;
                break;
+34 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2017 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.server.backup.internal;

import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportConnectionListener;

/** Listener to be called when a task finishes, successfully or not. */
public interface OnTaskFinishedListener {
    OnTaskFinishedListener NOP = caller -> {};

    /**
     * Called when a task finishes, successfully or not.
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more
     *     details.
     */
    void onFinished(String caller);
}
+39 −21

File changed.

Preview size limit exceeded, changes collapsed.

Loading