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

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

Merge "Binding on-demand #6: Transport attributes usage"

parents 1beb2684 7f14edea
Loading
Loading
Loading
Loading
+86 −124
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import static com.android.server.backup.internal.BackupHandler.MSG_REQUEST_BACKU
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_SESSION_TIMEOUT;
import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_CLEAR;
import static com.android.server.backup.internal.BackupHandler.MSG_RETRY_INIT;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_BACKUP;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_ADB_RESTORE;
import static com.android.server.backup.internal.BackupHandler.MSG_RUN_CLEAR;
@@ -120,6 +119,7 @@ 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.TransportClient;
import com.android.server.backup.transport.TransportNotRegisteredException;
import com.android.server.backup.utils.AppBackupUtils;
import com.android.server.backup.utils.BackupManagerMonitorUtils;
import com.android.server.backup.utils.BackupObserverUtils;
@@ -1083,19 +1083,18 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
        return mBackupPasswordManager.backupPasswordMatches(currentPw);
    }

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

        try {
            IBackupTransport transport = mTransportManager.getTransportBinder(transportName);
            if (transport != null) {
                String transportDirName = transport.transportDirName();
        File stateDir = new File(mBaseStateDir, transportDirName);
        File initPendingFile = new File(stateDir, INIT_SENTINEL_FILE_NAME);

@@ -1114,26 +1113,6 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
            initPendingFile.delete();
            mPendingInits.remove(transportName);
        }
                return; // done; don't fall through to the error case
            }
        } catch (Exception e) {
            // transport threw when asked its name; fall through to the lookup-failed case
            Slog.e(TAG, "Transport " + transportName + " failed to report name: "
                    + e.getMessage());
        }

        // The named transport doesn't exist or threw.  This operation is
        // important, so we record the need for a an init and post a message
        // to retry the init later.
        if (isPending) {
            mPendingInits.add(transportName);
            mBackupHandler.sendMessageDelayed(
                    mBackupHandler.obtainMessage(MSG_RETRY_INIT,
                            (isPending ? 1 : 0),
                            0,
                            transportName),
                    TRANSPORT_RETRY_INTERVAL);
        }
    }

    // Reset all of our bookkeeping, in response to having been told that
@@ -1614,27 +1593,9 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
            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();
        if (transportClient == null || transport == null) {
            if (transportClient != null) {
                mTransportManager.disposeOfTransportClient(transportClient, "BMS.requestBackup()");
            }
        if (transportClient == null) {
            BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
            monitor = BackupManagerMonitorUtils.monitorEvent(monitor,
                    BackupManagerMonitor.LOG_EVENT_ID_TRANSPORT_IS_NULL,
@@ -1679,15 +1640,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
                    + " k/v backups");
        }

        String dirName;
        try {
            dirName = transport.transportDirName();
        } catch (Exception e) {
            Slog.e(TAG, "Transport unavailable while attempting backup: " + e.getMessage());
            BackupObserverUtils.sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
            return BackupManager.ERROR_TRANSPORT_ABORTED;
        }

        String dirName = transportClient.getTransportDirName();
        boolean nonIncrementalBackup = (flags & BackupManager.FLAG_NON_INCREMENTAL_BACKUP) != 0;

        Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP);
