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

Commit dca44642 authored by Sarp Misoglu's avatar Sarp Misoglu
Browse files

Don't use backup restricted mode in certain cases

In this change we introduce a new ApplicationManifest property which
allows apps to specify whether they want to be put in restricted mode
for B&R operations. If the app explicitly set the property, it's always
respected.

If the app has not set the property then we use targetSdk gating:
* For targetSdk < 36, we keep the status quo and put the app into
  restricted mode.
* For targetSdk >= 36, we call a new API to the BackupTransport for it
  to make a decision on a per-package basis.

Some implementation details explained:
* In order to not block process creation in ActivityManager on an IPC to
  the BackupTransport, we call the transport earlier in
  PerformFullTransportBackupTask (for backup) and
  PerforUnifiedRestoreTask (for restore). We cache the list in memory in
  BackupManagerService.
* When AMS#bindBackupAgent is called, the BackupManagerService tells it
  whether to use restricted mode. AMS stores this in the existing
  BackupRecord data class and uses it in attachApplication().
* PerformUnifiedRestoreTask is an extremely untestable state machine and
  testing this properly is difficult without a significant rewrite so
  I'm using @VisibleForTesting.
* Seems like AMS#attachApplication also requires a lot of mocking so
  couldn't add tests there.

Flag: com.android.server.backup.enable_restricted_mode_changes
Bug: 376661510
Test: atest (see tests changed) and manually with a test app that
  defined its own Application subclass.

API-Coverage-Bug: 379086316
Change-Id: Ie060890131ba526d58ec9134e52fd80acc23ef63
parent d322e4e7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -13569,6 +13569,7 @@ package android.content.pm {
    field public static final String PROPERTY_MEDIA_CAPABILITIES = "android.media.PROPERTY_MEDIA_CAPABILITIES";
    field public static final String PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES = "android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES";
    field public static final String PROPERTY_SPECIAL_USE_FGS_SUBTYPE = "android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE";
    field @FlaggedApi("com.android.server.backup.enable_restricted_mode_changes") public static final String PROPERTY_USE_RESTRICTED_BACKUP_MODE = "android.app.backup.PROPERTY_USE_RESTRICTED_BACKUP_MODE";
    field public static final int SIGNATURE_FIRST_NOT_SIGNED = -1; // 0xffffffff
    field public static final int SIGNATURE_MATCH = 0; // 0x0
    field public static final int SIGNATURE_NEITHER_SIGNED = 1; // 0x1
+1 −0
Original line number Diff line number Diff line
@@ -1937,6 +1937,7 @@ package android.app.backup {
    method public android.os.IBinder getBinder();
    method public long getCurrentRestoreSet();
    method public int getNextFullRestoreDataChunk(android.os.ParcelFileDescriptor);
    method @FlaggedApi("com.android.server.backup.enable_restricted_mode_changes") @NonNull public java.util.List<java.lang.String> getPackagesThatShouldNotUseRestrictedMode(@NonNull java.util.List<java.lang.String>, int);
    method public int getRestoreData(android.os.ParcelFileDescriptor);
    method public int getTransportFlags();
    method public int initializeDevice();
+1 −1
Original line number Diff line number Diff line
@@ -358,7 +358,7 @@ interface IActivityManager {
    @UnsupportedAppUsage
    void resumeAppSwitches();
    boolean bindBackupAgent(in String packageName, int backupRestoreMode, int targetUserId,
            int backupDestination);
            int backupDestination, boolean useRestrictedMode);
    void backupAgentCreated(in String packageName, in IBinder agent, int userId);
    void unbindBackupAgent(in ApplicationInfo appInfo);
    int handleIncomingUser(int callingPid, int callingUid, int userId, boolean allowAll,
+33 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.app.backup;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Intent;
@@ -27,6 +29,7 @@ import android.os.RemoteException;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.ITransportStatusCallback;
import com.android.internal.infra.AndroidFuture;
import com.android.server.backup.Flags;

import java.util.Arrays;
import java.util.List;
@@ -670,6 +673,22 @@ public class BackupTransport {
        return null;
    }

    /**
     * Ask the transport whether packages that are about to be backed up or restored should not be
     * put into a restricted mode by the framework and started normally instead.
     *
     * @param operationType 0 for backup, 1 for restore.
     * @return a subset of the {@code packageNames} passed in, indicating
     * which packages should NOT be put into restricted mode for the given operation type.
     */
    @NonNull
    @FlaggedApi(Flags.FLAG_ENABLE_RESTRICTED_MODE_CHANGES)
    public List<String> getPackagesThatShouldNotUseRestrictedMode(
            @NonNull List<String> packageNames,
            @BackupAnnotations.OperationType int operationType) {
        return List.of();
    }

    /**
     * Bridge between the actual IBackupTransport implementation and the stable API.  If the
     * binder interface needs to change, we use this layer to translate so that we can
@@ -977,5 +996,19 @@ public class BackupTransport {
                resultFuture.cancel(/* mayInterruptIfRunning */ true);
            }
        }

        @Override
        @FlaggedApi(Flags.FLAG_ENABLE_RESTRICTED_MODE_CHANGES)
        public void getPackagesThatShouldNotUseRestrictedMode(List<String> packageNames,
                int operationType, AndroidFuture<List<String>> resultFuture) {
            try {
                List<String> result =
                        BackupTransport.this.getPackagesThatShouldNotUseRestrictedMode(packageNames,
                                operationType);
                resultFuture.complete(result);
            } catch (RuntimeException e) {
                resultFuture.cancel(/* mayInterruptIfRunning */ true);
            }
        }
    }
}
+36 −0
Original line number Diff line number Diff line
@@ -192,6 +192,42 @@ public abstract class PackageManager {
    public static final String PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES =
            "android.net.PROPERTY_SELF_CERTIFIED_NETWORK_CAPABILITIES";

    /**
     * &lt;application&gt; level {@link android.content.pm.PackageManager.Property} tag
     * specifying whether the app should be put into the "restricted" backup mode when it's started
     * for backup and restore operations.
     *
     * <p> See <a
     * href="https://developer.android.com/identity/data/autobackup#ImplementingBackupAgent"> for
     * information about restricted mode</a>.
     *
     * <p> Starting with Android 16 apps may not be started in restricted mode based on this
     * property.
     *
     * <p><b>Syntax:</b>
     * <pre>
     * &lt;application&gt;
     *   &lt;property
     *     android:name="android.app.backup.PROPERTY_USE_RESTRICTED_BACKUP_MODE"
     *     android:value="true|false"/&gt;
     * &lt;/application&gt;
     * </pre>
     *
     * <p>If this property is set, the operating system will respect it for now (see Note below).
     * If it's not set, the behavior depends on the SDK level that the app is targeting. For apps
     * targeting SDK level {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM} or lower, the
     * property defaults to {@code true}. For apps targeting SDK level
     * {@link android.os.Build.VERSION_CODES#BAKLAVA} or higher, the operating system will make a
     * decision dynamically.
     *
     * <p>Note: It's not recommended to set this property to {@code true} unless absolutely
     * necessary. In a future Android version, this property may be deprecated in favor of removing
     * restricted mode completely.
     */
    @FlaggedApi(com.android.server.backup.Flags.FLAG_ENABLE_RESTRICTED_MODE_CHANGES)
    public static final String PROPERTY_USE_RESTRICTED_BACKUP_MODE =
            "android.app.backup.PROPERTY_USE_RESTRICTED_BACKUP_MODE";

    /**
     * Application level property that an app can specify to opt-out from having private data
     * directories both on the internal and external storages.
Loading