/*
 * Copyright (C) 2014 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;

import static java.util.Collections.emptySet;

import android.Manifest;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
import android.util.SparseArray;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.backup.utils.RandomAccessFileUtils;

import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Definition of the system service that performs backup/restore operations.
 *
 * <p>This class is responsible for handling user-aware operations and acts as a delegator, routing
 * incoming calls to the appropriate per-user {@link UserBackupManagerService} to handle the
 * corresponding backup/restore operation.
 *
 * <p>It also determines whether the backup service is available. It can be disabled in the
 * following two ways:
 *
 * <ul>
 *  <li>Temporary - call {@link #setBackupServiceActive(int, boolean)}, or
 *  <li>Permanent - set the system property {@link #BACKUP_DISABLE_PROPERTY} to true.
 * </ul>
 *
 * Temporary disabling is controlled by {@link #setBackupServiceActive(int, boolean)} through
 * privileged callers (currently {@link DevicePolicyManager}). If called on {@link
 * UserHandle#USER_SYSTEM}, backup is disabled for all users.
 */
public class BackupManagerService extends IBackupManager.Stub {
    public static final String TAG = "BackupManagerService";
    public static final boolean DEBUG = true;
    public static final boolean MORE_DEBUG = false;
    public static final boolean DEBUG_SCHEDULING = true;

    @VisibleForTesting
    static final String DUMP_RUNNING_USERS_MESSAGE = "Backup Manager is running for users:";

    /**
     * Name of file that disables the backup service. If this file exists, then backup is disabled
     * for all users.
     */
    private static final String BACKUP_SUPPRESS_FILENAME = "backup-suppress";

    /**
     * Name of file for non-system users that enables the backup service for the user. Backup is
     * disabled by default in non-system users.
     */
    private static final String BACKUP_ACTIVATED_FILENAME = "backup-activated";

    /**
     * Name of file for non-system users that remembers whether backup was explicitly activated or
     * deactivated with a call to setBackupServiceActive.
     */
    private static final String REMEMBER_ACTIVATED_FILENAME = "backup-remember-activated";

    // Product-level suppression of backup/restore.
    private static final String BACKUP_DISABLE_PROPERTY = "ro.backup.disable";

    private static final String BACKUP_THREAD = "backup";

    static BackupManagerService sInstance;

    static BackupManagerService getInstance() {
        return Objects.requireNonNull(sInstance);
    }

    private final Context mContext;
    private final UserManager mUserManager;

    private final boolean mGlobalDisable;
    // Lock to write backup suppress files.
    // TODD(b/121198006): remove this object and synchronized all methods on "this".
    private final Object mStateLock = new Object();

    private final Handler mHandler;
    private final Set<ComponentName> mTransportWhitelist;

    /** Keeps track of all unlocked users registered with this service. Indexed by user id. */
    private final SparseArray<UserBackupManagerService> mUserServices;

