Loading core/api/system-current.txt +28 −0 Original line number Diff line number Diff line Loading @@ -1474,6 +1474,7 @@ package android.app.backup { method @RequiresPermission(android.Manifest.permission.BACKUP) public void cancelBackups(); method @RequiresPermission(android.Manifest.permission.BACKUP) public void excludeKeysFromRestore(@NonNull String, @NonNull java.util.List<java.lang.String>); method @RequiresPermission(android.Manifest.permission.BACKUP) public long getAvailableRestoreToken(String); method @NonNull public android.app.backup.BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull android.app.backup.BackupAgent); method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getConfigurationIntent(String); method @RequiresPermission(android.Manifest.permission.BACKUP) public String getCurrentTransport(); method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.ComponentName getCurrentTransportComponent(); Loading Loading @@ -1592,6 +1593,33 @@ package android.app.backup { field public final long bytesTransferred; } public class BackupRestoreEventLogger { method public void logBackupMetaData(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String); method public void logItemsBackedUp(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int); method public void logItemsBackupFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String); method public void logItemsRestoreFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String); method public void logItemsRestored(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int); method public void logRestoreMetadata(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String); } @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreDataType { } @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreError { } public static final class BackupRestoreEventLogger.DataTypeResult implements android.os.Parcelable { ctor public BackupRestoreEventLogger.DataTypeResult(@NonNull String); method public int describeContents(); method @android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull public String getDataType(); method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getErrors(); method public int getFailCount(); method @Nullable public byte[] getMetadataHash(); method public int getSuccessCount(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.backup.BackupRestoreEventLogger.DataTypeResult> CREATOR; } public class BackupTransport { ctor public BackupTransport(); method public int abortFullRestore(); core/java/android/app/backup/BackupManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -1018,6 +1018,29 @@ public class BackupManager { } } /** * Get an instance of {@link BackupRestoreEventLogger} to report B&R related events during an * ongoing backup or restore operation. * * @param backupAgent the agent currently running a B&R operation. * * @return an instance of {@code BackupRestoreEventLogger} or {@code null} if the agent has not * finished initialisation, i.e. {@link BackupAgent#onCreate()} has not been called yet. * @throws IllegalStateException if called before the agent has finished initialisation. * * @hide */ @NonNull @SystemApi public BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull BackupAgent backupAgent) { BackupRestoreEventLogger logger = backupAgent.getBackupRestoreEventLogger(); if (logger == null) { throw new IllegalStateException("Attempting to get logger on an uninitialised " + "BackupAgent"); } return backupAgent.getBackupRestoreEventLogger(); } /* * We wrap incoming binder calls with a private class implementation that * redirects them into main-thread actions. This serializes the backup Loading core/java/android/app/backup/BackupRestoreEventLogger.java +8 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.app.backup; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; Loading @@ -35,7 +36,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; // TODO(b/244436184): Make this @SystemApi /** * Class to log B&R stats for each data type that is backed up and restored by the calling app. * Loading @@ -46,12 +46,15 @@ import java.util.Map; * * @hide */ @SystemApi public class BackupRestoreEventLogger { private static final String TAG = "BackupRestoreEventLogger"; /** * Max number of unique data types for which an instance of this logger can store info. Attempts * to use more distinct data type values will be rejected. * * @hide */ public static final int DATA_TYPES_ALLOWED = 15; Loading Loading @@ -301,7 +304,7 @@ public class BackupRestoreEventLogger { /** * Encapsulate logging results for a single data type. */ public static class DataTypeResult implements Parcelable { public static final class DataTypeResult implements Parcelable { @BackupRestoreDataType private final String mDataType; private int mSuccessCount; Loading @@ -309,7 +312,7 @@ public class BackupRestoreEventLogger { private final Map<String, Integer> mErrors = new HashMap<>(); private byte[] mMetadataHash; public DataTypeResult(String dataType) { public DataTypeResult(@NonNull String dataType) { mDataType = dataType; } Loading Loading @@ -358,7 +361,7 @@ public class BackupRestoreEventLogger { } @Override public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mDataType); dest.writeInt(mSuccessCount); Loading @@ -374,6 +377,7 @@ public class BackupRestoreEventLogger { dest.writeByteArray(mMetadataHash); } @NonNull public static final Parcelable.Creator<DataTypeResult> CREATOR = new Parcelable.Creator<>() { public DataTypeResult createFromParcel(Parcel in) { Loading core/tests/coretests/src/android/app/backup/BackupManagerTest.java 0 → 100644 +102 −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; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import android.app.backup.BackupAnnotations.BackupDestination; import android.app.backup.BackupAnnotations.OperationType; import android.content.Context; import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.function.ThrowingRunnable; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.IOException; @Presubmit @RunWith(AndroidJUnit4.class) public class BackupManagerTest { private BackupManager mBackupManager; @Mock Context mContext; @Before public void setUp() { MockitoAnnotations.initMocks(this); mBackupManager = new BackupManager(mContext); } @Test public void testGetBackupRestoreEventLogger_returnsBackupLoggerForBackup() { BackupAgent agent = getTestAgent(); agent.onCreate(UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.BACKUP); BackupRestoreEventLogger logger = mBackupManager.getBackupRestoreEventLogger(agent); assertThat(logger.getOperationType()).isEqualTo(OperationType.BACKUP); } @Test public void testGetBackupRestoreEventLogger_returnsRestoreLoggerForRestore() { BackupAgent agent = getTestAgent(); agent.onCreate(UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE); BackupRestoreEventLogger logger = mBackupManager.getBackupRestoreEventLogger(agent); assertThat(logger.getOperationType()).isEqualTo(OperationType.RESTORE); } @Test public void testGetBackupRestoreEventLogger_uninitialisedAgent_throwsException() { BackupAgent agent = getTestAgent(); assertThrows(IllegalStateException.class, () -> mBackupManager.getBackupRestoreEventLogger(agent)); } private static BackupAgent getTestAgent() { return new BackupAgent() { @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { } @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { } }; } } Loading
core/api/system-current.txt +28 −0 Original line number Diff line number Diff line Loading @@ -1474,6 +1474,7 @@ package android.app.backup { method @RequiresPermission(android.Manifest.permission.BACKUP) public void cancelBackups(); method @RequiresPermission(android.Manifest.permission.BACKUP) public void excludeKeysFromRestore(@NonNull String, @NonNull java.util.List<java.lang.String>); method @RequiresPermission(android.Manifest.permission.BACKUP) public long getAvailableRestoreToken(String); method @NonNull public android.app.backup.BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull android.app.backup.BackupAgent); method @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.Intent getConfigurationIntent(String); method @RequiresPermission(android.Manifest.permission.BACKUP) public String getCurrentTransport(); method @Nullable @RequiresPermission(android.Manifest.permission.BACKUP) public android.content.ComponentName getCurrentTransportComponent(); Loading Loading @@ -1592,6 +1593,33 @@ package android.app.backup { field public final long bytesTransferred; } public class BackupRestoreEventLogger { method public void logBackupMetaData(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String); method public void logItemsBackedUp(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int); method public void logItemsBackupFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String); method public void logItemsRestoreFailed(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int, @android.app.backup.BackupRestoreEventLogger.BackupRestoreError @Nullable String); method public void logItemsRestored(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, int); method public void logRestoreMetadata(@android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull String, @NonNull String); } @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreDataType { } @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface BackupRestoreEventLogger.BackupRestoreError { } public static final class BackupRestoreEventLogger.DataTypeResult implements android.os.Parcelable { ctor public BackupRestoreEventLogger.DataTypeResult(@NonNull String); method public int describeContents(); method @android.app.backup.BackupRestoreEventLogger.BackupRestoreDataType @NonNull public String getDataType(); method @NonNull public java.util.Map<java.lang.String,java.lang.Integer> getErrors(); method public int getFailCount(); method @Nullable public byte[] getMetadataHash(); method public int getSuccessCount(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator<android.app.backup.BackupRestoreEventLogger.DataTypeResult> CREATOR; } public class BackupTransport { ctor public BackupTransport(); method public int abortFullRestore();
core/java/android/app/backup/BackupManager.java +23 −0 Original line number Diff line number Diff line Loading @@ -1018,6 +1018,29 @@ public class BackupManager { } } /** * Get an instance of {@link BackupRestoreEventLogger} to report B&R related events during an * ongoing backup or restore operation. * * @param backupAgent the agent currently running a B&R operation. * * @return an instance of {@code BackupRestoreEventLogger} or {@code null} if the agent has not * finished initialisation, i.e. {@link BackupAgent#onCreate()} has not been called yet. * @throws IllegalStateException if called before the agent has finished initialisation. * * @hide */ @NonNull @SystemApi public BackupRestoreEventLogger getBackupRestoreEventLogger(@NonNull BackupAgent backupAgent) { BackupRestoreEventLogger logger = backupAgent.getBackupRestoreEventLogger(); if (logger == null) { throw new IllegalStateException("Attempting to get logger on an uninitialised " + "BackupAgent"); } return backupAgent.getBackupRestoreEventLogger(); } /* * We wrap incoming binder calls with a private class implementation that * redirects them into main-thread actions. This serializes the backup Loading
core/java/android/app/backup/BackupRestoreEventLogger.java +8 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.app.backup; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; Loading @@ -35,7 +36,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; // TODO(b/244436184): Make this @SystemApi /** * Class to log B&R stats for each data type that is backed up and restored by the calling app. * Loading @@ -46,12 +46,15 @@ import java.util.Map; * * @hide */ @SystemApi public class BackupRestoreEventLogger { private static final String TAG = "BackupRestoreEventLogger"; /** * Max number of unique data types for which an instance of this logger can store info. Attempts * to use more distinct data type values will be rejected. * * @hide */ public static final int DATA_TYPES_ALLOWED = 15; Loading Loading @@ -301,7 +304,7 @@ public class BackupRestoreEventLogger { /** * Encapsulate logging results for a single data type. */ public static class DataTypeResult implements Parcelable { public static final class DataTypeResult implements Parcelable { @BackupRestoreDataType private final String mDataType; private int mSuccessCount; Loading @@ -309,7 +312,7 @@ public class BackupRestoreEventLogger { private final Map<String, Integer> mErrors = new HashMap<>(); private byte[] mMetadataHash; public DataTypeResult(String dataType) { public DataTypeResult(@NonNull String dataType) { mDataType = dataType; } Loading Loading @@ -358,7 +361,7 @@ public class BackupRestoreEventLogger { } @Override public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mDataType); dest.writeInt(mSuccessCount); Loading @@ -374,6 +377,7 @@ public class BackupRestoreEventLogger { dest.writeByteArray(mMetadataHash); } @NonNull public static final Parcelable.Creator<DataTypeResult> CREATOR = new Parcelable.Creator<>() { public DataTypeResult createFromParcel(Parcel in) { Loading
core/tests/coretests/src/android/app/backup/BackupManagerTest.java 0 → 100644 +102 −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; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import android.app.backup.BackupAnnotations.BackupDestination; import android.app.backup.BackupAnnotations.OperationType; import android.content.Context; import android.os.ParcelFileDescriptor; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.function.ThrowingRunnable; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.IOException; @Presubmit @RunWith(AndroidJUnit4.class) public class BackupManagerTest { private BackupManager mBackupManager; @Mock Context mContext; @Before public void setUp() { MockitoAnnotations.initMocks(this); mBackupManager = new BackupManager(mContext); } @Test public void testGetBackupRestoreEventLogger_returnsBackupLoggerForBackup() { BackupAgent agent = getTestAgent(); agent.onCreate(UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.BACKUP); BackupRestoreEventLogger logger = mBackupManager.getBackupRestoreEventLogger(agent); assertThat(logger.getOperationType()).isEqualTo(OperationType.BACKUP); } @Test public void testGetBackupRestoreEventLogger_returnsRestoreLoggerForRestore() { BackupAgent agent = getTestAgent(); agent.onCreate(UserHandle.SYSTEM, BackupDestination.CLOUD, OperationType.RESTORE); BackupRestoreEventLogger logger = mBackupManager.getBackupRestoreEventLogger(agent); assertThat(logger.getOperationType()).isEqualTo(OperationType.RESTORE); } @Test public void testGetBackupRestoreEventLogger_uninitialisedAgent_throwsException() { BackupAgent agent = getTestAgent(); assertThrows(IllegalStateException.class, () -> mBackupManager.getBackupRestoreEventLogger(agent)); } private static BackupAgent getTestAgent() { return new BackupAgent() { @Override public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data, ParcelFileDescriptor newState) throws IOException { } @Override public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) throws IOException { } }; } }