@@ -1998,16 +1951,17 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
        writeFullBackupScheduleAsync();
    }

    private boolean fullBackupAllowable(IBackupTransport transport) {
        if (transport == null) {
            Slog.w(TAG, "Transport not present; full data backup not performed");
    private boolean fullBackupAllowable(String transportName) {
        if (!mTransportManager.isTransportRegistered(transportName)) {
            Slog.w(TAG, "Transport not registered; full data backup not performed");
            return false;
        }

        // Don't proceed unless we have already established package metadata
        // for the current dataset via a key/value backup pass.
        try {
            File stateDir = new File(mBaseStateDir, transport.transportDirName());
            String transportDirName = mTransportManager.getTransportDirName(transportName);
            File stateDir = new File(mBaseStateDir, transportDirName);
            File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL);
            if (pmState.length() <= 0) {
                if (DEBUG) {
@@ -2097,7 +2051,8 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter

                headBusy = false;

                if (!fullBackupAllowable(mTransportManager.getCurrentTransportBinder())) {
                String transportName = mTransportManager.getCurrentTransportName();
                if (!fullBackupAllowable(transportName)) {
                    if (MORE_DEBUG) {
                        Slog.i(TAG, "Preconditions not met; not running full backup");
                    }
@@ -2545,7 +2500,8 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
            throw new IllegalStateException("Restore supported only for the device owner");
        }

        if (!fullBackupAllowable(mTransportManager.getCurrentTransportBinder())) {
        String transportName = mTransportManager.getCurrentTransportName();
        if (!fullBackupAllowable(transportName)) {
            Slog.i(TAG, "Full backup not currently possible -- key/value backup not yet run?");
        } else {
            if (DEBUG) {
@@ -2826,10 +2782,30 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
                    if (wasEnabled && mProvisioned) {
                        // NOTE: we currently flush every registered transport, not just
                        // the currently-active one.
                        String[] allTransports = mTransportManager.getBoundTransportNames();
                        List<String> transportNames = new ArrayList<>();
                        List<String> transportDirNames = new ArrayList<>();
                        mTransportManager.forEachRegisteredTransport(
                                name -> {
                                    final String dirName;
                                    try {
                                        dirName =
                                                mTransportManager
                                                        .getTransportDirName(name);
                                    } catch (TransportNotRegisteredException e) {
                                        // Should never happen
                                        Slog.e(TAG, "Unexpected unregistered transport", e);
                                        return;
                                    }
                                    transportNames.add(name);
                                    transportDirNames.add(dirName);
                                });

                        // build the set of transports for which we are posting an init
                        for (String transport : allTransports) {
                            recordInitPendingLocked(true, transport);
                        for (int i = 0; i < transportNames.size(); i++) {
                            recordInitPendingLocked(
                                    true,
                                    transportNames.get(i),
                                    transportDirNames.get(i));
                        }
                        mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),
                                mRunInitIntent);
@@ -2993,7 +2969,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter

        final long oldId = Binder.clearCallingIdentity();
        try {
            mTransportManager.describeTransport(
            mTransportManager.updateTransportAttributes(
                    transportComponent,
                    name,
                    configurationIntent,
@@ -3093,24 +3069,17 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
    public Intent getConfigurationIntent(String transportName) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                "getConfigurationIntent");

        final IBackupTransport transport = mTransportManager.getTransportBinder(transportName);
        if (transport != null) {
        try {
                final Intent intent = transport.configurationIntent();
            Intent intent = mTransportManager.getTransportConfigurationIntent(transportName);
            if (MORE_DEBUG) {
                    Slog.d(TAG, "getConfigurationIntent() returning config intent "
                            + intent);
                Slog.d(TAG, "getConfigurationIntent() returning intent " + intent);
            }
            return intent;
            } catch (Exception e) {
                /* fall through to return null */
        } catch (TransportNotRegisteredException e) {
            Slog.e(TAG, "Unable to get configuration intent from transport: " + e.getMessage());
            }
        }

            return null;
        }
    }

    // Supply the configuration summary string for the given transport.  If the name is
    // not one of the available transports, or if the transport does not supply any
@@ -3143,23 +3112,17 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                "getDataManagementIntent");

        final IBackupTransport transport = mTransportManager.getTransportBinder(transportName);
        if (transport != null) {
        try {
                final Intent intent = transport.dataManagementIntent();
            Intent intent = mTransportManager.getTransportDataManagementIntent(transportName);
            if (MORE_DEBUG) {
                    Slog.d(TAG, "getDataManagementIntent() returning intent "
                            + intent);
                Slog.d(TAG, "getDataManagementIntent() returning intent " + intent);
            }
            return intent;
            } catch (Exception e) {
                /* fall through to return null */
        } catch (TransportNotRegisteredException e) {
            Slog.e(TAG, "Unable to get management intent from transport: " + e.getMessage());
            }
        }

            return null;
        }
    }

    // Supply the menu label for affordances that fire the manage-data intent
    // for the given transport.
@@ -3168,20 +3131,17 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                "getDataManagementLabel");

        final IBackupTransport transport = mTransportManager.getTransportBinder(transportName);
        if (transport != null) {
        try {
                final String text = transport.dataManagementLabel();
                if (MORE_DEBUG) Slog.d(TAG, "getDataManagementLabel() returning " + text);
                return text;
            } catch (Exception e) {
                /* fall through to return null */
                Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage());
            }
            String label = mTransportManager.getTransportDataManagementLabel(transportName);
            if (MORE_DEBUG) {
                Slog.d(TAG, "getDataManagementLabel() returning " + label);
            }

            return label;
        } catch (TransportNotRegisteredException e) {
            Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage());
            return null;
        }
    }

    // Callback: a requested backup agent has been instantiated.  This should only
    // be called from the Activity Manager.
@@ -3497,14 +3457,16 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter
            pw.println("Available transports:");
            final String[] transports = listAllTransports();
            if (transports != null) {
                for (String t : listAllTransports()) {
                for (String t : transports) {
                    pw.println((t.equals(mTransportManager.getCurrentTransportName()) ? "  * "
                            : "    ") + t);
                    try {
                        IBackupTransport transport = mTransportManager.getTransportBinder(t);
                        File dir = new File(mBaseStateDir, transport.transportDirName());
                        File dir = new File(mBaseStateDir,
                                mTransportManager.getTransportDirName(t));
                        pw.println("       destination: " + transport.currentDestinationString());
                        pw.println("       intent: " + transport.configurationIntent());
                        pw.println("       intent: "
                                + mTransportManager.getTransportConfigurationIntent(t));
                        for (File f : dir.listFiles()) {
                            pw.println(
                                    "       " + f.getName() + " - " + f.length() + " state bytes");
+83 −4
Original line number Diff line number Diff line
@@ -49,12 +49,14 @@ 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 com.android.server.backup.transport.TransportNotRegisteredException;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
@@ -236,6 +238,72 @@ public class TransportManager {
        return getTransportBinder(mCurrentTransportName);
    }

    /**
     * Retrieve the configuration intent of {@code transportName}.
     * @throws TransportNotRegisteredException if the transport is not registered.
     */
    @Nullable
    public Intent getTransportConfigurationIntent(String transportName)
            throws TransportNotRegisteredException {
        synchronized (mTransportLock) {
            return getRegisteredTransportDescriptionOrThrowLocked(transportName)
                    .configurationIntent;
        }
    }

    /**
     * Retrieve the data management intent of {@code transportName}.
     * @throws TransportNotRegisteredException if the transport is not registered.
     */
    @Nullable
    public Intent getTransportDataManagementIntent(String transportName)
            throws TransportNotRegisteredException {
        synchronized (mTransportLock) {
            return getRegisteredTransportDescriptionOrThrowLocked(transportName)
                    .dataManagementIntent;
        }
    }

    /**
     * Retrieve the data management label of {@code transportName}.
     * @throws TransportNotRegisteredException if the transport is not registered.
     */
    @Nullable
    public String getTransportDataManagementLabel(String transportName)
            throws TransportNotRegisteredException {
        synchronized (mTransportLock) {
            return getRegisteredTransportDescriptionOrThrowLocked(transportName)
                    .dataManagementLabel;
        }
    }

    /**
     * Retrieve the transport dir name of {@code transportName}.
     * @throws TransportNotRegisteredException if the transport is not registered.
     */
    public String getTransportDirName(String transportName)
            throws TransportNotRegisteredException {
        synchronized (mTransportLock) {
            return getRegisteredTransportDescriptionOrThrowLocked(transportName)
                    .transportDirName;
        }
    }

    /**
     * Execute {@code transportConsumer} for each registered transport passing the transport name.
     * This is called with an internal lock held, ensuring that the transport will remain registered
     * while {@code transportConsumer} is being executed. Don't do heavy operations in
     * {@code transportConsumer}.
     */
    public void forEachRegisteredTransport(Consumer<String> transportConsumer) {
        synchronized (mTransportLock) {
            for (TransportDescription transportDescription
                    : mRegisteredTransportsDescriptionMap.values()) {
                transportConsumer.accept(transportDescription.name);
            }
        }
    }

    public String getTransportName(IBackupTransport binder) {
        synchronized (mTransportLock) {
            for (TransportConnection conn : mValidTransports.values()) {
@@ -280,6 +348,17 @@ public class TransportManager {
        return (entry == null) ? null : entry.getValue();
    }

    @GuardedBy("mTransportLock")
    private TransportDescription getRegisteredTransportDescriptionOrThrowLocked(
            String transportName) throws TransportNotRegisteredException {
        TransportDescription description = getRegisteredTransportDescriptionLocked(transportName);
        if (description == null) {
            throw new TransportNotRegisteredException(transportName);
        }
        return description;
    }


    @GuardedBy("mTransportLock")
    @Nullable
    private Map.Entry<ComponentName, TransportDescription> getRegisteredTransportEntryLocked(
@@ -385,13 +464,13 @@ public class TransportManager {
     * Updates given values for the transport already registered and identified with
     * {@param transportComponent}. If the transport is not registered it will log and return.
     */
    public void describeTransport(
    public void updateTransportAttributes(
            ComponentName transportComponent,
            String name,
            @Nullable Intent configurationIntent,
            String currentDestinationString,
            @Nullable Intent dataManagementIntent,
            String dataManagementLabel) {
            @Nullable String dataManagementLabel) {
        synchronized (mTransportLock) {
            TransportDescription description =
                    mRegisteredTransportsDescriptionMap.get(transportComponent);
@@ -766,7 +845,7 @@ public class TransportManager {
        @Nullable private Intent configurationIntent;
        private String currentDestinationString;
        @Nullable private Intent dataManagementIntent;
        private String dataManagementLabel;
        @Nullable private String dataManagementLabel;

        private TransportDescription(
                String name,
@@ -774,7 +853,7 @@ public class TransportManager {
                @Nullable Intent configurationIntent,
                String currentDestinationString,
                @Nullable Intent dataManagementIntent,
                String dataManagementLabel) {
                @Nullable String dataManagementLabel) {
            this.name = name;
            this.transportDirName = transportDirName;
            this.configurationIntent = configurationIntent;
+0 −10
Original line number Diff line number Diff line
@@ -293,16 +293,6 @@ public class BackupHandler extends Handler {
                break;
            }

            case MSG_RETRY_INIT: {
                synchronized (backupManagerService.getQueueLock()) {
                    backupManagerService.recordInitPendingLocked(msg.arg1 != 0, (String) msg.obj);
                    backupManagerService.getAlarmManager().set(AlarmManager.RTC_WAKEUP,
                            System.currentTimeMillis(),
                            backupManagerService.getRunInitIntent());
                }
                break;
            }

            case MSG_RUN_GET_RESTORE_SETS: {
                // Like other async operations, this is entered with the wakelock held
                RestoreSet[] sets = null;
+4 −2
Original line number Diff line number Diff line
@@ -98,7 +98,8 @@ public class PerformInitializeTask implements Runnable {
                                    transportDirName));
                    EventLog.writeEvent(EventLogTags.BACKUP_SUCCESS, 0, millis);
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.recordInitPendingLocked(false, transportName);
                        backupManagerService.recordInitPendingLocked(
                                false, transportName, transportDirName);
                    }
                    notifyResult(transportName, BackupTransport.TRANSPORT_OK);
                } else {
@@ -107,7 +108,8 @@ public class PerformInitializeTask implements Runnable {
                    Slog.e(TAG, "Transport error in initializeDevice()");
                    EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
                    synchronized (backupManagerService.getQueueLock()) {
                        backupManagerService.recordInitPendingLocked(true, transportName);
                        backupManagerService.recordInitPendingLocked(
                                true, transportName, transportDirName);
                    }
                    notifyResult(transportName, status);
                    result = status;
+35 −0
Original line number 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.transport;

import android.util.AndroidException;

import com.android.server.backup.TransportManager;

/**
 * Exception thrown when the transport is not registered.
 *
 * @see TransportManager#getTransportDirName(String)
 * @see TransportManager#getTransportConfigurationIntent(String)
 * @see TransportManager#getTransportDataManagementIntent(String)
 * @see TransportManager#getTransportDataManagementLabel(String)
 */
public class TransportNotRegisteredException extends AndroidException {
    public TransportNotRegisteredException(String transportName) {
        super("Transport " + transportName + " not registered");
    }
}
Loading