Merge "Quota exceeded API in BackupAgent"
This commit is contained in:
committed by
Android (Google) Code Review
commit
7200364e8d
@@ -6105,6 +6105,7 @@ package android.app.backup {
|
||||
method public void onCreate();
|
||||
method public void onDestroy();
|
||||
method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException;
|
||||
method public void onQuotaExceeded(long, long);
|
||||
method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
|
||||
method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException;
|
||||
method public void onRestoreFinished();
|
||||
|
||||
@@ -6254,6 +6254,7 @@ package android.app.backup {
|
||||
method public void onCreate();
|
||||
method public void onDestroy();
|
||||
method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException;
|
||||
method public void onQuotaExceeded(long, long);
|
||||
method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
|
||||
method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException;
|
||||
method public void onRestoreFinished();
|
||||
@@ -6316,6 +6317,7 @@ package android.app.backup {
|
||||
field public static final int ERROR_PACKAGE_NOT_FOUND = -2002; // 0xfffff82e
|
||||
field public static final int ERROR_TRANSPORT_ABORTED = -1000; // 0xfffffc18
|
||||
field public static final int ERROR_TRANSPORT_PACKAGE_REJECTED = -1002; // 0xfffffc16
|
||||
field public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED = -1005; // 0xfffffc13
|
||||
field public static final int SUCCESS = 0; // 0x0
|
||||
}
|
||||
|
||||
@@ -6348,6 +6350,7 @@ package android.app.backup {
|
||||
method public int finishBackup();
|
||||
method public void finishRestore();
|
||||
method public android.app.backup.RestoreSet[] getAvailableRestoreSets();
|
||||
method public long getBackupQuota(java.lang.String, boolean);
|
||||
method public android.os.IBinder getBinder();
|
||||
method public long getCurrentRestoreSet();
|
||||
method public int getNextFullRestoreDataChunk(android.os.ParcelFileDescriptor);
|
||||
@@ -6373,6 +6376,7 @@ package android.app.backup {
|
||||
field public static final int TRANSPORT_NOT_INITIALIZED = -1001; // 0xfffffc17
|
||||
field public static final int TRANSPORT_OK = 0; // 0x0
|
||||
field public static final int TRANSPORT_PACKAGE_REJECTED = -1002; // 0xfffffc16
|
||||
field public static final int TRANSPORT_QUOTA_EXCEEDED = -1005; // 0xfffffc13
|
||||
}
|
||||
|
||||
public class FileBackupHelper extends android.app.backup.FileBackupHelperBase implements android.app.backup.BackupHelper {
|
||||
|
||||
@@ -6107,6 +6107,7 @@ package android.app.backup {
|
||||
method public void onCreate();
|
||||
method public void onDestroy();
|
||||
method public void onFullBackup(android.app.backup.FullBackupDataOutput) throws java.io.IOException;
|
||||
method public void onQuotaExceeded(long, long);
|
||||
method public abstract void onRestore(android.app.backup.BackupDataInput, int, android.os.ParcelFileDescriptor) throws java.io.IOException;
|
||||
method public void onRestoreFile(android.os.ParcelFileDescriptor, long, java.io.File, int, long, long) throws java.io.IOException;
|
||||
method public void onRestoreFinished();
|
||||
|
||||
@@ -104,6 +104,27 @@ oneway interface IBackupAgent {
|
||||
*/
|
||||
void doMeasureFullBackup(int token, IBackupManager callbackBinder);
|
||||
|
||||
/**
|
||||
* Tells the application agent that the backup data size exceeded current transport quota.
|
||||
* Later calls to {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
|
||||
* and {@link #onFullBackup(FullBackupDataOutput)} could use this information
|
||||
* to reduce backup size under the limit.
|
||||
* However, the quota can change, so do not assume that the value passed in here is absolute,
|
||||
* similarly all subsequent backups should not be restricted to this size.
|
||||
* This callback will be invoked before data has been put onto the wire in a preflight check,
|
||||
* so it is relatively inexpensive to hit your quota.
|
||||
* Apps that hit quota repeatedly without dealing with it can be subject to having their backup
|
||||
* schedule reduced.
|
||||
* The {@code quotaBytes} is a loose guideline b/c of metadata added by the backupmanager
|
||||
* so apps should be more aggressive in trimming their backup set.
|
||||
*
|
||||
* @param backupDataBytes Expected or already processed amount of data.
|
||||
* Could be less than total backup size if backup process was interrupted
|
||||
* before finish of processing all backup data.
|
||||
* @param quotaBytes Current amount of backup data that is allowed for the app.
|
||||
*/
|
||||
void doQuotaExceeded(long backupDataBytes, long quotaBytes);
|
||||
|
||||
/**
|
||||
* Restore a single "file" to the application. The file was typically obtained from
|
||||
* a full-backup dataset. The agent reads 'size' bytes of file content
|
||||
|
||||
@@ -381,6 +381,28 @@ public abstract class BackupAgent extends ContextWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells the application agent that the backup data size exceeded current transport quota.
|
||||
* Later calls to {@link #onBackup(ParcelFileDescriptor, BackupDataOutput, ParcelFileDescriptor)}
|
||||
* and {@link #onFullBackup(FullBackupDataOutput)} could use this information
|
||||
* to reduce backup size under the limit.
|
||||
* However, the quota can change, so do not assume that the value passed in here is absolute,
|
||||
* similarly all subsequent backups should not be restricted to this size.
|
||||
* This callback will be invoked before data has been put onto the wire in a preflight check,
|
||||
* so it is relatively inexpensive to hit your quota.
|
||||
* Apps that hit quota repeatedly without dealing with it can be subject to having their backup
|
||||
* schedule reduced.
|
||||
* The {@code quotaBytes} is a loose guideline b/c of metadata added by the backupmanager
|
||||
* so apps should be more aggressive in trimming their backup set.
|
||||
*
|
||||
* @param backupDataBytes Expected or already processed amount of data.
|
||||
* Could be less than total backup size if backup process was interrupted
|
||||
* before finish of processing all backup data.
|
||||
* @param quotaBytes Current amount of backup data that is allowed for the app.
|
||||
*/
|
||||
public void onQuotaExceeded(long backupDataBytes, long quotaBytes) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the xml yielded any <include/> tag for the provided <code>domainToken</code>.
|
||||
* If so, perform a {@link #fullBackupFileTree} which backs up the file or recurses if the path
|
||||
@@ -955,6 +977,21 @@ public abstract class BackupAgent extends ContextWrapper {
|
||||
public void fail(String message) {
|
||||
getHandler().post(new FailRunnable(message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doQuotaExceeded(long backupDataBytes, long quotaBytes) {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
BackupAgent.this.onQuotaExceeded(backupDataBytes, quotaBytes);
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "onQuotaExceeded(" + BackupAgent.this.getClass().getName() + ") threw",
|
||||
e);
|
||||
throw e;
|
||||
} finally {
|
||||
waitForSharedPrefs();
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class FailRunnable implements Runnable {
|
||||
|
||||
@@ -109,6 +109,16 @@ public class BackupManager {
|
||||
public static final int ERROR_TRANSPORT_PACKAGE_REJECTED =
|
||||
BackupTransport.TRANSPORT_PACKAGE_REJECTED;
|
||||
|
||||
/**
|
||||
* Returned when the transport reject the attempt to backup because
|
||||
* backup data size exceeded current quota limit for this package.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
public static final int ERROR_TRANSPORT_QUOTA_EXCEEDED =
|
||||
BackupTransport.TRANSPORT_QUOTA_EXCEEDED;
|
||||
|
||||
/**
|
||||
* The {@link BackupAgent} for the requested package failed for some reason
|
||||
* and didn't provide appropriate backup data.
|
||||
|
||||
@@ -49,6 +49,7 @@ public class BackupTransport {
|
||||
public static final int TRANSPORT_PACKAGE_REJECTED = -1002;
|
||||
public static final int AGENT_ERROR = -1003;
|
||||
public static final int AGENT_UNKNOWN = -1004;
|
||||
public static final int TRANSPORT_QUOTA_EXCEEDED = -1005;
|
||||
|
||||
// Indicates that operation was initiated by user, not a scheduled one.
|
||||
// Transport should ignore its own moratoriums for call with this flag set.
|
||||
@@ -494,6 +495,18 @@ public class BackupTransport {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ask the transport about current quota for backup size of the package.
|
||||
*
|
||||
* @param packageName ID of package to provide the quota.
|
||||
* @param isFullBackup If set, transport should return limit for full data backup, otherwise
|
||||
* for key-value backup.
|
||||
* @return Current limit on full data backup size in bytes.
|
||||
*/
|
||||
public long getBackupQuota(String packageName, boolean isFullBackup) {
|
||||
return Long.MAX_VALUE;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------
|
||||
// Full restore interfaces
|
||||
|
||||
@@ -676,6 +689,11 @@ public class BackupTransport {
|
||||
return BackupTransport.this.isAppEligibleForBackup(targetPackage, isFullBackup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBackupQuota(String packageName, boolean isFullBackup) {
|
||||
return BackupTransport.this.getBackupQuota(packageName, isFullBackup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) {
|
||||
return BackupTransport.this.getNextFullRestoreDataChunk(socket);
|
||||
|
||||
@@ -249,6 +249,16 @@ interface IBackupTransport {
|
||||
*/
|
||||
boolean isAppEligibleForBackup(in PackageInfo targetPackage, boolean isFullBackup);
|
||||
|
||||
/**
|
||||
* Ask the transport about current quota for backup size of the package.
|
||||
*
|
||||
* @param packageName ID of package to provide the quota.
|
||||
* @param isFullBackup If set, transport should return limit for full data backup, otherwise
|
||||
* for key-value backup.
|
||||
* @return Current limit on full data backup size in bytes.
|
||||
*/
|
||||
long getBackupQuota(String packageName, boolean isFullBackup);
|
||||
|
||||
// full restore stuff
|
||||
|
||||
/**
|
||||
|
||||
@@ -71,6 +71,9 @@ public class LocalTransport extends BackupTransport {
|
||||
// The currently-active restore set always has the same (nonzero!) token
|
||||
private static final long CURRENT_SET_TOKEN = 1;
|
||||
|
||||
// Full backup size quota is set to reasonable value.
|
||||
private static final long FULL_BACKUP_SIZE_QUOTA = 25 * 1024 * 1024;
|
||||
|
||||
private Context mContext;
|
||||
private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
|
||||
private File mCurrentSetDir = new File(mDataDir, Long.toString(CURRENT_SET_TOKEN));
|
||||
@@ -90,6 +93,7 @@ public class LocalTransport extends BackupTransport {
|
||||
private FileInputStream mSocketInputStream;
|
||||
private BufferedOutputStream mFullBackupOutputStream;
|
||||
private byte[] mFullBackupBuffer;
|
||||
private long mFullBackupSize;
|
||||
|
||||
private FileInputStream mCurFullRestoreStream;
|
||||
private FileOutputStream mFullRestoreSocketStream;
|
||||
@@ -314,8 +318,13 @@ public class LocalTransport extends BackupTransport {
|
||||
|
||||
@Override
|
||||
public int checkFullBackupSize(long size) {
|
||||
int result = TRANSPORT_OK;
|
||||
// Decline zero-size "backups"
|
||||
final int result = (size > 0) ? TRANSPORT_OK : TRANSPORT_PACKAGE_REJECTED;
|
||||
if (size <= 0) {
|
||||
result = TRANSPORT_PACKAGE_REJECTED;
|
||||
} else if (size > FULL_BACKUP_SIZE_QUOTA) {
|
||||
result = TRANSPORT_QUOTA_EXCEEDED;
|
||||
}
|
||||
if (result != TRANSPORT_OK) {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "Declining backup of size " + size);
|
||||
@@ -339,6 +348,7 @@ public class LocalTransport extends BackupTransport {
|
||||
// sure to dup() our own copy of the socket fd. Transports which run in
|
||||
// their own processes must not do this.
|
||||
try {
|
||||
mFullBackupSize = 0;
|
||||
mSocket = ParcelFileDescriptor.dup(socket.getFileDescriptor());
|
||||
mSocketInputStream = new FileInputStream(mSocket.getFileDescriptor());
|
||||
} catch (IOException e) {
|
||||
@@ -359,6 +369,11 @@ public class LocalTransport extends BackupTransport {
|
||||
return TRANSPORT_ERROR;
|
||||
}
|
||||
|
||||
mFullBackupSize += numBytes;
|
||||
if (mFullBackupSize > FULL_BACKUP_SIZE_QUOTA) {
|
||||
return TRANSPORT_QUOTA_EXCEEDED;
|
||||
}
|
||||
|
||||
if (numBytes > mFullBackupBuffer.length) {
|
||||
mFullBackupBuffer = new byte[numBytes];
|
||||
}
|
||||
@@ -699,4 +714,8 @@ public class LocalTransport extends BackupTransport {
|
||||
return TRANSPORT_OK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBackupQuota(String packageName, boolean isFullBackup) {
|
||||
return isFullBackup ? FULL_BACKUP_SIZE_QUOTA : Long.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3168,8 +3168,9 @@ public class BackupManagerService {
|
||||
|
||||
ParcelFileDescriptor backupData = null;
|
||||
mStatus = BackupTransport.TRANSPORT_OK;
|
||||
long size = 0;
|
||||
try {
|
||||
int size = (int) mBackupDataName.length();
|
||||
size = mBackupDataName.length();
|
||||
if (size > 0) {
|
||||
if (mStatus == BackupTransport.TRANSPORT_OK) {
|
||||
backupData = ParcelFileDescriptor.open(mBackupDataName,
|
||||
@@ -3214,6 +3215,10 @@ public class BackupManagerService {
|
||||
sendBackupOnResult(mObserver, pkgName,
|
||||
BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
|
||||
EventLogTags.writeBackupAgentFailure(pkgName, "Transport rejected");
|
||||
} else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
|
||||
sendBackupOnResult(mObserver, pkgName,
|
||||
BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
|
||||
EventLog.writeEvent(EventLogTags.BACKUP_QUOTA_EXCEEDED, pkgName);
|
||||
} else {
|
||||
// Actual transport-level failure to communicate the data to the backend
|
||||
sendBackupOnResult(mObserver, pkgName, BackupManager.ERROR_TRANSPORT_ABORTED);
|
||||
@@ -3234,6 +3239,20 @@ public class BackupManagerService {
|
||||
// Success or single-package rejection. Proceed with the next app if any,
|
||||
// otherwise we're done.
|
||||
nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
|
||||
} else if (mStatus == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
|
||||
if (MORE_DEBUG) {
|
||||
Slog.d(TAG, "Package " + mCurrentPackage.packageName +
|
||||
" hit quota limit on k/v backup");
|
||||
}
|
||||
if (mAgentBinder != null) {
|
||||
try {
|
||||
long quota = mTransport.getBackupQuota(mCurrentPackage.packageName, false);
|
||||
mAgentBinder.doQuotaExceeded(size, quota);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Unable to contact backup agent for quota exceeded");
|
||||
}
|
||||
}
|
||||
nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
|
||||
} else {
|
||||
// Any other error here indicates a transport-level failure. That means
|
||||
// we need to halt everything and reschedule everything for next time.
|
||||
@@ -3476,6 +3495,7 @@ public class BackupManagerService {
|
||||
OutputStream mOutput;
|
||||
FullBackupPreflight mPreflightHook;
|
||||
IFullBackupRestoreObserver mObserver;
|
||||
IBackupAgent mAgent;
|
||||
File mFilesDir;
|
||||
File mManifestFile;
|
||||
File mMetadataFile;
|
||||
@@ -3562,14 +3582,14 @@ public class BackupManagerService {
|
||||
int result = BackupTransport.TRANSPORT_OK;
|
||||
Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName);
|
||||
|
||||
IBackupAgent agent = bindToAgentSynchronous(pkg.applicationInfo,
|
||||
mAgent = bindToAgentSynchronous(pkg.applicationInfo,
|
||||
IApplicationThread.BACKUP_MODE_FULL);
|
||||
if (agent != null) {
|
||||
if (mAgent != null) {
|
||||
ParcelFileDescriptor[] pipes = null;
|
||||
try {
|
||||
// Call the preflight hook, if any
|
||||
if (mPreflightHook != null) {
|
||||
result = mPreflightHook.preflightFullBackup(pkg, agent);
|
||||
result = mPreflightHook.preflightFullBackup(pkg, mAgent);
|
||||
if (MORE_DEBUG) {
|
||||
Slog.v(TAG, "preflight returned " + result);
|
||||
}
|
||||
@@ -3592,7 +3612,7 @@ public class BackupManagerService {
|
||||
UserHandle.USER_SYSTEM);
|
||||
|
||||
final int token = generateToken();
|
||||
FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
|
||||
FullBackupRunner runner = new FullBackupRunner(pkg, mAgent, pipes[1],
|
||||
token, sendApk, !isSharedStorage, widgetBlob);
|
||||
pipes[1].close(); // the runner has dup'd it
|
||||
pipes[1] = null;
|
||||
@@ -3640,6 +3660,16 @@ public class BackupManagerService {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void sendQuotaExceeded(final long backupDataBytes, final long quotaBytes) {
|
||||
if (mAgent != null) {
|
||||
try {
|
||||
mAgent.doQuotaExceeded(backupDataBytes, quotaBytes);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception while telling agent about quota exceeded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writeApkToBackup(PackageInfo pkg, FullBackupDataOutput output) {
|
||||
// Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
|
||||
// TODO: handle backing up split APKs
|
||||
@@ -4344,6 +4374,15 @@ public class BackupManagerService {
|
||||
}
|
||||
} while (nRead > 0 && result == BackupTransport.TRANSPORT_OK);
|
||||
|
||||
if (result == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
|
||||
long quota = transport.getBackupQuota(currentPackage.packageName, true);
|
||||
if (MORE_DEBUG) {
|
||||
Slog.d(TAG, "Package hit quota limit " + currentPackage.packageName
|
||||
+ ": " + totalRead + " of " + quota);
|
||||
}
|
||||
backupRunner.sendQuotaExceeded(totalRead, quota);
|
||||
}
|
||||
|
||||
// If we've lost our running criteria, tell the transport to cancel
|
||||
// and roll back this (partial) backup payload; otherwise tell it
|
||||
// that we've reached the clean finish state.
|
||||
@@ -4387,6 +4426,8 @@ public class BackupManagerService {
|
||||
}
|
||||
|
||||
if (result == BackupTransport.TRANSPORT_PACKAGE_REJECTED) {
|
||||
sendBackupOnResult(mBackupObserver, currentPackage.packageName,
|
||||
BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Transport rejected backup of "
|
||||
+ currentPackage.packageName
|
||||
@@ -4394,35 +4435,40 @@ public class BackupManagerService {
|
||||
}
|
||||
EventLog.writeEvent(EventLogTags.FULL_BACKUP_AGENT_FAILURE,
|
||||
currentPackage.packageName, "transport rejected");
|
||||
sendBackupOnResult(mBackupObserver, currentPackage.packageName,
|
||||
BackupManager.ERROR_TRANSPORT_PACKAGE_REJECTED);
|
||||
// do nothing, clean up, and continue looping
|
||||
} else if (result == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
|
||||
sendBackupOnResult(mBackupObserver, currentPackage.packageName,
|
||||
BackupManager.ERROR_TRANSPORT_QUOTA_EXCEEDED);
|
||||
Slog.w(TAG, "Transport quota exceeded; aborting backup: " + result);
|
||||
EventLog.writeEvent(EventLogTags.FULL_BACKUP_QUOTA_EXCEEDED,
|
||||
currentPackage.packageName);
|
||||
return;
|
||||
} else if (result != BackupTransport.TRANSPORT_OK) {
|
||||
Slog.w(TAG, "Transport failed; aborting backup: " + result);
|
||||
EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE);
|
||||
sendBackupOnResult(mBackupObserver, currentPackage.packageName,
|
||||
BackupManager.ERROR_TRANSPORT_ABORTED);
|
||||
Slog.w(TAG, "Transport failed; aborting backup: " + result);
|
||||
EventLog.writeEvent(EventLogTags.FULL_BACKUP_TRANSPORT_FAILURE);
|
||||
return;
|
||||
} else {
|
||||
// Success!
|
||||
sendBackupOnResult(mBackupObserver, currentPackage.packageName,
|
||||
BackupManager.SUCCESS);
|
||||
EventLog.writeEvent(EventLogTags.FULL_BACKUP_SUCCESS,
|
||||
currentPackage.packageName);
|
||||
logBackupComplete(currentPackage.packageName);
|
||||
sendBackupOnResult(mBackupObserver, currentPackage.packageName,
|
||||
BackupManager.SUCCESS);
|
||||
}
|
||||
cleanUpPipes(transportPipes);
|
||||
cleanUpPipes(enginePipes);
|
||||
currentPackage = null;
|
||||
}
|
||||
|
||||
sendBackupFinished(mBackupObserver, BackupManager.SUCCESS);
|
||||
if (DEBUG) {
|
||||
Slog.i(TAG, "Full backup completed.");
|
||||
}
|
||||
sendBackupFinished(mBackupObserver, BackupManager.SUCCESS);
|
||||
} catch (Exception e) {
|
||||
Slog.w(TAG, "Exception trying full transport backup", e);
|
||||
sendBackupFinished(mBackupObserver, BackupManager.ERROR_TRANSPORT_ABORTED);
|
||||
Slog.w(TAG, "Exception trying full transport backup", e);
|
||||
} finally {
|
||||
cleanUpPipes(transportPipes);
|
||||
cleanUpPipes(enginePipes);
|
||||
@@ -4503,6 +4549,14 @@ public class BackupManagerService {
|
||||
}
|
||||
|
||||
result = mTransport.checkFullBackupSize(totalSize);
|
||||
if (result == BackupTransport.TRANSPORT_QUOTA_EXCEEDED) {
|
||||
final long quota = mTransport.getBackupQuota(pkg.packageName, true);
|
||||
if (MORE_DEBUG) {
|
||||
Slog.d(TAG, "Package hit quota limit on preflight " +
|
||||
pkg.packageName + ": " + totalSize + " of " + quota);
|
||||
}
|
||||
agent.doQuotaExceeded(totalSize, quota);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Slog.w(TAG, "Exception preflighting " + pkg.packageName + ": " + e.getMessage());
|
||||
result = BackupTransport.AGENT_ERROR;
|
||||
@@ -4550,6 +4604,7 @@ public class BackupManagerService {
|
||||
final PackageInfo mTarget;
|
||||
final FullBackupPreflight mPreflight;
|
||||
final CountDownLatch mLatch;
|
||||
private FullBackupEngine mEngine;
|
||||
|
||||
SinglePackageBackupRunner(ParcelFileDescriptor output, PackageInfo target,
|
||||
IBackupTransport transport, CountDownLatch latch) throws IOException {
|
||||
@@ -4563,9 +4618,9 @@ public class BackupManagerService {
|
||||
public void run() {
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(mOutput.getFileDescriptor());
|
||||
FullBackupEngine engine = new FullBackupEngine(out, mTarget.packageName,
|
||||
mEngine = new FullBackupEngine(out, mTarget.packageName,
|
||||
mPreflight, false);
|
||||
engine.backupOnePackage(mTarget);
|
||||
mEngine.backupOnePackage(mTarget);
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Exception during full package backup of " + mTarget);
|
||||
} finally {
|
||||
@@ -4578,6 +4633,10 @@ public class BackupManagerService {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendQuotaExceeded(final long backupDataBytes, final long quotaBytes) {
|
||||
mEngine.sendQuotaExceeded(backupDataBytes, quotaBytes);
|
||||
}
|
||||
|
||||
long expectedSize() {
|
||||
return mPreflight.expectedSize();
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ option java_package com.android.server
|
||||
2826 backup_reset (Transport|3)
|
||||
2827 backup_initialize
|
||||
2828 backup_requested (Total|1|1),(Key-Value|1|1),(Full|1|1)
|
||||
2829 backup_quota_exceeded (Package|3)
|
||||
2830 restore_start (Transport|3),(Source|2|5)
|
||||
2831 restore_transport_failure
|
||||
2832 restore_agent_failure (Package|3),(Message|3)
|
||||
@@ -119,6 +120,7 @@ option java_package com.android.server
|
||||
2842 full_backup_transport_failure
|
||||
2843 full_backup_success (Package|3)
|
||||
2844 full_restore_package (Package|3)
|
||||
2845 full_backup_quota_exceeded (Package|3)
|
||||
|
||||
2850 backup_transport_lifecycle (Transport|3),(Bound|1|1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user