    private final BroadcastReceiver mUserRemovedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
                if (userId > 0) { // for only non system users
                    mHandler.post(() -> onRemovedNonSystemUser(userId));
                }
            }
        }
    };

    public BackupManagerService(Context context) {
        this(context, new SparseArray<>());
    }

    @VisibleForTesting
    BackupManagerService(Context context, SparseArray<UserBackupManagerService> userServices) {
        mContext = context;
        mGlobalDisable = isBackupDisabled();
        HandlerThread handlerThread =
                new HandlerThread(BACKUP_THREAD, Process.THREAD_PRIORITY_BACKGROUND);
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());
        mUserManager = UserManager.get(context);
        mUserServices = userServices;
        Set<ComponentName> transportWhitelist =
                SystemConfig.getInstance().getBackupTransportWhitelist();
        mTransportWhitelist = (transportWhitelist == null) ? emptySet() : transportWhitelist;
        mContext.registerReceiver(
                mUserRemovedReceiver, new IntentFilter(Intent.ACTION_USER_REMOVED));
    }

    // TODO: Remove this when we implement DI by injecting in the construtor.
    @VisibleForTesting
    Handler getBackupHandler() {
        return mHandler;
    }

    protected boolean isBackupDisabled() {
        return SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false);
    }

    protected int binderGetCallingUserId() {
        return Binder.getCallingUserHandle().getIdentifier();
    }

    protected int binderGetCallingUid() {
        return Binder.getCallingUid();
    }

    /** Stored in the system user's directory. */
    protected File getSuppressFileForSystemUser() {
        return new File(UserBackupManagerFiles.getBaseStateDir(UserHandle.USER_SYSTEM),
                BACKUP_SUPPRESS_FILENAME);
    }

    /** Stored in the system user's directory and the file is indexed by the user it refers to. */
    protected File getRememberActivatedFileForNonSystemUser(int userId) {
        return UserBackupManagerFiles.getStateFileInSystemDir(REMEMBER_ACTIVATED_FILENAME, userId);
    }

    /** Stored in the system user's directory and the file is indexed by the user it refers to. */
    protected File getActivatedFileForNonSystemUser(int userId) {
        return UserBackupManagerFiles.getStateFileInSystemDir(BACKUP_ACTIVATED_FILENAME, userId);
    }

    /**
     * Remove backup state for non system {@code userId} when the user is removed from the device.
     * For non system users, backup state is stored in both the user's own dir and the system dir.
     * When the user is removed, the user's own dir gets removed by the OS. This method ensures that
     * the part of the user backup state which is in the system dir also gets removed.
     */
    private void onRemovedNonSystemUser(int userId) {
        Slog.i(TAG, "Removing state for non system user " + userId);
        File dir = UserBackupManagerFiles.getStateDirInSystemDir(userId);
        if (!FileUtils.deleteContentsAndDir(dir)) {
            Slog.w(TAG, "Failed to delete state dir for removed user: " + userId);
        }
    }

    // TODO (b/124359804) move to util method in FileUtils
    private void createFile(File file) throws IOException {
        if (file.exists()) {
            return;
        }

        file.getParentFile().mkdirs();
        if (!file.createNewFile()) {
            Slog.w(TAG, "Failed to create file " + file.getPath());
        }
    }

    // TODO (b/124359804) move to util method in FileUtils
    private void deleteFile(File file) {
        if (!file.exists()) {
            return;
        }

        if (!file.delete()) {
            Slog.w(TAG, "Failed to delete file " + file.getPath());
        }
    }

    /**
     * Deactivates the backup service for user {@code userId}. If this is the system user, it
     * creates a suppress file which disables backup for all users. If this is a non-system user, it
     * only deactivates backup for that user by deleting its activate file.
     */
    @GuardedBy("mStateLock")
    private void deactivateBackupForUserLocked(int userId) throws IOException {
        if (userId == UserHandle.USER_SYSTEM) {
            createFile(getSuppressFileForSystemUser());
        } else {
            deleteFile(getActivatedFileForNonSystemUser(userId));
        }
    }

    /**
     * Enables the backup service for user {@code userId}. If this is the system user, it deletes
     * the suppress file. If this is a non-system user, it creates the user's activate file. Note,
     * deleting the suppress file does not automatically enable backup for non-system users, they
     * need their own activate file in order to participate in the service.
     */
    @GuardedBy("mStateLock")
    private void activateBackupForUserLocked(int userId) throws IOException {
        if (userId == UserHandle.USER_SYSTEM) {
            deleteFile(getSuppressFileForSystemUser());
        } else {
            createFile(getActivatedFileForNonSystemUser(userId));
        }
    }

    /**
     * This method should not perform any I/O (e.g. do not call isBackupActivatedForUser),
     * it's used in multiple places where I/O waits would cause system lock-ups.
     * @param userId User id for which this operation should be performed.
     * @return true if the user is ready for backup and false otherwise.
     */
    @Override
    public boolean isUserReadyForBackup(int userId) {
        return mUserServices.get(UserHandle.USER_SYSTEM) != null
                && mUserServices.get(userId) != null;
    }

    /**
     * Backup is activated for the system user if the suppress file does not exist. Backup is
     * activated for non-system users if the suppress file does not exist AND the user's activated
     * file exists.
     */
    private boolean isBackupActivatedForUser(int userId) {
        if (getSuppressFileForSystemUser().exists()) {
            return false;
        }

        return userId == UserHandle.USER_SYSTEM
                || getActivatedFileForNonSystemUser(userId).exists();
    }

    protected Context getContext() {
        return mContext;
    }

    protected UserManager getUserManager() {
        return mUserManager;
    }

    protected void postToHandler(Runnable runnable) {
        mHandler.post(runnable);
    }

    /**
     * Called from {@link BackupManagerService.Lifecycle} when a user {@code userId} is unlocked.
     * Starts the backup service for this user if backup is active for this user. Offloads work onto
     * the handler thread {@link #mHandlerThread} to keep unlock time low since backup is not
     * essential for device functioning.
     */
    void onUnlockUser(int userId) {
        postToHandler(() -> startServiceForUser(userId));
    }

    /**
     * Starts the backup service for user {@code userId} by creating a new instance of {@link
     * UserBackupManagerService} and registering it with this service.
     */
    @VisibleForTesting
    void startServiceForUser(int userId) {
        // We know that the user is unlocked here because it is called from setBackupServiceActive
        // and unlockUser which have these guarantees. So we can check if the file exists.
        if (mGlobalDisable) {
            Slog.i(TAG, "Backup service not supported");
            return;
        }
        if (!isBackupActivatedForUser(userId)) {
            Slog.i(TAG, "Backup not activated for user " + userId);
            return;
        }
        if (mUserServices.get(userId) != null) {
            Slog.i(TAG, "userId " + userId + " already started, so not starting again");
            return;
        }
        Slog.i(TAG, "Starting service for user: " + userId);
        UserBackupManagerService userBackupManagerService =
                UserBackupManagerService.createAndInitializeService(
                        userId, mContext, this, mTransportWhitelist);
        startServiceForUser(userId, userBackupManagerService);
    }

    /**
     * Starts the backup service for user {@code userId} by registering its instance of {@link
     * UserBackupManagerService} with this service and setting enabled state.
     */
    void startServiceForUser(int userId, UserBackupManagerService userBackupManagerService) {
        mUserServices.put(userId, userBackupManagerService);

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
        userBackupManagerService.initializeBackupEnableState();
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    }

    /** Stops the backup service for user {@code userId} when the user is stopped. */
    @VisibleForTesting
    protected void stopServiceForUser(int userId) {
        UserBackupManagerService userBackupManagerService = mUserServices.removeReturnOld(userId);

        if (userBackupManagerService != null) {
            userBackupManagerService.tearDownService();

            KeyValueBackupJob.cancel(userId, mContext);
            FullBackupJob.cancel(userId, mContext);
        }
    }

    /**
     *  Returns a list of users currently unlocked that have a {@link UserBackupManagerService}
     *  registered.
     *
     *  Warning: Do NOT modify returned object as it's used inside.
     *
     *  TODO: Return a copy or only expose read-only information through other means.
     */
    @VisibleForTesting
    SparseArray<UserBackupManagerService> getUserServices() {
        return mUserServices;
    }

    /**
     * Called from {@link BackupManagerService.Lifecycle} when a user {@code userId} is stopped.
     * Offloads work onto the handler thread {@link #mHandlerThread} to keep stopping time low.
     */
    void onStopUser(int userId) {
        postToHandler(
                () -> {
                    if (!mGlobalDisable) {
                        Slog.i(TAG, "Stopping service for user: " + userId);
                        stopServiceForUser(userId);
                    }
                });
    }

    /** Returns {@link UserBackupManagerService} for user {@code userId}. */
    @Nullable
    public UserBackupManagerService getUserService(int userId) {
        return mUserServices.get(userId);
    }

    /**
     * The system user and managed profiles can only be acted on by callers in the system or root
     * processes. Other users can be acted on by callers who have both android.permission.BACKUP and
     * android.permission.INTERACT_ACROSS_USERS_FULL permissions.
     */
    private void enforcePermissionsOnUser(int userId) throws SecurityException {
        boolean isRestrictedUser =
                userId == UserHandle.USER_SYSTEM
                        || getUserManager().getUserInfo(userId).isManagedProfile();

        if (isRestrictedUser) {
            int caller = binderGetCallingUid();
            if (caller != Process.SYSTEM_UID && caller != Process.ROOT_UID) {
                throw new SecurityException("No permission to configure backup activity");
            }
        } else {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.BACKUP, "No permission to configure backup activity");
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS_FULL,
                    "No permission to configure backup activity");
        }
    }

    /**
     * Only privileged callers should be changing the backup state. Deactivating backup in the
     * system user also deactivates backup in all users. We are not guaranteed that {@code userId}
     * is unlocked at this point yet, so handle both cases.
     */
    public void setBackupServiceActive(int userId, boolean makeActive) {
        enforcePermissionsOnUser(userId);

        // In Q, backup is OFF by default for non-system users. In the future, we will change that
        // to ON unless backup was explicitly deactivated with a (permissioned) call to
        // setBackupServiceActive.
        // Therefore, remember this for use in the future. Basically the default in the future will
        // be: rememberFile.exists() ? rememberFile.value() : ON
        // Note that this has to be done right after the permission checks and before any other
        // action since we need to remember that a permissioned call was made irrespective of
        // whether the call changes the state or not.
        if (userId != UserHandle.USER_SYSTEM) {
            try {
                File rememberFile = getRememberActivatedFileForNonSystemUser(userId);
                createFile(rememberFile);
                RandomAccessFileUtils.writeBoolean(rememberFile, makeActive);
            } catch (IOException e) {
                Slog.e(TAG, "Unable to persist backup service activity", e);
            }
        }

        if (mGlobalDisable) {
            Slog.i(TAG, "Backup service not supported");
            return;
        }

        synchronized (mStateLock) {
            Slog.i(TAG, "Making backup " + (makeActive ? "" : "in") + "active");
            if (makeActive) {
                try {
                    activateBackupForUserLocked(userId);
                } catch (IOException e) {
                    Slog.e(TAG, "Unable to persist backup service activity");
                }

                // If the user is unlocked, we can start the backup service for it. Otherwise we
                // will start the service when the user is unlocked as part of its unlock callback.
                if (getUserManager().isUserUnlocked(userId)) {
                    // Clear calling identity as initialization enforces the system identity but we
                    // can be coming from shell.
                    long oldId = Binder.clearCallingIdentity();
                    try {
                        startServiceForUser(userId);
                    } finally {
                        Binder.restoreCallingIdentity(oldId);
                    }
                }
            } else {
                try {
                    //TODO(b/121198006): what if this throws an exception?
                    deactivateBackupForUserLocked(userId);
                } catch (IOException e) {
                    Slog.e(TAG, "Unable to persist backup service inactivity");
                }
                //TODO(b/121198006): loop through active users that have work profile and
                // stop them as well.
                onStopUser(userId);
            }
        }
    }

    // IBackupManager binder API

    /**
     * Querying activity state of backup service.
     *
     * @param userId The user in which the activity state of backup service is queried.
     * @return true if the service is active.
     */
    @Override
    public boolean isBackupServiceActive(int userId) {
        synchronized (mStateLock) {
            return !mGlobalDisable && isBackupActivatedForUser(userId);
        }
    }

    @Override
    public void dataChangedForUser(int userId, String packageName) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            dataChanged(userId, packageName);
        }
    }

    @Override
    public void dataChanged(String packageName) throws RemoteException {
        dataChangedForUser(binderGetCallingUserId(), packageName);
    }

    /**
     * An app's backup agent calls this method to let the service know that there's new data to
     * backup for their app {@code packageName}. Only used for apps participating in key-value
     * backup.
     */
    public void dataChanged(@UserIdInt int userId, String packageName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "dataChanged()");

        if (userBackupManagerService != null) {
            userBackupManagerService.dataChanged(packageName);
        }
    }

    // ---------------------------------------------
    // TRANSPORT OPERATIONS
    // ---------------------------------------------

    @Override
    public void initializeTransportsForUser(
            int userId, String[] transportNames, IBackupObserver observer) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            initializeTransports(userId, transportNames, observer);
        }
    }

    /** Run an initialize operation for the given transports {@code transportNames}. */
    public void initializeTransports(
            @UserIdInt int userId, String[] transportNames, IBackupObserver observer) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "initializeTransports()");

        if (userBackupManagerService != null) {
            userBackupManagerService.initializeTransports(transportNames, observer);
        }
    }

    @Override
    public void clearBackupDataForUser(int userId, String transportName, String packageName)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            clearBackupData(userId, transportName, packageName);
        }
    }

    /**
     * Clear the given package {@code packageName}'s backup data from the transport {@code
     * transportName}.
     */
    public void clearBackupData(@UserIdInt int userId, String transportName, String packageName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "clearBackupData()");

        if (userBackupManagerService != null) {
            userBackupManagerService.clearBackupData(transportName, packageName);
        }
    }

    @Override
    public void clearBackupData(String transportName, String packageName)
            throws RemoteException {
        clearBackupDataForUser(binderGetCallingUserId(), transportName, packageName);
    }

    @Override
    public void agentConnectedForUser(int userId, String packageName, IBinder agent)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            agentConnected(userId, packageName, agent);
        }
    }

    @Override
    public void agentConnected(String packageName, IBinder agent) throws RemoteException {
        agentConnectedForUser(binderGetCallingUserId(), packageName, agent);
    }

    /**
     * Callback: a requested backup agent has been instantiated. This should only be called from the
     * {@link ActivityManager}.
     */
    public void agentConnected(@UserIdInt int userId, String packageName, IBinder agentBinder) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "agentConnected()");

        if (userBackupManagerService != null) {
            userBackupManagerService.agentConnected(packageName, agentBinder);
        }
    }

    @Override
    public void agentDisconnectedForUser(int userId, String packageName) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            agentDisconnected(userId, packageName);
        }
    }

    @Override
    public void agentDisconnected(String packageName) throws RemoteException {
        agentDisconnectedForUser(binderGetCallingUserId(), packageName);
    }

    /**
     * Callback: a backup agent has failed to come up, or has unexpectedly quit. This should only be
     * called from the {@link ActivityManager}.
     */
    public void agentDisconnected(@UserIdInt int userId, String packageName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "agentDisconnected()");

        if (userBackupManagerService != null) {
            userBackupManagerService.agentDisconnected(packageName);
        }
    }

    @Override
    public void restoreAtInstallForUser(int userId, String packageName, int token)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            restoreAtInstall(userId, packageName, token);
        }
    }

    @Override
    public void restoreAtInstall(String packageName, int token) throws RemoteException {
        restoreAtInstallForUser(binderGetCallingUserId(), packageName, token);
    }

    /**
     * Used to run a restore pass for an application that is being installed. This should only be
     * called from the {@link PackageManager}.
     */
    public void restoreAtInstall(@UserIdInt int userId, String packageName, int token) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "restoreAtInstall()");

        if (userBackupManagerService != null) {
            userBackupManagerService.restoreAtInstall(packageName, token);
        }
    }

    @Override
    public void setBackupEnabledForUser(@UserIdInt int userId, boolean isEnabled)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            setBackupEnabled(userId, isEnabled);
        }
    }

    @Override
    public void setBackupEnabled(boolean isEnabled) throws RemoteException {
        setBackupEnabledForUser(binderGetCallingUserId(), isEnabled);
    }

    /** Enable/disable the backup service. This is user-configurable via backup settings. */
    public void setBackupEnabled(@UserIdInt int userId, boolean enable) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "setBackupEnabled()");

        if (userBackupManagerService != null) {
            userBackupManagerService.setBackupEnabled(enable);
        }
    }

    @Override
    public void setAutoRestoreForUser(int userId, boolean doAutoRestore) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            setAutoRestore(userId, doAutoRestore);
        }
    }

    @Override
    public void setAutoRestore(boolean doAutoRestore) throws RemoteException {
        setAutoRestoreForUser(binderGetCallingUserId(), doAutoRestore);
    }

    /** Enable/disable automatic restore of app data at install time. */
    public void setAutoRestore(@UserIdInt int userId, boolean autoRestore) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "setAutoRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.setAutoRestore(autoRestore);
        }
    }

    @Override
    public boolean isBackupEnabledForUser(@UserIdInt int userId) throws RemoteException {
        return isUserReadyForBackup(userId) && isBackupEnabled(userId);
    }

    @Override
    public boolean isBackupEnabled() throws RemoteException {
        return isBackupEnabledForUser(binderGetCallingUserId());
    }

    /**
     * Return {@code true} if the backup mechanism is currently enabled, else returns {@code false}.
     */
    public boolean isBackupEnabled(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "isBackupEnabled()");

        return userBackupManagerService != null && userBackupManagerService.isBackupEnabled();
    }

    /** Sets the backup password used when running adb backup. */
    @Override
    public boolean setBackupPassword(String currentPassword, String newPassword) {
        int userId = binderGetCallingUserId();
        if (!isUserReadyForBackup(userId)) {
            return false;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        UserHandle.USER_SYSTEM, "setBackupPassword()");

        return userBackupManagerService != null
                && userBackupManagerService.setBackupPassword(currentPassword, newPassword);
    }

    /** Returns {@code true} if adb backup was run with a password, else returns {@code false}. */
    @Override
    public boolean hasBackupPassword() throws RemoteException {
        int userId = binderGetCallingUserId();
        if (!isUserReadyForBackup(userId)) {
            return false;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        UserHandle.USER_SYSTEM, "hasBackupPassword()");

        return userBackupManagerService != null && userBackupManagerService.hasBackupPassword();
    }

    @Override
    public void backupNowForUser(@UserIdInt int userId) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            backupNow(userId);
        }
    }

    @Override
    public void backupNow() throws RemoteException {
        backupNowForUser(binderGetCallingUserId());
    }

    /**
     * Run a backup pass immediately for any key-value backup applications that have declared that
     * they have pending updates.
     */
    public void backupNow(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "backupNow()");

        if (userBackupManagerService != null) {
            userBackupManagerService.backupNow();
        }
    }

    /**
     * Used by 'adb backup' to run a backup pass for packages {@code packageNames} supplied via the
     * command line, writing the resulting data stream to the supplied {@code fd}. This method is
     * synchronous and does not return to the caller until the backup has been completed. It
     * requires on-screen confirmation by the user.
     */
    @Override
    public void adbBackup(
            @UserIdInt int userId,
            ParcelFileDescriptor fd,
            boolean includeApks,
            boolean includeObbs,
            boolean includeShared,
            boolean doWidgets,
            boolean doAllApps,
            boolean includeSystem,
            boolean doCompress,
            boolean doKeyValue,
            String[] packageNames) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "adbBackup()");

        if (userBackupManagerService != null) {
            userBackupManagerService.adbBackup(
                    fd,
                    includeApks,
                    includeObbs,
                    includeShared,
                    doWidgets,
                    doAllApps,
                    includeSystem,
                    doCompress,
                    doKeyValue,
                    packageNames);
        }
    }

    @Override
    public void fullTransportBackupForUser(int userId, String[] packageNames)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            fullTransportBackup(userId, packageNames);
        }
    }

    /**
     * Run a full backup pass for the given packages {@code packageNames}. Used by 'adb shell bmgr'.
     */
    public void fullTransportBackup(@UserIdInt int userId, String[] packageNames) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "fullTransportBackup()");

        if (userBackupManagerService != null) {
            userBackupManagerService.fullTransportBackup(packageNames);
        }
    }

    /**
     * Used by 'adb restore' to run a restore pass reading from the supplied {@code fd}. This method
     * is synchronous and does not return to the caller until the restore has been completed. It
     * requires on-screen confirmation by the user.
     */
    @Override
    public void adbRestore(@UserIdInt int userId, ParcelFileDescriptor fd) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "adbRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.adbRestore(fd);
        }
    }

    @Override
    public void acknowledgeFullBackupOrRestoreForUser(
            int userId,
            int token,
            boolean allow,
            String curPassword,
            String encryptionPassword,
            IFullBackupRestoreObserver observer)
            throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            acknowledgeAdbBackupOrRestore(userId, token, allow,
                    curPassword, encryptionPassword, observer);
        }
    }

    /**
     * Confirm that the previously requested adb backup/restore operation can proceed. This is used
     * to require a user-facing disclosure about the operation.
     */
    public void acknowledgeAdbBackupOrRestore(
            @UserIdInt int userId,
            int token,
            boolean allow,
            String currentPassword,
            String encryptionPassword,
            IFullBackupRestoreObserver observer) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "acknowledgeAdbBackupOrRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.acknowledgeAdbBackupOrRestore(
                    token, allow, currentPassword, encryptionPassword, observer);
        }
    }

    @Override
    public void acknowledgeFullBackupOrRestore(int token, boolean allow, String curPassword,
            String encryptionPassword, IFullBackupRestoreObserver observer)
            throws RemoteException {
        acknowledgeFullBackupOrRestoreForUser(
                binderGetCallingUserId(), token, allow, curPassword, encryptionPassword, observer);
    }


    @Override
    public String getCurrentTransportForUser(int userId) throws RemoteException {
        return (isUserReadyForBackup(userId)) ? getCurrentTransport(userId) : null;
    }

    @Override
    public String getCurrentTransport() throws RemoteException {
        return getCurrentTransportForUser(binderGetCallingUserId());
    }

    /** Return the name of the currently active transport. */
    @Nullable
    public String getCurrentTransport(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getCurrentTransport()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.getCurrentTransport();
    }

    /**
     * Returns the {@link ComponentName} of the host service of the selected transport or
     * {@code null} if no transport selected or if the transport selected is not registered.
     */
    @Override
    @Nullable
    public ComponentName getCurrentTransportComponentForUser(int userId) {
        return (isUserReadyForBackup(userId)) ? getCurrentTransportComponent(userId) : null;
    }

    /**
     * Returns the {@link ComponentName} of the host service of the selected transport or {@code
     * null} if no transport selected or if the transport selected is not registered.
     */
    @Nullable
    public ComponentName getCurrentTransportComponent(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getCurrentTransportComponent()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.getCurrentTransportComponent();
    }

    @Override
    public String[] listAllTransportsForUser(int userId) throws RemoteException {
        return (isUserReadyForBackup(userId)) ? listAllTransports(userId) : null;
    }

    /** Report all known, available backup transports by name. */
    @Nullable
    public String[] listAllTransports(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "listAllTransports()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.listAllTransports();
    }

    @Override
    public String[] listAllTransports() throws RemoteException {
        return listAllTransportsForUser(binderGetCallingUserId());
    }

    @Override
    public ComponentName[] listAllTransportComponentsForUser(int userId) throws RemoteException {
        return (isUserReadyForBackup(userId))
                ? listAllTransportComponents(userId) : null;
    }

    /** Report all known, available backup transports by {@link ComponentName}. */
    @Nullable
    public ComponentName[] listAllTransportComponents(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "listAllTransportComponents()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.listAllTransportComponents();
    }

    @Override
    public String[] getTransportWhitelist() {
        int userId = binderGetCallingUserId();
        if (!isUserReadyForBackup(userId)) {
            return null;
        }
        // No permission check, intentionally.
        String[] whitelistedTransports = new String[mTransportWhitelist.size()];
        int i = 0;
        for (ComponentName component : mTransportWhitelist) {
            whitelistedTransports[i] = component.flattenToShortString();
            i++;
        }
        return whitelistedTransports;
    }

    @Override
    public void updateTransportAttributesForUser(
            int userId,
            ComponentName transportComponent,
            String name,
            @Nullable Intent configurationIntent,
            String currentDestinationString,
            @Nullable Intent dataManagementIntent,
            CharSequence dataManagementLabel) {
        if (isUserReadyForBackup(userId)) {
            updateTransportAttributes(
                    userId,
                    transportComponent,
                    name,
                    configurationIntent,
                    currentDestinationString,
                    dataManagementIntent,
                    dataManagementLabel);
        }
    }

    /**
     * Update the attributes of the transport identified by {@code transportComponent}. If the
     * specified transport has not been bound at least once (for registration), this call will be
     * ignored. Only the host process of the transport can change its description, otherwise a
     * {@link SecurityException} will be thrown.
     *
     * @param transportComponent The identity of the transport being described.
     * @param name A {@link String} with the new name for the transport. This is NOT for
     *     identification. MUST NOT be {@code null}.
     * @param configurationIntent An {@link Intent} that can be passed to {@link
     *     Context#startActivity} in order to launch the transport's configuration UI. It may be
     *     {@code null} if the transport does not offer any user-facing configuration UI.
     * @param currentDestinationString A {@link String} describing the destination to which the
     *     transport is currently sending data. MUST NOT be {@code null}.
     * @param dataManagementIntent An {@link Intent} that can be passed to {@link
     *     Context#startActivity} in order to launch the transport's data-management UI. It may be
     *     {@code null} if the transport does not offer any user-facing data management UI.
     * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
     *     data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
     *     null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
     * @throws SecurityException If the UID of the calling process differs from the package UID of
     *     {@code transportComponent} or if the caller does NOT have BACKUP permission.
     */
    public void updateTransportAttributes(
            @UserIdInt int userId,
            ComponentName transportComponent,
            String name,
            @Nullable Intent configurationIntent,
            String currentDestinationString,
            @Nullable Intent dataManagementIntent,
            CharSequence dataManagementLabel) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "updateTransportAttributes()");

        if (userBackupManagerService != null) {
            userBackupManagerService.updateTransportAttributes(
                    transportComponent,
                    name,
                    configurationIntent,
                    currentDestinationString,
                    dataManagementIntent,
                    dataManagementLabel);
        }
    }

    @Override
    public String selectBackupTransportForUser(int userId, String transport)
            throws RemoteException {
        return (isUserReadyForBackup(userId))
                ? selectBackupTransport(userId, transport) : null;
    }

    @Override
    public String selectBackupTransport(String transport) throws RemoteException {
        return selectBackupTransportForUser(binderGetCallingUserId(), transport);
    }

    /**
     * Selects transport {@code transportName} and returns the previously selected transport.
     *
     * @deprecated Use {@link #selectBackupTransportAsync(ComponentName,
     *     ISelectBackupTransportCallback)} instead.
     */
    @Deprecated
    @Nullable
    public String selectBackupTransport(@UserIdInt int userId, String transportName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "selectBackupTransport()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.selectBackupTransport(transportName);
    }

    @Override
    public void selectBackupTransportAsyncForUser(int userId, ComponentName transport,
            ISelectBackupTransportCallback listener) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            selectBackupTransportAsync(userId, transport, listener);
        } else {
            if (listener != null) {
                try {
                    listener.onFailure(BackupManager.ERROR_BACKUP_NOT_ALLOWED);
                } catch (RemoteException ex) {
                    // ignore
                }
            }
        }
    }

    /**
     * Selects transport {@code transportComponent} asynchronously and notifies {@code listener}
     * with the result upon completion.
     */
    public void selectBackupTransportAsync(
            @UserIdInt int userId,
            ComponentName transportComponent,
            ISelectBackupTransportCallback listener) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "selectBackupTransportAsync()");

        if (userBackupManagerService != null) {
            userBackupManagerService.selectBackupTransportAsync(transportComponent, listener);
        }
    }

    @Override
    public Intent getConfigurationIntentForUser(int userId, String transport)
            throws RemoteException {
        return isUserReadyForBackup(userId) ? getConfigurationIntent(userId, transport)
                : null;
    }

    @Override
    public Intent getConfigurationIntent(String transport)
            throws RemoteException {
        return getConfigurationIntentForUser(binderGetCallingUserId(), transport);
    }

    /**
     * Supply the configuration intent for the given transport. If the name is not one of the
     * available transports, or if the transport does not supply any configuration UI, the method
     * returns {@code null}.
     */
    @Nullable
    public Intent getConfigurationIntent(@UserIdInt int userId, String transportName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getConfigurationIntent()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.getConfigurationIntent(transportName);
    }

    @Override
    public String getDestinationStringForUser(int userId, String transport) throws RemoteException {
        return isUserReadyForBackup(userId) ? getDestinationString(userId, transport)
                : null;
    }

    @Override
    public String getDestinationString(String transport) throws RemoteException {
        return getDestinationStringForUser(binderGetCallingUserId(), transport);
    }

    /**
     * Supply the current destination string for the given transport. If the name is not one of the
     * registered transports the method will return null.
     *
     * <p>This string is used VERBATIM as the summary text of the relevant Settings item.
     *
     * @param transportName The name of the registered transport.
     * @return The current destination string or null if the transport is not registered.
     */
    @Nullable
    public String getDestinationString(@UserIdInt int userId, String transportName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getDestinationString()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.getDestinationString(transportName);
    }

    @Override
    public Intent getDataManagementIntentForUser(int userId, String transport)
            throws RemoteException {
        return isUserReadyForBackup(userId)
                ? getDataManagementIntent(userId, transport) : null;
    }

    @Override
    public Intent getDataManagementIntent(String transport)
            throws RemoteException {
        return getDataManagementIntentForUser(binderGetCallingUserId(), transport);
    }

    /** Supply the manage-data intent for the given transport. */
    @Nullable
    public Intent getDataManagementIntent(@UserIdInt int userId, String transportName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getDataManagementIntent()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.getDataManagementIntent(transportName);
    }

    @Override
    public CharSequence getDataManagementLabelForUser(int userId, String transport)
            throws RemoteException {
        return isUserReadyForBackup(userId) ? getDataManagementLabel(userId, transport)
                : null;
    }

    /**
     * Supply the menu label for affordances that fire the manage-data intent for the given
     * transport.
     */
    @Nullable
    public CharSequence getDataManagementLabel(@UserIdInt int userId, String transportName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getDataManagementLabel()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.getDataManagementLabel(transportName);
    }

    @Override
    public IRestoreSession beginRestoreSessionForUser(
            int userId, String packageName, String transportID) throws RemoteException {
        return isUserReadyForBackup(userId)
                ? beginRestoreSession(userId, packageName, transportID) : null;
    }

    /**
     * Begin a restore for the specified package {@code packageName} using the specified transport
     * {@code transportName}.
     */
    @Nullable
    public IRestoreSession beginRestoreSession(
            @UserIdInt int userId, String packageName, String transportName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "beginRestoreSession()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.beginRestoreSession(packageName, transportName);
    }

    @Override
    public void opCompleteForUser(int userId, int token, long result) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            opComplete(userId, token, result);
        }
    }

    @Override
    public void opComplete(int token, long result) throws RemoteException {
        opCompleteForUser(binderGetCallingUserId(), token, result);
    }

    /**
     * Used by a currently-active backup agent to notify the service that it has completed its given
     * outstanding asynchronous backup/restore operation.
     */
    public void opComplete(@UserIdInt int userId, int token, long result) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "opComplete()");

        if (userBackupManagerService != null) {
            userBackupManagerService.opComplete(token, result);
        }
    }

    @Override
    public long getAvailableRestoreTokenForUser(int userId, String packageName) {
        return isUserReadyForBackup(userId) ? getAvailableRestoreToken(userId, packageName) : 0;
    }

    /**
     * Get the restore-set token for the best-available restore set for this {@code packageName}:
     * the active set if possible, else the ancestral one. Returns zero if none available.
     */
    public long getAvailableRestoreToken(@UserIdInt int userId, String packageName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "getAvailableRestoreToken()");

        return userBackupManagerService == null
                ? 0
                : userBackupManagerService.getAvailableRestoreToken(packageName);
    }

    @Override
    public boolean isAppEligibleForBackupForUser(int userId, String packageName) {
        return isUserReadyForBackup(userId) && isAppEligibleForBackup(userId,
                packageName);
    }

    /** Checks if the given package {@code packageName} is eligible for backup. */
    public boolean isAppEligibleForBackup(@UserIdInt int userId, String packageName) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "isAppEligibleForBackup()");

        return userBackupManagerService != null
                && userBackupManagerService.isAppEligibleForBackup(packageName);
    }

    @Override
    public String[] filterAppsEligibleForBackupForUser(int userId, String[] packages) {
        return isUserReadyForBackup(userId) ? filterAppsEligibleForBackup(userId, packages) : null;
    }

    /**
     * Returns from the inputted packages {@code packages}, the ones that are eligible for backup.
     */
    @Nullable
    public String[] filterAppsEligibleForBackup(@UserIdInt int userId, String[] packages) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "filterAppsEligibleForBackup()");

        return userBackupManagerService == null
                ? null
                : userBackupManagerService.filterAppsEligibleForBackup(packages);
    }

    @Override
    public int requestBackupForUser(@UserIdInt int userId, String[] packages, IBackupObserver
            observer, IBackupManagerMonitor monitor, int flags) throws RemoteException {
        if (!isUserReadyForBackup(userId)) {
            return BackupManager.ERROR_BACKUP_NOT_ALLOWED;
        }
        return requestBackup(userId, packages, observer, monitor, flags);
    }

    @Override
    public int requestBackup(String[] packages, IBackupObserver observer,
            IBackupManagerMonitor monitor, int flags) throws RemoteException {
        return requestBackupForUser(binderGetCallingUserId(), packages,
                observer, monitor, flags);
    }

    /**
     * Requests a backup for the inputted {@code packages} with a specified callback {@link
     * IBackupManagerMonitor} for receiving events during the operation.
     */
    public int requestBackup(
            @UserIdInt int userId,
            String[] packages,
            IBackupObserver observer,
            IBackupManagerMonitor monitor,
            int flags) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "requestBackup()");

        return userBackupManagerService == null
                ? BackupManager.ERROR_BACKUP_NOT_ALLOWED
                : userBackupManagerService.requestBackup(packages, observer, monitor, flags);
    }

    @Override
    public void cancelBackupsForUser(@UserIdInt int userId) throws RemoteException {
        if (isUserReadyForBackup(userId)) {
            cancelBackups(userId);
        }
    }

    @Override
    public void cancelBackups() throws RemoteException {
        cancelBackupsForUser(binderGetCallingUserId());
    }

    /** Cancel all running backup operations. */
    public void cancelBackups(@UserIdInt int userId) {
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "cancelBackups()");

        if (userBackupManagerService != null) {
            userBackupManagerService.cancelBackups();
        }
    }

    /**
     * Returns a {@link UserHandle} for the user that has {@code ancestralSerialNumber} as the
     * serial number of its ancestral work profile or null if there is no {@link
     * UserBackupManagerService} associated with that user.
     *
     * <p> The ancestral work profile is set by {@link #setAncestralSerialNumber(long)}
     * and it corresponds to the profile that was used to restore to the callers profile.
     */
    @Override
    @Nullable
    public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
        if (mGlobalDisable) {
            return null;
        }
        int callingUserId = Binder.getCallingUserHandle().getIdentifier();
        long oldId = Binder.clearCallingIdentity();
        final int[] userIds;
        try {
            userIds = getUserManager().getProfileIds(callingUserId, false);
        } finally {
            Binder.restoreCallingIdentity(oldId);
        }

        for (int userId : userIds) {
            UserBackupManagerService userBackupManagerService = mUserServices.get(userId);
            if (userBackupManagerService != null) {
                if (userBackupManagerService.getAncestralSerialNumber() == ancestralSerialNumber) {
                    return UserHandle.of(userId);
                }
            }
        }

        return null;
    }

    /**
     * Sets the ancestral work profile for the calling user.
     *
     * <p> The ancestral work profile corresponds to the profile that was used to restore to the
     * callers profile.
     */
    @Override
    public void setAncestralSerialNumber(long ancestralSerialNumber) {
        if (mGlobalDisable) {
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(
                        Binder.getCallingUserHandle().getIdentifier(),
                        "setAncestralSerialNumber()");

        if (userBackupManagerService != null) {
            userBackupManagerService.setAncestralSerialNumber(ancestralSerialNumber);
        }
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) {
            return;
        }
        dumpWithoutCheckingPermission(fd, pw, args);
    }

    @VisibleForTesting
    void dumpWithoutCheckingPermission(FileDescriptor fd, PrintWriter pw, String[] args) {
        int userId = binderGetCallingUserId();
        if (!isUserReadyForBackup(userId)) {
            pw.println("Inactive");
            return;
        }

        if (args != null) {
            for (String arg : args) {
                if ("-h".equals(arg)) {
                    pw.println("'dumpsys backup' optional arguments:");
                    pw.println("  -h       : this help text");
                    pw.println("  a[gents] : dump information about defined backup agents");
                    pw.println("  transportclients : dump information about transport clients");
                    pw.println("  transportstats : dump transport statts");
                    pw.println("  users    : dump the list of users for which backup service "
                            + "is running");
                    return;
                } else if ("users".equals(arg.toLowerCase())) {
                    pw.print(DUMP_RUNNING_USERS_MESSAGE);
                    for (int i = 0; i < mUserServices.size(); i++) {
                        pw.print(" " + mUserServices.keyAt(i));
                    }
                    pw.println();
                    return;
                }
            }
        }

        for (int i = 0; i < mUserServices.size(); i++) {
            UserBackupManagerService userBackupManagerService =
                    getServiceForUserIfCallerHasPermission(mUserServices.keyAt(i), "dump()");
            if (userBackupManagerService != null) {
                userBackupManagerService.dump(fd, pw, args);
            }
        }
    }

    /**
     * Used by the {@link JobScheduler} to run a full backup when conditions are right. The model we
     * use is to perform one app backup per scheduled job execution, and to reschedule the job with
     * zero latency as long as conditions remain right and we still have work to do.
     *
     * @return Whether ongoing work will continue. The return value here will be passed along as the
     *     return value to the callback {@link JobService#onStartJob(JobParameters)}.
     */
    public boolean beginFullBackup(@UserIdInt int userId, FullBackupJob scheduledJob) {
        if (!isUserReadyForBackup(userId)) {
            return false;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "beginFullBackup()");

        return userBackupManagerService != null
                && userBackupManagerService.beginFullBackup(scheduledJob);
    }

    /**
     * Used by the {@link JobScheduler} to end the current full backup task when conditions are no
     * longer met for running the full backup job.
     */
    public void endFullBackup(@UserIdInt int userId) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "endFullBackup()");

        if (userBackupManagerService != null) {
            userBackupManagerService.endFullBackup();
        }
    }

    /**
     * Excludes keys from KV restore for a given package. The corresponding data will be excluded
     * from the data set available the backup agent during restore. However,  final list  of keys
     * that have been excluded will be passed to the agent to make it aware of the exclusions.
     */
    public void excludeKeysFromRestore(String packageName, List<String> keys) {
        int userId = Binder.getCallingUserHandle().getIdentifier();
        if (!isUserReadyForBackup(userId)) {
            Slog.w(TAG, "Returning from excludeKeysFromRestore as backup for user" + userId +
                    " is not initialized yet");
            return;
        }
        UserBackupManagerService userBackupManagerService =
                getServiceForUserIfCallerHasPermission(userId, "excludeKeysFromRestore()");

        if (userBackupManagerService != null) {
            userBackupManagerService.excludeKeysFromRestore(packageName, keys);
        }
    }

    /**
     * Returns the {@link UserBackupManagerService} instance for the specified user {@code userId}.
     * If the user is not registered with the service (either the user is locked or not eligible for
     * the backup service) then return {@code null}.
     *
     * @param userId The id of the user to retrieve its instance of {@link
     *     UserBackupManagerService}.
     * @param caller A {@link String} identifying the caller for logging purposes.
     * @throws SecurityException if {@code userId} is different from the calling user id and the
     *     caller does NOT have the android.permission.INTERACT_ACROSS_USERS_FULL permission.
     */
    @Nullable
    @VisibleForTesting
    UserBackupManagerService getServiceForUserIfCallerHasPermission(
            @UserIdInt int userId, String caller) {
        enforceCallingPermissionOnUserId(userId, caller);
        UserBackupManagerService userBackupManagerService = mUserServices.get(userId);
        if (userBackupManagerService == null) {
            Slog.w(TAG, "Called " + caller + " for unknown user: " + userId);
        }
        return userBackupManagerService;
    }

    /**
     * If {@code userId} is different from the calling user id, then the caller must hold the
     * android.permission.INTERACT_ACROSS_USERS_FULL permission.
     *
     * @param userId User id on which the backup operation is being requested.
     * @param message A message to include in the exception if it is thrown.
     */
    void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
        if (Binder.getCallingUserHandle().getIdentifier() != userId) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
        }
    }

    /** Implementation to receive lifecycle event callbacks for system services. */
    public static class Lifecycle extends SystemService {
        public Lifecycle(Context context) {
            this(context, new BackupManagerService(context));
        }

        @VisibleForTesting
        Lifecycle(Context context, BackupManagerService backupManagerService) {
            super(context);
            sInstance = backupManagerService;
        }

        @Override
        public void onStart() {
            publishService(Context.BACKUP_SERVICE, BackupManagerService.sInstance);
        }

        @Override
        public void onUnlockUser(int userId) {
            sInstance.onUnlockUser(userId);
        }

        @Override
        public void onStopUser(int userId) {
            sInstance.onStopUser(userId);
        }

        @VisibleForTesting
        void publishService(String name, IBinder service) {
            publishBinderService(name, service);
        }
    }
}
