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

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

Merge "Integrate BackupAgent with B&REventLogger"

parents 6cdb9351 c7076a71
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -16,10 +16,13 @@

package android.app;

import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.IBackupCallback;
import android.app.backup.IBackupManager;
import android.os.ParcelFileDescriptor;

import com.android.internal.infra.AndroidFuture;
 
/**
 * Interface presented by applications being asked to participate in the
 * backup & restore mechanism.  End user code will not typically implement
@@ -193,4 +196,14 @@ oneway interface IBackupAgent {
     * @param message The message to be passed to the agent's application in an exception.
     */
    void fail(String message);

    /**
     * Provides the logging results that were accumulated in the BackupAgent during a backup or
     * restore operation. This method should be called after the agent completes its backup or
     * restore.
     *
     * @param resultsFuture a future that is completed with the logging results.
     */
    void getLoggerResults(
            in AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> resultsFuture);
}
+29 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.util.ArraySet;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AndroidFuture;

import libcore.io.IoUtils;

@@ -202,6 +203,7 @@ public abstract class BackupAgent extends ContextWrapper {

    Handler mHandler = null;

    @Nullable private volatile BackupRestoreEventLogger mLogger = null;
    @Nullable private UserHandle mUser;
     // This field is written from the main thread (in onCreate), and read in a Binder thread (in
     // onFullBackup that is called from system_server via Binder).
@@ -234,6 +236,20 @@ public abstract class BackupAgent extends ContextWrapper {
        } catch (InterruptedException e) { /* ignored */ }
    }

    /**
     * Get a logger to record app-specific backup and restore events that are happening during a
     * backup or restore operation.
     *
     * <p>The logger instance had been created by the system with the correct {@link
     * BackupRestoreEventLogger.OperationType} that corresponds to the operation the {@code
     * BackupAgent} is currently handling.
     *
     * @hide
     */
    @Nullable
    public BackupRestoreEventLogger getBackupRestoreEventLogger() {
        return mLogger;
    }

    public BackupAgent() {
        super(null);
@@ -264,6 +280,9 @@ public abstract class BackupAgent extends ContextWrapper {
     * @hide
     */
    public void onCreate(UserHandle user, @OperationType int operationType) {
        // TODO: Instantiate with the correct type using a parameter.
        mLogger = new BackupRestoreEventLogger(BackupRestoreEventLogger.OperationType.BACKUP);

        onCreate();

        mUser = user;
@@ -1305,6 +1324,16 @@ public abstract class BackupAgent extends ContextWrapper {
                }
            }
        }

        @Override
        public void getLoggerResults(
                AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> in) {
            if (mLogger != null) {
                in.complete(mLogger.getLoggingResults());
            } else {
                in.complete(Collections.emptyList());
            }
        }
    }

    static class FailRunnable implements Runnable {
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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;

parcelable BackupRestoreEventLogger.DataTypeResult;
 No newline at end of file
+57 −1
Original line number Diff line number Diff line
@@ -19,6 +19,10 @@ package android.app.backup;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.Slog;

import java.lang.annotation.Retention;
@@ -312,7 +316,7 @@ public class BackupRestoreEventLogger {
    /**
     * Encapsulate logging results for a single data type.
     */
    public static class DataTypeResult {
    public static class DataTypeResult implements Parcelable {
        @BackupRestoreDataType
        private final String mDataType;
        private int mSuccessCount;
@@ -362,5 +366,57 @@ public class BackupRestoreEventLogger {
        public byte[] getMetadataHash() {
            return mMetadataHash;
        }

        @Override
        public int describeContents() {
            return 0;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(mDataType);

            dest.writeInt(mSuccessCount);

            dest.writeInt(mFailCount);

            Bundle errorsBundle = new Bundle();
            for (Map.Entry<String, Integer> e : mErrors.entrySet()) {
                errorsBundle.putInt(e.getKey(), e.getValue());
            }
            dest.writeBundle(errorsBundle);

            dest.writeByteArray(mMetadataHash);
        }

        public static final Parcelable.Creator<DataTypeResult> CREATOR =
                new Parcelable.Creator<>() {
                    public DataTypeResult createFromParcel(Parcel in) {
                        String dataType = in.readString();

                        int successCount = in.readInt();

                        int failCount = in.readInt();

                        Map<String, Integer> errors = new ArrayMap<>();
                        Bundle errorsBundle = in.readBundle(getClass().getClassLoader());
                        for (String key : errorsBundle.keySet()) {
                            errors.put(key, errorsBundle.getInt(key));
                        }

                        byte[] metadataHash = in.createByteArray();

                        DataTypeResult result = new DataTypeResult(dataType);
                        result.mSuccessCount = successCount;
                        result.mFailCount = failCount;
                        result.mErrors.putAll(errors);
                        result.mMetadataHash = metadataHash;
                        return result;
                    }

                    public DataTypeResult[] newArray(int size) {
                        return new DataTypeResult[size];
                    }
                };
    }
}
+42 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import java.util.Set;
public class BackupAgentTest {
    // An arbitrary user.
    private static final UserHandle USER_HANDLE = new UserHandle(15);
    private static final String DATA_TYPE_BACKED_UP = "test data type";

    @Mock FullBackup.BackupScheme mBackupScheme;

@@ -73,6 +74,42 @@ public class BackupAgentTest {
        assertThat(rules).isEqualTo(expectedRules);
    }

    @Test
    public void getBackupRestoreEventLogger_beforeOnCreate_isNull() {
        BackupAgent agent = new TestFullBackupAgent();

        assertThat(agent.getBackupRestoreEventLogger()).isNull();
    }

    @Test
    public void getBackupRestoreEventLogger_afterOnCreateForBackup_initializedForBackup() {
        BackupAgent agent = new TestFullBackupAgent();
        agent.onCreate(USER_HANDLE, OperationType.BACKUP); // TODO: pass in new operation type

        assertThat(agent.getBackupRestoreEventLogger().getOperationType()).isEqualTo(1);
    }

    @Test
    public void getBackupRestoreEventLogger_afterOnCreateForRestore_initializedForRestore() {
        BackupAgent agent = new TestFullBackupAgent();
        agent.onCreate(USER_HANDLE, OperationType.BACKUP); // TODO: pass in new operation type

        assertThat(agent.getBackupRestoreEventLogger().getOperationType()).isEqualTo(1);
    }

    @Test
    public void getBackupRestoreEventLogger_afterBackup_containsLogsLoggedByAgent()
            throws Exception {
        BackupAgent agent = new TestFullBackupAgent();
        agent.onCreate(USER_HANDLE, OperationType.BACKUP); // TODO: pass in new operation type

        // TestFullBackupAgent logs DATA_TYPE_BACKED_UP when onFullBackup is called.
        agent.onFullBackup(new FullBackupDataOutput(/* quota = */ 0));

        assertThat(agent.getBackupRestoreEventLogger().getLoggingResults().get(0).getDataType())
                .isEqualTo(DATA_TYPE_BACKED_UP);
    }

    private BackupAgent getAgentForOperationType(@OperationType int operationType) {
        BackupAgent agent = new TestFullBackupAgent();
        agent.onCreate(USER_HANDLE, operationType);
@@ -87,6 +124,11 @@ public class BackupAgentTest {
            // Left empty as this is a full backup agent.
        }

        @Override
        public void onFullBackup(FullBackupDataOutput data) {
            getBackupRestoreEventLogger().logItemsBackedUp(DATA_TYPE_BACKED_UP, 1);
        }

        @Override
        public void onRestore(BackupDataInput data, int appVersionCode,
                ParcelFileDescriptor newState) throws IOException {
Loading