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

Commit 74eee103 authored by Bernardo Rufino's avatar Bernardo Rufino
Browse files

Use RemoteCall for quota exceeded in backups

For both key-value and full-backup. This makes the tasks wait for the
quota exceeded call, allowing the agent to complete before being torn
down (as described in bug). Also added a short time-out (3s) in case of
misbehaving agents.

Bug: 68762178
Bug: 110082831
Test: atest FrameworksServicesRoboTests
Test: 1. while true; do atest FullBackupQuotaTest; done
      2. Stop after ~50 executions, verify all succeeded.
Test: 1. while true; do atest KeyValueQuotaTest; done
      2. Stop after ~50 executions, verify all succeeded.
Test: CtsBackupTestCases

Change-Id: Ib582e75a4d317ab53a6df8cb261966a04ef085fb
parent 62b08001
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -48,8 +48,7 @@ oneway interface IBackupAgent {
     *        be echoed back to the backup service binder once the new
     *        data has been written to the data and newState files.
     *
     * @param callbackBinder Binder on which to indicate operation completion,
     *        passed here as a convenience to the agent.
     * @param callbackBinder Binder on which to indicate operation completion.
     *
     * @param transportFlags Flags with additional information about the transport.
     */
@@ -133,8 +132,9 @@ oneway interface IBackupAgent {
     *                        Could be less than total backup size if backup process was interrupted
     *                        before finish of processing all backup data.
     * @param quotaBytes Current amount of backup data that is allowed for the app.
     * @param callbackBinder Binder on which to indicate operation completion.
     */
    void doQuotaExceeded(long backupDataBytes, long quotaBytes);
    void doQuotaExceeded(long backupDataBytes, long quotaBytes, IBackupCallback callbackBinder);

    /**
     * Restore a single "file" to the application.  The file was typically obtained from
+14 −2
Original line number Diff line number Diff line
@@ -980,7 +980,7 @@ public abstract class BackupAgent extends ContextWrapper {
                try {
                    callbackBinder.operationComplete(result);
                } catch (RemoteException e) {
                    // we'll time out anyway, so we're safe
                    // We will time out anyway.
                }

                // Don't close the fd out from under the system service if this was local
@@ -1162,10 +1162,16 @@ public abstract class BackupAgent extends ContextWrapper {
        }

        @Override
        public void doQuotaExceeded(long backupDataBytes, long quotaBytes) {
        public void doQuotaExceeded(
                long backupDataBytes,
                long quotaBytes,
                IBackupCallback callbackBinder) {
            long ident = Binder.clearCallingIdentity();

            long result = RESULT_ERROR;
            try {
                BackupAgent.this.onQuotaExceeded(backupDataBytes, quotaBytes);
                result = RESULT_SUCCESS;
            } catch (Exception e) {
                Log.d(TAG, "onQuotaExceeded(" + BackupAgent.this.getClass().getName() + ") threw",
                        e);
@@ -1173,6 +1179,12 @@ public abstract class BackupAgent extends ContextWrapper {
            } finally {
                waitForSharedPrefs();
                Binder.restoreCallingIdentity(ident);

                try {
                    callbackBinder.operationComplete(result);
                } catch (RemoteException e) {
                    // We will time out anyway.
                }
            }
        }
    }
+26 −0
Original line number Diff line number Diff line
@@ -57,6 +57,10 @@ public class BackupAgentTimeoutParameters extends KeyValueSettingObserver {
    public static final String SETTING_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS =
            "restore_agent_finished_timeout_millis";

    @VisibleForTesting
    public static final String SETTING_QUOTA_EXCEEDED_TIMEOUT_MILLIS =
            "quota_exceeded_timeout_millis";

    // Default values
    @VisibleForTesting public static final long DEFAULT_KV_BACKUP_AGENT_TIMEOUT_MILLIS = 30 * 1000;

@@ -71,6 +75,9 @@ public class BackupAgentTimeoutParameters extends KeyValueSettingObserver {
    @VisibleForTesting
    public static final long DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS = 30 * 1000;

    @VisibleForTesting
    public static final long DEFAULT_QUOTA_EXCEEDED_TIMEOUT_MILLIS = 3 * 1000;

    @GuardedBy("mLock")
    private long mKvBackupAgentTimeoutMillis;

@@ -86,6 +93,9 @@ public class BackupAgentTimeoutParameters extends KeyValueSettingObserver {
    @GuardedBy("mLock")
    private long mRestoreAgentFinishedTimeoutMillis;

    @GuardedBy("mLock")
    private long mQuotaExceededTimeoutMillis;

    private final Object mLock = new Object();

    public BackupAgentTimeoutParameters(Handler handler, ContentResolver resolver) {
@@ -118,6 +128,10 @@ public class BackupAgentTimeoutParameters extends KeyValueSettingObserver {
                    parser.getLong(
                            SETTING_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS,
                            DEFAULT_RESTORE_AGENT_FINISHED_TIMEOUT_MILLIS);
            mQuotaExceededTimeoutMillis =
                    parser.getLong(
                            SETTING_QUOTA_EXCEEDED_TIMEOUT_MILLIS,
                            DEFAULT_QUOTA_EXCEEDED_TIMEOUT_MILLIS);
        }
    }

@@ -170,4 +184,16 @@ public class BackupAgentTimeoutParameters extends KeyValueSettingObserver {
            return mRestoreAgentFinishedTimeoutMillis;
        }
    }

    public long getQuotaExceededTimeoutMillis() {
        synchronized (mLock) {
            if (BackupManagerService.DEBUG_SCHEDULING) {
                Slog.v(
                        TAG,
                        "getQuotaExceededTimeoutMillis(): "
                                + mQuotaExceededTimeoutMillis);
            }
            return mQuotaExceededTimeoutMillis;
        }
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import com.android.server.AppWidgetBackupBridge;
import com.android.server.backup.BackupAgentTimeoutParameters;
import com.android.server.backup.BackupManagerService;
import com.android.server.backup.BackupRestoreTask;
import com.android.server.backup.remote.RemoteCall;
import com.android.server.backup.utils.FullBackupUtils;

import java.io.BufferedOutputStream;
@@ -270,10 +271,12 @@ public class FullBackupEngine {
        return result;
    }

    public void sendQuotaExceeded(final long backupDataBytes, final long quotaBytes) {
    public void sendQuotaExceeded(long backupDataBytes, long quotaBytes) {
        if (initializeAgent()) {
            try {
                mAgent.doQuotaExceeded(backupDataBytes, quotaBytes);
                RemoteCall.execute(
                        callback -> mAgent.doQuotaExceeded(backupDataBytes, quotaBytes, callback),
                        mAgentTimeoutParameters.getQuotaExceededTimeoutMillis());
            } catch (RemoteException e) {
                Slog.e(TAG, "Remote exception while telling agent about quota exceeded");
            }
+4 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import com.android.server.backup.BackupManagerService;
import com.android.server.backup.TransportManager;
import com.android.server.backup.internal.OnTaskFinishedListener;
import com.android.server.backup.internal.Operation;
import com.android.server.backup.remote.RemoteCall;
import com.android.server.backup.transport.TransportClient;
import com.android.server.backup.transport.TransportNotAvailableException;
import com.android.server.backup.utils.AppBackupUtils;
@@ -739,7 +740,9 @@ public class PerformFullTransportBackupTask extends FullBackupTask implements Ba
                        Slog.d(TAG, "Package hit quota limit on preflight " +
                                pkg.packageName + ": " + totalSize + " of " + mQuota);
                    }
                    agent.doQuotaExceeded(totalSize, mQuota);
                    RemoteCall.execute(
                            callback -> agent.doQuotaExceeded(totalSize, mQuota, callback),
                            mAgentTimeoutParameters.getQuotaExceededTimeoutMillis());
                }
            } catch (Exception e) {
                Slog.w(TAG, "Exception preflighting " + pkg.packageName + ": " + e.getMessage());
Loading