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

Commit c74e868b authored by Felipe Leme's avatar Felipe Leme
Browse files

Refactored LocalTransport to log DataTypeResult as a String.

You can check by running:

$ adb logcat LocalTransport *:s &
$ adb shell 'settings put secure backup_local_transport_parameters "dump_agent_results=true"'
$ adb shell bmgr transport com.android.localtransport/.LocalTransport
$ adb shell bmgr backupnow android
$ adb shell bmgr run

Test: atest FrameworksCoreTests --test-filter=".*DataTypeResult.*"
Test: manual verification with steps above

Bug: 394173116
Flag: EXEMPT changes on debugging components only

Change-Id: Ife98467d8169984c9e4f212260e3d18442812666
parent 8b634e94
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -34,9 +34,11 @@ import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Class to log B&R stats for each data type that is backed up and restored by the calling app.
@@ -325,6 +327,21 @@ public final class BackupRestoreEventLogger {
        }
    }

    /** @hide */
    public static String toString(DataTypeResult result) {
        Objects.requireNonNull(result, "result cannot be null");
        StringBuilder string = new StringBuilder("type=").append(result.mDataType)
                .append(", successCount=").append(result.mSuccessCount)
                .append(", failCount=").append(result.mFailCount);
        if (!result.mErrors.isEmpty()) {
            string.append(", errors=").append(result.mErrors);
        }
        if (result.mMetadataHash != null) {
            string.append(", metadataHash=").append(Arrays.toString(result.mMetadataHash));
        }
        return string.toString();
    }

    /**
     * Encapsulate logging results for a single data type.
     */
+34 −0
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import static com.google.common.truth.Truth.assertThat;

import static junit.framework.Assert.fail;

import static org.junit.Assert.assertThrows;

import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
@@ -32,6 +34,8 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.server.backup.Flags;

import com.google.common.truth.Expect;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -42,6 +46,7 @@ import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

