Pass operation type via BackupManagerMonitor#onEvent

Events sent via BackupManagerMonitor don't contain the operation type
they're associated with (backup / restore) making them useless for
logging and debugging in some cases.

Bug: 279941227
Test: atest FrameworksMockingServicesTest
Change-Id: I8450a2404a0e4a0c4d82b62980cda1e5639f424f
This commit is contained in:
Ruslan Tkhakokhov
2023-04-27 21:13:02 +00:00
parent 64c27756ba
commit 97853abf6e
7 changed files with 101 additions and 22 deletions

View File

@@ -207,6 +207,12 @@ oneway interface IBackupAgent {
void getLoggerResults(
in AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> resultsFuture);
/**
* Provides the operation type (backup or restore) the agent is created for. See
* {@link android.app.backup.BackupAnnotations.OperationType}.
*/
void getOperationType(in AndroidFuture<int> operationTypeFuture);
/**
* Clears the logs accumulated by the BackupAgent during a backup or restore operation.
*/

View File

@@ -1352,6 +1352,12 @@ public abstract class BackupAgent extends ContextWrapper {
}
}
@Override
public void getOperationType(
AndroidFuture<Integer> in) {
in.complete(mLogger == null ? OperationType.UNKNOWN : mLogger.getOperationType());
}
@Override
public void clearBackupRestoreEventLogger() {
final long ident = Binder.clearCallingIdentity();

View File

@@ -17,6 +17,7 @@
package android.app.backup;
import android.annotation.SystemApi;
import android.app.backup.BackupAnnotations.OperationType;
import android.os.Bundle;
/**
@@ -136,6 +137,13 @@ public class BackupManagerMonitor {
public static final String EXTRA_LOG_AGENT_LOGGING_RESULTS =
"android.app.backup.extra.LOG_AGENT_LOGGING_RESULTS";
/**
* The operation type this log is associated with. See {@link OperationType}.
*
* @hide
*/
public static final String EXTRA_LOG_OPERATION_TYPE = "android.app.backup.extra.OPERATION_TYPE";
// TODO complete this list with all log messages. And document properly.
public static final int LOG_EVENT_ID_FULL_BACKUP_CANCEL = 4;
public static final int LOG_EVENT_ID_ILLEGAL_KEY = 5;

View File

@@ -46,6 +46,7 @@ import android.app.IActivityManager;
import android.app.IBackupAgent;
import android.app.PendingIntent;
import android.app.backup.BackupAgent;
import android.app.backup.BackupAnnotations;
import android.app.backup.BackupAnnotations.BackupDestination;
import android.app.backup.BackupManager;
import android.app.backup.BackupManagerMonitor;
@@ -3066,7 +3067,8 @@ public class UserBackupManagerService {
/* caller */ "BMS.reportDelayedRestoreResult");
IBackupManagerMonitor monitor = transportClient.getBackupManagerMonitor();
BackupManagerMonitorUtils.sendAgentLoggingResults(monitor, packageInfo, results);
BackupManagerMonitorUtils.sendAgentLoggingResults(monitor, packageInfo, results,
BackupAnnotations.OperationType.RESTORE);
} catch (NameNotFoundException | TransportNotAvailableException
| TransportNotRegisteredException | RemoteException e) {
Slog.w(TAG, "Failed to send delayed restore logs: " + e);

View File

@@ -18,6 +18,7 @@ package com.android.server.backup.utils;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_AGENT_LOGGING_RESULTS;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS;
@@ -27,6 +28,7 @@ import static com.android.server.backup.BackupManagerService.TAG;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.IBackupAgent;
import android.app.backup.BackupAnnotations.OperationType;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.IBackupManagerMonitor;
@@ -122,9 +124,13 @@ public class BackupManagerMonitorUtils {
try {
AndroidFuture<List<DataTypeResult>> resultsFuture =
new AndroidFuture<>();
AndroidFuture<Integer> operationTypeFuture = new AndroidFuture<>();
agent.getLoggerResults(resultsFuture);
agent.getOperationType(operationTypeFuture);
return sendAgentLoggingResults(monitor, pkg,
resultsFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
resultsFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS),
operationTypeFuture.get(AGENT_LOGGER_RESULTS_TIMEOUT_MILLIS,
TimeUnit.MILLISECONDS));
} catch (TimeoutException e) {
Slog.w(TAG, "Timeout while waiting to retrieve logging results from agent", e);
} catch (Exception e) {
@@ -134,10 +140,12 @@ public class BackupManagerMonitorUtils {
}
public static IBackupManagerMonitor sendAgentLoggingResults(
@NonNull IBackupManagerMonitor monitor, PackageInfo pkg, List<DataTypeResult> results) {
@NonNull IBackupManagerMonitor monitor, PackageInfo pkg, List<DataTypeResult> results,
@OperationType int operationType) {
Bundle loggerResultsBundle = new Bundle();
loggerResultsBundle.putParcelableList(
EXTRA_LOG_AGENT_LOGGING_RESULTS, results);
loggerResultsBundle.putInt(EXTRA_LOG_OPERATION_TYPE, operationType);
return monitorEvent(
monitor,
LOG_EVENT_ID_AGENT_LOGGING_RESULTS,

View File

@@ -31,6 +31,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.when;
import android.app.backup.BackupAgent;
import android.app.backup.BackupAnnotations;
import android.app.backup.BackupAnnotations.BackupDestination;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.IBackupManagerMonitor;
@@ -246,7 +247,8 @@ public class UserBackupManagerServiceTest {
mService.reportDelayedRestoreResult(TEST_PACKAGE, results);
verify(() -> BackupManagerMonitorUtils.sendAgentLoggingResults(
eq(mBackupManagerMonitor), eq(packageInfo), eq(results)));
eq(mBackupManagerMonitor), eq(packageInfo), eq(results), eq(
BackupAnnotations.OperationType.RESTORE)));
}
private static PackageInfo getPackageInfo(String packageName) {

View File

@@ -21,6 +21,7 @@ import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_ID;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_LONG_VERSION;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_OPERATION_TYPE;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT;
import static android.app.backup.BackupManagerMonitor.LOG_EVENT_ID_AGENT_LOGGING_RESULTS;
@@ -33,6 +34,8 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.IBackupAgent;
import android.app.backup.BackupAnnotations;
import android.app.backup.BackupAnnotations.OperationType;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.IBackupManagerMonitor;
@@ -155,50 +158,94 @@ public class BackupManagerMonitorUtilsTest {
}
@Test
public void monitorAgentLoggingResults_fillsBundleCorrectly() throws Exception {
public void monitorAgentLoggingResults_onBackup_fillsBundleCorrectly() throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = "test.package";
// Mock an agent that returns a logging result.
IBackupAgent agent = spy(IBackupAgent.class);
List<BackupRestoreEventLogger.DataTypeResult> loggingResults = new ArrayList<>();
loggingResults.add(new BackupRestoreEventLogger.DataTypeResult("testLoggingResult"));
doAnswer(
invocation -> {
AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> in =
invocation.getArgument(0);
in.complete(loggingResults);
return null;
})
.when(agent)
.getLoggerResults(any());
IBackupAgent agent = setUpLoggingAgentForOperation(OperationType.BACKUP);
IBackupManagerMonitor monitor =
BackupManagerMonitorUtils.monitorAgentLoggingResults(
mMonitorMock, packageInfo, agent);
assertCorrectBundleSentToMonitor(monitor);
assertCorrectBundleSentToMonitor(monitor, OperationType.BACKUP);
}
@Test
public void sendAgentLoggingResults_fillsBundleCorrectly() throws Exception {
public void monitorAgentLoggingResults_onRestore_fillsBundleCorrectly() throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = "test.package";
// Mock an agent that returns a logging result.
IBackupAgent agent = setUpLoggingAgentForOperation(OperationType.RESTORE);
IBackupManagerMonitor monitor =
BackupManagerMonitorUtils.monitorAgentLoggingResults(
mMonitorMock, packageInfo, agent);
assertCorrectBundleSentToMonitor(monitor, OperationType.RESTORE);
}
private IBackupAgent setUpLoggingAgentForOperation(@OperationType int operationType)
throws Exception {
IBackupAgent agent = spy(IBackupAgent.class);
List<BackupRestoreEventLogger.DataTypeResult> loggingResults = new ArrayList<>();
loggingResults.add(new BackupRestoreEventLogger.DataTypeResult("testLoggingResult"));
doAnswer(
invocation -> {
AndroidFuture<List<BackupRestoreEventLogger.DataTypeResult>> in =
invocation.getArgument(0);
in.complete(loggingResults);
return null;
})
.when(agent)
.getLoggerResults(any());
doAnswer(
invocation -> {
AndroidFuture<Integer> in = invocation.getArgument(0);
in.complete(operationType);
return null;
})
.when(agent)
.getOperationType(any());
return agent;
}
@Test
public void sendAgentLoggingResults_onBackup_fillsBundleCorrectly() throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = "test.package";
List<BackupRestoreEventLogger.DataTypeResult> loggingResults = new ArrayList<>();
loggingResults.add(new BackupRestoreEventLogger.DataTypeResult("testLoggingResult"));
IBackupManagerMonitor monitor = BackupManagerMonitorUtils.sendAgentLoggingResults(
mMonitorMock, packageInfo, loggingResults);
mMonitorMock, packageInfo, loggingResults, OperationType.BACKUP);
assertCorrectBundleSentToMonitor(monitor);
assertCorrectBundleSentToMonitor(monitor, OperationType.BACKUP);
}
private void assertCorrectBundleSentToMonitor(IBackupManagerMonitor monitor) throws Exception {
@Test
public void sendAgentLoggingResults_onRestore_fillsBundleCorrectly() throws Exception {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = "test.package";
List<BackupRestoreEventLogger.DataTypeResult> loggingResults = new ArrayList<>();
loggingResults.add(new BackupRestoreEventLogger.DataTypeResult("testLoggingResult"));
IBackupManagerMonitor monitor = BackupManagerMonitorUtils.sendAgentLoggingResults(
mMonitorMock, packageInfo, loggingResults, OperationType.RESTORE);
assertCorrectBundleSentToMonitor(monitor, OperationType.RESTORE);
}
private void assertCorrectBundleSentToMonitor(IBackupManagerMonitor monitor,
@OperationType int operationType) throws Exception {
assertThat(monitor).isEqualTo(mMonitorMock);
ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
verify(mMonitorMock).onEvent(bundleCaptor.capture());
Bundle eventBundle = bundleCaptor.getValue();
assertThat(eventBundle.getInt(EXTRA_LOG_OPERATION_TYPE))
.isEqualTo(operationType);
assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_ID))
.isEqualTo(LOG_EVENT_ID_AGENT_LOGGING_RESULTS);
assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_CATEGORY))