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

Commit a694a2b8 authored by Sarp Misoglu's avatar Sarp Misoglu Committed by Android (Google) Code Review
Browse files

Merge "Use internal interface for AMS -> BMS calls" into main

parents 5b68df99 51e0759a
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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 android.app.backup;

import android.annotation.UserIdInt;
import android.os.IBinder;

/**
 * Local system service interface for {@link com.android.server.backup.BackupManagerService}.
 *
 * @hide Only for use within the system server.
 */
public interface BackupManagerInternal {

    /**
     * Notifies the Backup Manager Service that an agent has become available. This
     * method is only invoked by the Activity Manager.
     */
    void agentConnectedForUser(String packageName, @UserIdInt int userId, IBinder agent);

    /**
     * Notify the Backup Manager Service that an agent has unexpectedly gone away.
     * This method is only invoked by the Activity Manager.
     */
    void agentDisconnectedForUser(String packageName, @UserIdInt int userId);
}
+0 −32
Original line number Diff line number Diff line
@@ -92,38 +92,6 @@ interface IBackupManager {
    void initializeTransportsForUser(int userId, in String[] transportNames,
        IBackupObserver observer);

    /**
     * Notifies the Backup Manager Service that an agent has become available.  This
     * method is only invoked by the Activity Manager.
     *
     * 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 for which an agent has become available.
     */
    void agentConnectedForUser(int userId, String packageName, IBinder agent);

    /**
     * {@link android.app.backup.IBackupManager.agentConnected} for the calling user id.
     */
    void agentConnected(String packageName, IBinder agent);

    /**
     * Notify the Backup Manager Service that an agent has unexpectedly gone away.
     * This method is only invoked by the Activity Manager.
     *
     * 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 for which an agent has unexpectedly gone away.
     */
    void agentDisconnectedForUser(int userId, String packageName);

    /**
     * {@link android.app.backup.IBackupManager.agentDisconnected} for the calling user id.
     */
    void agentDisconnected(String packageName);

    /**
     * Notify the Backup Manager Service that an application being installed will
     * need a data-restore pass.  This method is only invoked by the Package Manager.
+25 −44
Original line number Diff line number Diff line
@@ -22,9 +22,9 @@ import android.Manifest;
import android.annotation.NonNull;
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.BackupManagerInternal;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManagerMonitor;
@@ -60,6 +60,7 @@ 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.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
import com.android.server.backup.utils.RandomAccessFileUtils;
@@ -91,7 +92,7 @@ import java.util.Set;
 * 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 class BackupManagerService extends IBackupManager.Stub implements BackupManagerInternal {
    public static final String TAG = "BackupManagerService";
    public static final boolean DEBUG = true;
    public static final boolean MORE_DEBUG = false;
@@ -191,7 +192,6 @@ public class BackupManagerService extends IBackupManager.Stub {
        }
    }

    // TODO: Remove this when we implement DI by injecting in the construtor.
    @VisibleForTesting
    Handler getBackupHandler() {
        return mHandler;
@@ -637,51 +637,28 @@ public class BackupManagerService extends IBackupManager.Stub {
    }

    @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);
    public void agentConnectedForUser(String packageName, @UserIdInt int userId, IBinder agent) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }

    /**
     * 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()");
        UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(
                userId, "agentConnected()");

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

    @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);
    public void agentDisconnectedForUser(String packageName, @UserIdInt int userId) {
        if (!isUserReadyForBackup(userId)) {
            return;
        }

    /**
     * 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()");
        UserBackupManagerService userBackupManagerService = getServiceForUserIfCallerHasPermission(
                userId, "agentDisconnected()");

        if (userBackupManagerService != null) {
            userBackupManagerService.getBackupAgentConnectionManager().agentDisconnected(
@@ -1688,7 +1665,7 @@ public class BackupManagerService extends IBackupManager.Stub {
     * @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) {
    private void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
        if (binderGetCallingUserId() != userId) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
@@ -1697,6 +1674,8 @@ public class BackupManagerService extends IBackupManager.Stub {

    /** Implementation to receive lifecycle event callbacks for system services. */
    public static class Lifecycle extends SystemService {
        private final BackupManagerService mBackupManagerService;

        public Lifecycle(Context context) {
            this(context, new BackupManagerService(context));
        }
@@ -1704,12 +1683,14 @@ public class BackupManagerService extends IBackupManager.Stub {
        @VisibleForTesting
        Lifecycle(Context context, BackupManagerService backupManagerService) {
            super(context);
            mBackupManagerService = backupManagerService;
            sInstance = backupManagerService;
            LocalServices.addService(BackupManagerInternal.class, mBackupManagerService);
        }

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

        @Override
@@ -1717,17 +1698,17 @@ public class BackupManagerService extends IBackupManager.Stub {
            // 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.
            sInstance.postToHandler(
            mBackupManagerService.postToHandler(
                    () -> {
                        sInstance.updateDefaultBackupUserIdIfNeeded();
                        sInstance.startServiceForUser(user.getUserIdentifier());
                        sInstance.mHasFirstUserUnlockedSinceBoot = true;
                        mBackupManagerService.updateDefaultBackupUserIdIfNeeded();
                        mBackupManagerService.startServiceForUser(user.getUserIdentifier());
                        mBackupManagerService.mHasFirstUserUnlockedSinceBoot = true;
                    });
        }

        @Override
        public void onUserStopping(@NonNull TargetUser user) {
            sInstance.onStopUser(user.getUserIdentifier());
            mBackupManagerService.onStopUser(user.getUserIdentifier());
        }

        @VisibleForTesting
+7 −18
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ import android.app.ServiceStartNotAllowedException;
import android.app.WaitResult;
import android.app.assist.ActivityId;
import android.app.backup.BackupAnnotations.BackupDestination;
import android.app.backup.IBackupManager;
import android.app.backup.BackupManagerInternal;
import android.app.compat.CompatChanges;
import android.app.job.JobParameters;
import android.app.usage.UsageEvents;
@@ -4490,11 +4490,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                final int userId = app.userId;
                final String packageName = app.info.packageName;
                mHandler.post(() -> {
                    try {
                        getBackupManager().agentDisconnectedForUser(userId, packageName);
                    } catch (RemoteException e) {
                        // Can't happen; the backup manager is local
                    }
                    LocalServices.getService(BackupManagerInternal.class).agentDisconnectedForUser(
                            packageName, userId);
                });
            }
        } else {
@@ -13547,11 +13544,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
                    + backupTarget.appInfo + " died during backup");
            mHandler.post(() -> {
                try {
                    getBackupManager().agentDisconnectedForUser(app.userId, app.info.packageName);
                } catch (RemoteException e) {
                    // can't happen; backup manager is local
                }
                LocalServices.getService(BackupManagerInternal.class).agentDisconnectedForUser(
                        app.info.packageName, app.userId);
            });
        }
@@ -14265,9 +14259,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        final long oldIdent = Binder.clearCallingIdentity();
        try {
            getBackupManager().agentConnectedForUser(userId, agentPackageName, agent);
        } catch (RemoteException e) {
            // can't happen; the backup manager service is local
            LocalServices.getService(BackupManagerInternal.class).agentConnectedForUser(
                    agentPackageName, userId, agent);
        } catch (Exception e) {
            Slog.w(TAG, "Exception trying to deliver BackupAgent binding: ");
            e.printStackTrace();
@@ -19488,8 +19481,4 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        return token;
    }
    private IBackupManager getBackupManager() {
        return IBackupManager.Stub.asInterface(ServiceManager.getService(Context.BACKUP_SERVICE));
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import static org.testng.Assert.expectThrows;

import android.annotation.UserIdInt;
import android.app.Application;
import android.app.backup.BackupManagerInternal;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
@@ -52,6 +53,7 @@ import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;

import com.android.server.LocalServices;
import com.android.server.SystemService.TargetUser;
import com.android.server.backup.testing.TransportData;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
@@ -229,7 +231,7 @@ public class BackupManagerServiceRoboTest {
        setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
        IBinder agentBinder = mock(IBinder.class);

        backupManagerService.agentConnected(mUserOneId, TEST_PACKAGE, agentBinder);
        backupManagerService.agentConnectedForUser(TEST_PACKAGE, mUserOneId, agentBinder);

        verify(mUserOneBackupAgentConnectionManager).agentConnected(TEST_PACKAGE, agentBinder);
    }
@@ -242,7 +244,7 @@ public class BackupManagerServiceRoboTest {
        setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
        IBinder agentBinder = mock(IBinder.class);

        backupManagerService.agentConnected(mUserTwoId, TEST_PACKAGE, agentBinder);
        backupManagerService.agentConnectedForUser(TEST_PACKAGE, mUserTwoId, agentBinder);

        verify(mUserOneBackupAgentConnectionManager, never()).agentConnected(TEST_PACKAGE,
                agentBinder);
@@ -1549,6 +1551,7 @@ public class BackupManagerServiceRoboTest {
    @Test
    public void testOnStart_publishesService() {
        BackupManagerService backupManagerService = mock(BackupManagerService.class);
        LocalServices.removeServiceForTest(BackupManagerInternal.class);
        BackupManagerService.Lifecycle lifecycle =
                spy(new BackupManagerService.Lifecycle(mContext, backupManagerService));
        doNothing().when(lifecycle).publishService(anyString(), any());
Loading