@Presubmit
@@ -64,6 +69,9 @@ public class BackupRestoreEventLoggerTest {
    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    @Rule
    public final Expect expect = Expect.create();

    @Before
    public void setUp() throws Exception {
        mHashDigest = MessageDigest.getInstance("SHA-256");
@@ -366,6 +374,32 @@ public class BackupRestoreEventLoggerTest {
        assertThat(mLogger.getLoggingResults()).isEmpty();
    }

    @Test
    public void testDataTypeResultToString_nullArgs() {
        assertThrows(NullPointerException.class, () -> BackupRestoreEventLogger.toString(null));
    }

    @Test
    public void testDataTypeResultToString_typeOnly() {
        DataTypeResult result = new DataTypeResult("The Type is Bond, James Bond!");

        expect.withMessage("toString()")
                .that(BackupRestoreEventLogger.toString(result)).isEqualTo(
                        "type=The Type is Bond, James Bond!, successCount=0, failCount=0");
    }

    @Test
    public void testDataTypeResultToString_allFields() {
        DataTypeResult result = DataTypeResultTest.createDataTypeResult(
                "The Type is Bond, James Bond!", /* successCount= */ 42, /* failCount= */ 108,
                Map.of("D'OH!", 666, "", 0), new byte[] { 4, 8, 15, 16, 23, 42 });

        expect.withMessage("toString()")
                .that(BackupRestoreEventLogger.toString(result)).isEqualTo(
                        "type=The Type is Bond, James Bond!, successCount=42, failCount=108, "
                        + "errors={=0, D'OH!=666}, metadataHash=[4, 8, 15, 16, 23, 42]");
    }

    private static DataTypeResult getResultForDataType(
            BackupRestoreEventLogger logger, String dataType) {
        Optional<DataTypeResult> result = getResultForDataTypeIfPresent(logger, dataType);
+117 −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 static com.google.common.truth.Truth.assertWithMessage;

import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.os.Bundle;
import android.os.Parcel;

import com.google.common.truth.Expect;

import org.junit.Rule;
import org.junit.Test;

import java.util.Map;

public final class DataTypeResultTest {

    @Rule
    public final Expect expect = Expect.create();

    @Test
    public void testGetters_defaultConstructorFields() {
        var result = new DataTypeResult("The Type is Bond, James Bond!");

        expect.withMessage("getDataType()").that(result.getDataType())
                .isEqualTo("The Type is Bond, James Bond!");
        expect.withMessage("getSuccessCount()").that(result.getSuccessCount()).isEqualTo(0);
        expect.withMessage("getFailCount()").that(result.getFailCount()).isEqualTo(0);
        expect.withMessage("getErrorsCount()").that(result.getErrors()).isEmpty();
        expect.withMessage("getMetadataHash()").that(result.getMetadataHash()).isNull();
        expect.withMessage("describeContents()").that(result.describeContents()).isEqualTo(0);
    }

    @Test
    public void testGetters_allFields() {
        DataTypeResult result = createDataTypeResult("The Type is Bond, James Bond!",
                /* successCount= */ 42, /* failCount= */ 108, Map.of("D'OH!", 666),
                new byte[] { 4, 8, 15, 16, 23, 42 });

        expect.withMessage("getDataType()").that(result.getDataType())
                .isEqualTo("The Type is Bond, James Bond!");
        expect.withMessage("getSuccessCount()").that(result.getSuccessCount()).isEqualTo(42);
        expect.withMessage("getFailCount()").that(result.getFailCount()).isEqualTo(108);
        expect.withMessage("getErrorsCount()").that(result.getErrors()).containsExactly("D'OH!",
                666);
        expect.withMessage("getMetadataHash()").that(result.getMetadataHash()).asList()
                .containsExactly((byte) 4, (byte) 8, (byte) 15, (byte) 16, (byte) 23, (byte) 42)
                .inOrder();
        expect.withMessage("describeContents()").that(result.describeContents()).isEqualTo(0);
    }

    @Test
    public void testParcelMethods() {
        DataTypeResult original = createDataTypeResult("The Type is Bond, James Bond!",
                /* successCount= */ 42, /* failCount= */ 108, Map.of("D'OH!", 666),
                new byte[] { 4, 8, 15, 16, 23, 42 });
        Parcel parcel = Parcel.obtain();
        try {
            original.writeToParcel(parcel, /* flags= */ 0);

            parcel.setDataPosition(0);
            var clone = DataTypeResult.CREATOR.createFromParcel(parcel);
            assertWithMessage("createFromParcel()").that(clone).isNotNull();

            expect.withMessage("getDataType()").that(clone.getDataType())
                    .isEqualTo(original.getDataType());
            expect.withMessage("getSuccessCount()").that(clone.getSuccessCount())
                    .isEqualTo(original.getSuccessCount());
            expect.withMessage("getFailCount()").that(clone.getFailCount())
                    .isEqualTo(original.getFailCount());
            expect.withMessage("getErrorsCount()").that(clone.getErrors())
                    .containsExactlyEntriesIn(original.getErrors()).inOrder();
            expect.withMessage("getMetadataHash()").that(clone.getMetadataHash())
                    .isEqualTo(original.getMetadataHash());
            expect.withMessage("describeContents()").that(clone.describeContents()).isEqualTo(0);
        } finally {
            parcel.recycle();
        }
    }

    static DataTypeResult createDataTypeResult(String dataType, int successCount, int failCount,
            Map<String, Integer> errors, byte... metadataHash) {
        Parcel parcel = Parcel.obtain();
        try {
            parcel.writeString(dataType);
            parcel.writeInt(successCount);
            parcel.writeInt(failCount);
            Bundle errorsBundle = new Bundle();
            errors.entrySet()
                    .forEach(entry -> errorsBundle.putInt(entry.getKey(), entry.getValue()));
            parcel.writeBundle(errorsBundle);
            parcel.writeByteArray(metadataHash);

            parcel.setDataPosition(0);
            var result = DataTypeResult.CREATOR.createFromParcel(parcel);
            assertWithMessage("createFromParcel()").that(result).isNotNull();
            return result;
        } finally {
            parcel.recycle();
        }
    }
}
+3 −15
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.app.backup.BackupAnnotations;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreDescription;
@@ -52,7 +53,6 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

@@ -924,24 +924,12 @@ public class LocalTransport extends BackupTransport {
                        BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS,
                        DataTypeResult.class);
                for (DataTypeResult result : results) {
                    Log.i(TAG, "\tdataType: " + result.getDataType());
                    Log.i(TAG, "\tsuccessCount: " + result.getSuccessCount());
                    Log.i(TAG, "\tfailCount: " + result.getFailCount());
                    Log.i(TAG, "\tmetadataHash: " + Arrays.toString(result.getMetadataHash()));

                    if (!result.getErrors().isEmpty()) {
                        Log.i(TAG, "\terrors {");
                        for (String error : result.getErrors().keySet()) {
                            Log.i(TAG, "\t\t" + error + ": " + result.getErrors().get(error));
                        }
                        Log.i(TAG, "\t}");
                    Log.i(TAG, "\t" + BackupRestoreEventLogger.toString(result));
                }

                Log.i(TAG, "}");
            }
        }
    }
    }

    @NonNull
    @Override