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

Commit afd9776c authored by Ruslan Tkhakokhov's avatar Ruslan Tkhakokhov Committed by Android (Google) Code Review
Browse files

Merge "Wrap IBackupTransport usages with BackupTransportClient"

parents 8f3255ae 622b9681
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.Preconditions;
import com.android.server.backup.transport.BackupTransportClient;
import com.android.server.backup.transport.OnTransportRegisteredListener;
import com.android.server.backup.transport.TransportConnection;
import com.android.server.backup.transport.TransportConnectionManager;
@@ -641,7 +642,7 @@ public class TransportManager {
        TransportConnection transportConnection =
                mTransportConnectionManager.getTransportClient(
                        transportComponent, extras, callerLogString);
        final IBackupTransport transport;
        final BackupTransportClient transport;
        try {
            transport = transportConnection.connectOrThrow(callerLogString);
        } catch (TransportNotAvailableException e) {
@@ -653,10 +654,6 @@ public class TransportManager {

        int result;
        try {
            // This is a temporary fix to allow blocking calls.
            // TODO: b/147702043. Redesign IBackupTransport so as to make the calls non-blocking.
            Binder.allowBlocking(transport.asBinder());

            String transportName = transport.name();
            String transportDirName = transport.transportDirName();
            registerTransport(transportComponent, transport);
@@ -674,8 +671,8 @@ public class TransportManager {
    }

    /** If {@link RemoteException} is thrown the transport is guaranteed to not be registered. */
    private void registerTransport(ComponentName transportComponent, IBackupTransport transport)
            throws RemoteException {
    private void registerTransport(ComponentName transportComponent,
            BackupTransportClient transport) throws RemoteException {
        checkCanUseTransport();

        TransportDescription description =
+5 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.Binder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;

@@ -35,6 +36,10 @@ public class BackupTransportClient {

    BackupTransportClient(IBackupTransport transportBinder) {
        mTransportBinder = transportBinder;

        // This is a temporary fix to allow blocking calls.
        // TODO: b/147702043. Redesign IBackupTransport so as to make the calls non-blocking.
        Binder.allowBlocking(mTransportBinder.asBinder());
    }

    /**
+32 −28
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * A {@link TransportConnection} manages the connection to an {@link IBackupTransport} service,
 * A {@link TransportConnection} manages the connection to a {@link BackupTransportClient},
 * obtained via the {@param bindIntent} parameter provided in the constructor. A
 * {@link TransportConnection} is responsible for only one connection to the transport service,
 * not more.
@@ -67,9 +67,9 @@ import java.util.concurrent.ExecutionException;
 * <p>After retrieved using {@link TransportManager#getTransportClient(String, String)}, you can
 * call either {@link #connect(String)}, if you can block your thread, or {@link
 * #connectAsync(TransportConnectionListener, String)}, otherwise, to obtain a {@link
 * IBackupTransport} instance. It's meant to be passed around as a token to a connected transport.
 * When the connection is not needed anymore you should call {@link #unbind(String)} or indirectly
 * via {@link TransportManager#disposeOfTransportClient(TransportConnection, String)}.
 * BackupTransportClient} instance. It's meant to be passed around as a token to a connected
 * transport. When the connection is not needed anymore you should call {@link #unbind(String)} or
 * indirectly via {@link TransportManager#disposeOfTransportClient(TransportConnection, String)}.
 *
 * <p>DO NOT forget to unbind otherwise there will be dangling connections floating around.
 *
@@ -106,7 +106,7 @@ public class TransportConnection {
    private int mState = State.IDLE;

    @GuardedBy("mStateLock")
    private volatile IBackupTransport mTransport;
    private volatile BackupTransportClient mTransport;

    TransportConnection(
            @UserIdInt int userId,
@@ -174,10 +174,12 @@ public class TransportConnection {
     * trigger another one, just piggyback on the original request.
     *
     * <p>It's guaranteed that you are going to get a call back to {@param listener} after this
     * call. However, the {@param IBackupTransport} parameter, the transport binder, is not
     * guaranteed to be non-null, or if it's non-null it's not guaranteed to be usable - i.e. it can
     * throw {@link DeadObjectException}s on method calls. You should check for both in your code.
     * The reasons for a null transport binder are:
     * call. However, the {@link BackupTransportClient} parameter in
     * {@link TransportConnectionListener#onTransportConnectionResult(BackupTransportClient,
     * TransportConnection)}, the transport client, is not guaranteed to be non-null, or if it's
     * non-null it's not guaranteed to be usable - i.e. it can throw {@link DeadObjectException}s
     * on method calls. You should check for both in your code. The reasons for a null transport
     * client are:
     *
     * <ul>
     *   <li>Some code called {@link #unbind(String)} before you got a callback.
@@ -193,7 +195,7 @@ public class TransportConnection {
     * For unusable transport binders check {@link DeadObjectException}.
     *
     * @param listener The listener that will be called with the (possibly null or unusable) {@link
     *     IBackupTransport} instance and this {@link TransportConnection} object.
     *     BackupTransportClient} instance and this {@link TransportConnection} object.
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. This
     *     should be a human-readable short string that is easily identifiable in the logs. Ideally
     *     TAG.methodName(), where TAG is the one used in logcat. In cases where this is is not very
@@ -293,8 +295,8 @@ public class TransportConnection {
     *
     * <p>Synchronous version of {@link #connectAsync(TransportConnectionListener, String)}. The
     * same observations about state are valid here. Also, what was said about the {@link
     * IBackupTransport} parameter of {@link TransportConnectionListener} now apply to the return
     * value of this method.
     * BackupTransportClient} parameter of {@link TransportConnectionListener} now apply to the
     * return value of this method.
     *
     * <p>This is a potentially blocking operation, so be sure to call this carefully on the correct
     * threads. You can't call this from the process main-thread (it throws an exception if you do
@@ -305,18 +307,18 @@ public class TransportConnection {
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     * @return A {@link IBackupTransport} transport binder instance or null. If it's non-null it can
     *     still be unusable - throws {@link DeadObjectException} on method calls
     * @return A {@link BackupTransportClient} transport client instance or null. If it's non-null
     *     it can still be unusable - throws {@link DeadObjectException} on method calls
     */
    @WorkerThread
    @Nullable
    public IBackupTransport connect(String caller) {
    public BackupTransportClient connect(String caller) {
        // If called on the main-thread this could deadlock waiting because calls to
        // ServiceConnection are on the main-thread as well
        Preconditions.checkState(
                !Looper.getMainLooper().isCurrentThread(), "Can't call connect() on main thread");

        IBackupTransport transport = mTransport;
        BackupTransportClient transport = mTransport;
        if (transport != null) {
            log(Priority.DEBUG, caller, "Sync connect: reusing transport");
            return transport;
@@ -330,7 +332,7 @@ public class TransportConnection {
            }
        }

        CompletableFuture<IBackupTransport> transportFuture = new CompletableFuture<>();
        CompletableFuture<BackupTransportClient> transportFuture = new CompletableFuture<>();
        TransportConnectionListener requestListener =
                (requestedTransport, transportClient) ->
                        transportFuture.complete(requestedTransport);
@@ -359,13 +361,14 @@ public class TransportConnection {
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     * @return A {@link IBackupTransport} transport binder instance.
     * @return A {@link BackupTransportClient} transport binder instance.
     * @see #connect(String)
     * @throws TransportNotAvailableException if connection attempt fails.
     */
    @WorkerThread
    public IBackupTransport connectOrThrow(String caller) throws TransportNotAvailableException {
        IBackupTransport transport = connect(caller);
    public BackupTransportClient connectOrThrow(String caller)
            throws TransportNotAvailableException {
        BackupTransportClient transport = connect(caller);
        if (transport == null) {
            log(Priority.ERROR, caller, "Transport connection failed");
            throw new TransportNotAvailableException();
@@ -379,12 +382,12 @@ public class TransportConnection {
     *
     * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check
     *     {@link #connectAsync(TransportConnectionListener, String)} for more details.
     * @return A {@link IBackupTransport} transport binder instance.
     * @return A {@link BackupTransportClient} transport client instance.
     * @throws TransportNotAvailableException if not connected.
     */
    public IBackupTransport getConnectedTransport(String caller)
    public BackupTransportClient getConnectedTransport(String caller)
            throws TransportNotAvailableException {
        IBackupTransport transport = mTransport;
        BackupTransportClient transport = mTransport;
        if (transport == null) {
            log(Priority.ERROR, caller, "Transport not connected");
            throw new TransportNotAvailableException();
@@ -425,7 +428,8 @@ public class TransportConnection {
    }

    private void onServiceConnected(IBinder binder) {
        IBackupTransport transport = IBackupTransport.Stub.asInterface(binder);
        IBackupTransport transportBinder = IBackupTransport.Stub.asInterface(binder);
        BackupTransportClient transport = new BackupTransportClient(transportBinder);
        synchronized (mStateLock) {
            checkStateIntegrityLocked();

@@ -492,15 +496,15 @@ public class TransportConnection {

    private void notifyListener(
            TransportConnectionListener listener,
            @Nullable IBackupTransport transport,
            @Nullable BackupTransportClient transport,
            String caller) {
        String transportString = (transport != null) ? "IBackupTransport" : "null";
        String transportString = (transport != null) ? "BackupTransportClient" : "null";
        log(Priority.INFO, "Notifying [" + caller + "] transport = " + transportString);
        mListenerHandler.post(() -> listener.onTransportConnectionResult(transport, this));
    }

    @GuardedBy("mStateLock")
    private void notifyListenersAndClearLocked(@Nullable IBackupTransport transport) {
    private void notifyListenersAndClearLocked(@Nullable BackupTransportClient transport) {
        for (Map.Entry<TransportConnectionListener, String> entry : mListeners.entrySet()) {
            TransportConnectionListener listener = entry.getKey();
            String caller = entry.getValue();
@@ -510,7 +514,7 @@ public class TransportConnection {
    }

    @GuardedBy("mStateLock")
    private void setStateLocked(@State int state, @Nullable IBackupTransport transport) {
    private void setStateLocked(@State int state, @Nullable BackupTransportClient transport) {
        log(Priority.VERBOSE, "State: " + stateToString(mState) + " => " + stateToString(state));
        onStateTransition(mState, state);
        mState = state;
+6 −5
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@ package com.android.server.backup.transport;

import android.annotation.Nullable;

import com.android.internal.backup.IBackupTransport;
import com.android.server.backup.transport.BackupTransportClient;

/**
 * Listener to be called by {@link TransportConnection#connectAsync(TransportConnectionListener,
@@ -26,13 +26,14 @@ import com.android.internal.backup.IBackupTransport;
 */
public interface TransportConnectionListener {
    /**
     * Called when {@link TransportConnection} has a transport binder available or that it decided
     * Called when {@link TransportConnection} has a transport client available or that it decided
     * it couldn't obtain one, in which case {@param transport} is null.
     *
     * @param transport A {@link IBackupTransport} transport binder or null.
     * @param transportClient A {@link BackupTransportClient} transport or null.
     * @param transportConnection The {@link TransportConnection} used to retrieve this transport
     *                            binder.
     *                            client.
     */
    void onTransportConnectionResult(
            @Nullable IBackupTransport transport, TransportConnection transportConnection);
            @Nullable BackupTransportClient transportClient,
            TransportConnection transportConnection);
}
+4 −3
Original line number Diff line number Diff line
@@ -103,7 +103,6 @@ import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.util.Preconditions;
import com.android.server.AppWidgetBackupBridge;
import com.android.server.EventLogTags;
@@ -127,6 +126,7 @@ import com.android.server.backup.params.ClearRetryParams;
import com.android.server.backup.params.RestoreParams;
import com.android.server.backup.restore.ActiveRestoreSession;
import com.android.server.backup.restore.PerformUnifiedRestoreTask;
import com.android.server.backup.transport.BackupTransportClient;
import com.android.server.backup.transport.TransportConnection;
import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.backup.transport.TransportNotRegisteredException;
@@ -3719,7 +3719,8 @@ public class UserBackupManagerService {
                mTransportManager.getTransportClient(newTransportName, callerLogString);
        if (transportConnection != null) {
            try {
                IBackupTransport transport = transportConnection.connectOrThrow(callerLogString);
                BackupTransportClient transport = transportConnection.connectOrThrow(
                        callerLogString);
                mCurrentToken = transport.getCurrentRestoreSet();
            } catch (Exception e) {
                // Oops.  We can't know the current dataset token, so reset and figure it out
@@ -4371,7 +4372,7 @@ public class UserBackupManagerService {

        final long oldCallingId = Binder.clearCallingIdentity();
        try {
            IBackupTransport transport = transportConnection.connectOrThrow(
            BackupTransportClient transport = transportConnection.connectOrThrow(
                    /* caller */ "BMS.getOperationTypeFromTransport");
            if ((transport.getTransportFlags() & BackupAgent.FLAG_DEVICE_TO_DEVICE_TRANSFER) != 0) {
                return OperationType.MIGRATION;
Loading