Add monitoring to backup in BackupManager.

This is the first CL of many that will add instumentation to
backup/restore operation in the BackupManager. For more details please
point to:
https://docs.google.com/document/d/1sUboR28LjkT1wRXOwVOV3tLo0qisiCvzxIGmzCVEjbI/edit#
This first Cl introduces 3 events that we sent to the monitor.

Test: ag/1858962 (same topic)

BUG: 34873525

Change-Id: I6c338b6fd9f4d7c8670dac201897250b6b170677
This commit is contained in:
Stefanot
2017-01-27 12:03:53 +00:00
parent 5706614868
commit b1f573dca3
9 changed files with 237 additions and 28 deletions

View File

@ -104,6 +104,7 @@ LOCAL_SRC_FILES += \
core/java/android/app/trust/ITrustListener.aidl \
core/java/android/app/backup/IBackupManager.aidl \
core/java/android/app/backup/IBackupObserver.aidl \
core/java/android/app/backup/IBackupManagerMonitor.aidl \
core/java/android/app/backup/IFullBackupRestoreObserver.aidl \
core/java/android/app/backup/IRestoreObserver.aidl \
core/java/android/app/backup/IRestoreSession.aidl \

View File

@ -6895,7 +6895,7 @@ package android.app.backup {
method public boolean isBackupEnabled();
method public java.lang.String[] listAllTransports();
method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver);
method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver, int);
method public int requestBackup(java.lang.String[], android.app.backup.BackupObserver, android.app.backup.BackupManagerMonitor, int);
method public int requestRestore(android.app.backup.RestoreObserver);
method public deprecated java.lang.String selectBackupTransport(java.lang.String);
method public void selectBackupTransport(android.content.ComponentName, android.app.backup.SelectBackupTransportCallback);
@ -6914,6 +6914,21 @@ package android.app.backup {
field public static final int SUCCESS = 0; // 0x0
}
public class BackupManagerMonitor {
ctor public BackupManagerMonitor();
method public void onEvent(android.os.Bundle);
field public static final java.lang.String EXTRA_LOG_EVENT_CATEGORY = "android.app.backup.extra.LOG_EVENT_CATEGORY";
field public static final java.lang.String EXTRA_LOG_EVENT_ID = "android.app.backup.extra.LOG_EVENT_ID";
field public static final java.lang.String EXTRA_LOG_EVENT_PACKAGE_NAME = "android.app.backup.extra.LOG_EVENT_PACKAGE_NAME";
field public static final java.lang.String EXTRA_LOG_EVENT_PACKAGE_VERSION = "android.app.backup.extra.LOG_EVENT_PACKAGE_VERSION";
field public static final int LOG_EVENT_CATEGORY_AGENT = 2; // 0x2
field public static final int LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY = 3; // 0x3
field public static final int LOG_EVENT_CATEGORY_TRANSPORT = 1; // 0x1
field public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4; // 0x4
field public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21; // 0x15
field public static final int LOG_EVENT_ID_NO_PACKAGES = 49; // 0x31
}
public abstract class BackupObserver {
ctor public BackupObserver();
method public void backupFinished(int);

View File

@ -17,6 +17,7 @@
package com.android.commands.bmgr;
import android.app.backup.BackupManager;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupObserver;
@ -312,8 +313,9 @@ public final class Bmgr {
}
try {
BackupObserver observer = new BackupObserver();
// TODO: implement monitor here?
int err = mBmgr.requestBackup(packages.toArray(new String[packages.size()]), observer,
flags);
null, flags);
if (err == 0) {
// Off and running -- wait for the backup to complete
observer.waitForCompletion();

View File

@ -19,6 +19,7 @@ package android.app.backup;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
@ -556,7 +557,7 @@ public class BackupManager {
*/
@SystemApi
public int requestBackup(String[] packages, BackupObserver observer) {
return requestBackup(packages, observer, 0);
return requestBackup(packages, observer, null, 0);
}
/**
@ -570,20 +571,26 @@ public class BackupManager {
* @param packages List of package names to backup.
* @param observer The {@link BackupObserver} to receive callbacks during the backup
* operation. Could be {@code null}.
* @param monitor The {@link BackupManagerMonitorWrapper} to receive callbacks of important
* events during the backup operation. Could be {@code null}.
* @param flags {@link #FLAG_NON_INCREMENTAL_BACKUP}.
* @return {@link BackupManager#SUCCESS} on success; nonzero on error.
* @throws IllegalArgumentException on null or empty {@code packages} param.
* @hide
*/
@SystemApi
public int requestBackup(String[] packages, BackupObserver observer, int flags) {
public int requestBackup(String[] packages, BackupObserver observer,
BackupManagerMonitor monitor, int flags) {
checkServiceBinder();
if (sService != null) {
try {
BackupObserverWrapper observerWrapper = observer == null
? null
: new BackupObserverWrapper(mContext, observer);
return sService.requestBackup(packages, observerWrapper, flags);
BackupManagerMonitorWrapper monitorWrapper = monitor == null
? null
: new BackupManagerMonitorWrapper(monitor);
return sService.requestBackup(packages, observerWrapper, monitorWrapper, flags);
} catch (RemoteException e) {
Log.e(TAG, "requestBackup() couldn't connect");
}
@ -680,4 +687,18 @@ public class BackupManager {
});
}
}
private class BackupManagerMonitorWrapper extends IBackupManagerMonitor.Stub {
final BackupManagerMonitor mMonitor;
BackupManagerMonitorWrapper(BackupManagerMonitor monitor) {
mMonitor = monitor;
}
@Override
public void onEvent(final Bundle event) throws RemoteException {
mMonitor.onEvent(event);
}
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2017 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 android.annotation.SystemApi;
import android.os.Bundle;
/**
* Callback class for receiving important events during backup/restore operations.
* Events consist mostly of errors and exceptions, giving detailed reason on why a restore/backup
* failed or any time BackupManager makes an important decision.
* On the other hand {@link BackupObserver} will give a failure/success view without
* getting into details why. This callback runs on the thread it was called on because it can get
* a bit spammy.
* These callbacks will run on the binder thread.
*
* @hide
*/
@SystemApi
public class BackupManagerMonitor {
// Logging constants for BackupManagerMonitor
public static final int LOG_EVENT_CATEGORY_TRANSPORT = 1;
public static final int LOG_EVENT_CATEGORY_AGENT = 2;
public static final int LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY = 3;
/** string : the package name */
public static final String EXTRA_LOG_EVENT_PACKAGE_NAME =
"android.app.backup.extra.LOG_EVENT_PACKAGE_NAME";
/** int : the versionCode of the package named by EXTRA_LOG_EVENT_PACKAGE_NAME */
public static final String EXTRA_LOG_EVENT_PACKAGE_VERSION =
"android.app.backup.extra.LOG_EVENT_PACKAGE_VERSION";
/** int : the id of the log message, will be a unique identifier */
public static final String EXTRA_LOG_EVENT_ID = "android.app.backup.extra.LOG_EVENT_ID";
/**
* int : category will be one of
* { LOG_EVENT_CATEGORY_TRANSPORT,
* LOG_EVENT_CATEGORY_AGENT,
* LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY}.
*/
public static final String EXTRA_LOG_EVENT_CATEGORY =
"android.app.backup.extra.LOG_EVENT_CATEGORY";
// TODO complete this list with all log messages. And document properly.
public static final int LOG_EVENT_ID_FULL_BACKUP_TIMEOUT = 4;
public static final int LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT = 21;
public static final int LOG_EVENT_ID_NO_PACKAGES = 49;
/**
* This method will be called each time something important happens on BackupManager.
*
* @param event bundle will contain data about event:
* - event id, not optional, a unique identifier for each event.
* - package name, optional, the current package we're backing up/restoring if applicable.
* - package version, optional, the current package version we're backing up/restoring
* if applicable.
* - category of event, not optional, one of
* { LOG_EVENT_CATEGORY_TRANSPORT,
* LOG_EVENT_CATEGORY_AGENT,
* LOG_EVENT_CATEGORY_BACKUP_MANAGER_POLICY}
*
*/
public void onEvent(Bundle event) {
}
}

View File

@ -17,6 +17,7 @@
package android.app.backup;
import android.app.backup.IBackupObserver;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
@ -376,9 +377,13 @@ interface IBackupManager {
* @param observer The {@link BackupObserver} to receive callbacks during the backup
* operation.
*
* @param monitor the {@link BackupManagerMonitor} to receive callbacks about important events
* during the backup operation.
*
* @param flags {@link BackupManager#FLAG_NON_INCREMENTAL_BACKUP}.
*
* @return Zero on success; nonzero on error.
*/
int requestBackup(in String[] packages, IBackupObserver observer, int flags);
int requestBackup(in String[] packages, IBackupObserver observer, IBackupManagerMonitor monitor,
int flags);
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2017 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 android.os.Bundle;
/**
* Callback class for receiving important events during backup/restore operations.
* These callbacks will run on the binder thread.
*
* @hide
*/
oneway interface IBackupManagerMonitor {
/**
* This method will be called each time something important happens on BackupManager.
*
* @param event bundle will contain data about event, like package name, package version etc.
*/
void onEvent(in Bundle event);
}

View File

@ -30,18 +30,20 @@ import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManager;
import android.app.backup.BackupManagerMonitor;
import android.app.backup.BackupProgress;
import android.app.backup.BackupTransport;
import android.app.backup.FullBackup;
import android.app.backup.FullBackupDataOutput;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupObserver;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.app.backup.IBackupManager;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.app.backup.SelectBackupTransportCallback;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
@ -427,6 +429,7 @@ public class BackupManagerService {
public IBackupTransport transport;
public String dirName;
public IRestoreObserver observer;
public IBackupManagerMonitor monitor;
public long token;
public PackageInfo pkgInfo;
public int pmToken; // in post-install restore, the PM's token for this transaction
@ -565,17 +568,19 @@ public class BackupManagerService {
public ArrayList<String> kvPackages;
public ArrayList<String> fullPackages;
public IBackupObserver observer;
public IBackupManagerMonitor monitor;
public boolean userInitiated;
public boolean nonIncrementalBackup;
BackupParams(IBackupTransport transport, String dirName, ArrayList<String> kvPackages,
ArrayList<String> fullPackages, IBackupObserver observer, boolean userInitiated,
boolean nonIncrementalBackup) {
ArrayList<String> fullPackages, IBackupObserver observer,
IBackupManagerMonitor monitor,boolean userInitiated, boolean nonIncrementalBackup) {
this.transport = transport;
this.dirName = dirName;
this.kvPackages = kvPackages;
this.fullPackages = fullPackages;
this.observer = observer;
this.monitor = monitor;
this.userInitiated = userInitiated;
this.nonIncrementalBackup = nonIncrementalBackup;
}
@ -785,8 +790,8 @@ public class BackupManagerService {
// Spin up a backup state sequence and set it running
try {
String dirName = transport.transportDirName();
PerformBackupTask pbt = new PerformBackupTask(transport, dirName,
queue, oldJournal, null, null, false, false /* nonIncremental */);
PerformBackupTask pbt = new PerformBackupTask(transport, dirName, queue,
oldJournal, null, null, null, false, false /* nonIncremental */);
Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
sendMessage(pbtMessage);
} catch (Exception e) {
@ -861,8 +866,8 @@ public class BackupManagerService {
RestoreParams params = (RestoreParams)msg.obj;
Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
BackupRestoreTask task = new PerformUnifiedRestoreTask(params.transport,
params.observer, params.token, params.pkgInfo, params.pmToken,
params.isSystemRestore, params.filterSet);
params.observer, params.monitor, params.token, params.pkgInfo,
params.pmToken, params.isSystemRestore, params.filterSet);
Message restoreMsg = obtainMessage(MSG_BACKUP_RESTORE_STEP, task);
sendMessage(restoreMsg);
break;
@ -1025,7 +1030,7 @@ public class BackupManagerService {
mWakelock.acquire();
PerformBackupTask pbt = new PerformBackupTask(params.transport, params.dirName,
kvQueue, null, params.observer, params.fullPackages, true,
kvQueue, null, params.observer, params.monitor, params.fullPackages, true,
params.nonIncrementalBackup);
Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
sendMessage(pbtMessage);
@ -2281,11 +2286,18 @@ public class BackupManagerService {
}
public int requestBackup(String[] packages, IBackupObserver observer, int flags) {
return requestBackup(packages, observer, null, flags);
}
public int requestBackup(String[] packages, IBackupObserver observer,
IBackupManagerMonitor monitor, int flags) {
mContext.enforceCallingPermission(android.Manifest.permission.BACKUP, "requestBackup");
if (packages == null || packages.length < 1) {
Slog.e(TAG, "No packages named for backup request");
sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
monitor = monitorEvent(monitor, BackupManagerMonitor.LOG_EVENT_ID_NO_PACKAGES,
null, BackupManagerMonitor.LOG_EVENT_CATEGORY_TRANSPORT);
throw new IllegalArgumentException("No packages are provided for backup");
}
@ -2340,7 +2352,7 @@ public class BackupManagerService {
Message msg = mBackupHandler.obtainMessage(MSG_REQUEST_BACKUP);
msg.obj = new BackupParams(transport, dirName, kvBackupList, fullBackupList, observer,
true, nonIncrementalBackup);
monitor, true, nonIncrementalBackup);
mBackupHandler.sendMessage(msg);
return BackupManager.SUCCESS;
}
@ -2456,6 +2468,7 @@ public class BackupManagerService {
BackupState mCurrentState;
ArrayList<String> mPendingFullBackups;
IBackupObserver mObserver;
IBackupManagerMonitor mMonitor;
// carried information about the current in-flight operation
IBackupAgent mAgentBinder;
@ -2473,12 +2486,13 @@ public class BackupManagerService {
public PerformBackupTask(IBackupTransport transport, String dirName,
ArrayList<BackupRequest> queue, File journal, IBackupObserver observer,
ArrayList<String> pendingFullBackups, boolean userInitiated,
boolean nonIncremental) {
IBackupManagerMonitor monitor, ArrayList<String> pendingFullBackups,
boolean userInitiated, boolean nonIncremental) {
mTransport = transport;
mOriginalQueue = queue;
mJournal = journal;
mObserver = observer;
mMonitor = monitor;
mPendingFullBackups = pendingFullBackups;
mUserInitiated = userInitiated;
mNonIncremental = nonIncremental;
@ -2838,7 +2852,7 @@ public class BackupManagerService {
PerformFullTransportBackupTask task =
new PerformFullTransportBackupTask(/*fullBackupRestoreObserver*/ null,
fullBackups, /*updateSchedule*/ false, /*runningJob*/ null, latch,
mObserver, mUserInitiated);
mObserver, mMonitor, mUserInitiated);
// Acquiring wakelock for PerformFullTransportBackupTask before its start.
mWakelock.acquire();
(new Thread(task, "full-transport-requested")).start();
@ -3215,6 +3229,9 @@ public class BackupManagerService {
Slog.e(TAG, "Timeout backing up " + mCurrentPackage.packageName);
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, mCurrentPackage.packageName,
"timeout");
mMonitor = monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_KEY_VALUE_BACKUP_TIMEOUT,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT);
addBackupTrace("timeout of " + mCurrentPackage.packageName);
agentErrorCleanup();
dataChangedImpl(mCurrentPackage.packageName);
@ -4197,17 +4214,19 @@ public class BackupManagerService {
class PerformFullTransportBackupTask extends FullBackupTask {
static final String TAG = "PFTBT";
ArrayList<PackageInfo> mPackages;
PackageInfo mCurrentPackage;
boolean mUpdateSchedule;
CountDownLatch mLatch;
AtomicBoolean mKeepRunning; // signal from job scheduler
FullBackupJob mJob; // if a scheduled job needs to be finished afterwards
IBackupObserver mBackupObserver;
IBackupManagerMonitor mMonitor;
boolean mUserInitiated;
PerformFullTransportBackupTask(IFullBackupRestoreObserver observer,
String[] whichPackages, boolean updateSchedule,
FullBackupJob runningJob, CountDownLatch latch, IBackupObserver backupObserver,
boolean userInitiated) {
IBackupManagerMonitor monitor, boolean userInitiated) {
super(observer);
mUpdateSchedule = updateSchedule;
mLatch = latch;
@ -4215,12 +4234,14 @@ public class BackupManagerService {
mJob = runningJob;
mPackages = new ArrayList<PackageInfo>(whichPackages.length);
mBackupObserver = backupObserver;
mMonitor = monitor;
mUserInitiated = userInitiated;
for (String pkg : whichPackages) {
try {
PackageInfo info = mPackageManager.getPackageInfo(pkg,
PackageManager.GET_SIGNATURES);
mCurrentPackage = info;
if (!appIsEligibleForBackup(info.applicationInfo)) {
// Cull any packages that have indicated that backups are not permitted,
// that run as system-domain uids but do not define their own backup agents,
@ -4732,6 +4753,9 @@ public class BackupManagerService {
if (DEBUG) {
Slog.w(TAG, "Full backup timeout of " + mTarget.packageName);
}
mMonitor = monitorEvent(mMonitor,
BackupManagerMonitor.LOG_EVENT_ID_FULL_BACKUP_TIMEOUT,
mCurrentPackage, BackupManagerMonitor.LOG_EVENT_CATEGORY_AGENT);
tearDownAgentAndKill(mTarget.applicationInfo);
}
}
@ -4993,7 +5017,7 @@ public class BackupManagerService {
CountDownLatch latch = new CountDownLatch(1);
String[] pkg = new String[] {entry.packageName};
mRunningFullBackupTask = new PerformFullTransportBackupTask(null, pkg, true,
scheduledJob, latch, null, false /* userInitiated */);
scheduledJob, latch, null, null, false /* userInitiated */);
// Acquiring wakelock for PerformFullTransportBackupTask before its start.
mWakelock.acquire();
(new Thread(mRunningFullBackupTask)).start();
@ -7825,8 +7849,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Invariant: mWakelock is already held, and this task is responsible for
// releasing it at the end of the restore operation.
PerformUnifiedRestoreTask(IBackupTransport transport, IRestoreObserver observer,
long restoreSetToken, PackageInfo targetPackage, int pmToken,
boolean isFullSystemRestore, String[] filterSet) {
IBackupManagerMonitor monitor, long restoreSetToken, PackageInfo targetPackage,
int pmToken, boolean isFullSystemRestore, String[] filterSet) {
mState = UnifiedRestoreState.INITIAL;
mStartRealtime = SystemClock.elapsedRealtime();
@ -9247,7 +9271,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
try {
CountDownLatch latch = new CountDownLatch(1);
PerformFullTransportBackupTask task = new PerformFullTransportBackupTask(null,
pkgNames, false, null, latch, null, false /* userInitiated */);
pkgNames, false, null, latch, null, null, false /* userInitiated */);
// Acquiring wakelock for PerformFullTransportBackupTask before its start.
mWakelock.acquire();
(new Thread(task, "full-transport-master")).start();
@ -10436,4 +10460,28 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
}
}
private static IBackupManagerMonitor monitorEvent(IBackupManagerMonitor monitor, int id,
PackageInfo pkg, int category) {
if (monitor != null) {
try {
Bundle bundle = new Bundle();
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_ID, id);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY, category);
if (pkg != null) {
bundle.putString(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME,
pkg.packageName);
bundle.putInt(BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION,
pkg.versionCode);
}
monitor.onEvent(bundle);
return monitor;
} catch(RemoteException e) {
if (DEBUG) {
Slog.w(TAG, "backup manager monitor went away");
}
}
}
return null;
}
}

View File

@ -18,6 +18,7 @@ package com.android.server.backup;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupObserver;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
@ -355,10 +356,10 @@ public class Trampoline extends IBackupManager.Stub {
}
@Override
public int requestBackup(String[] packages, IBackupObserver observer, int flags)
throws RemoteException {
public int requestBackup(String[] packages, IBackupObserver observer,
IBackupManagerMonitor monitor, int flags) throws RemoteException {
BackupManagerService svc = mService;
return (svc != null) ? svc.requestBackup(packages, observer, flags) : null;
return (svc != null) ? svc.requestBackup(packages, observer, monitor, flags) : null;
}
@Override