Merge change 26164 into eclair

* changes:
  Reset backup tracking in response to transport data-wipe notification
This commit is contained in:
Android (Google) Code Review
2009-09-21 16:13:48 -04:00
4 changed files with 107 additions and 13 deletions

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2009 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 com.android.internal.backup;
/**
* Constants used internally between the backup manager and its transports
*/
public class BackupConstants {
public static final int TRANSPORT_OK = 0;
public static final int TRANSPORT_ERROR = 1;
public static final int TRANSPORT_NOT_INITIALIZED = 2;
}

View File

@@ -81,10 +81,14 @@ interface IBackupTransport {
* will be erased prior to the storage of the data provided here. The purpose of this
* is to provide a guarantee that no stale data exists in the restore set when the
* device begins providing backups.
* @return false if errors occurred (the backup should be aborted and rescheduled),
* true if everything is OK so far (but {@link #finishBackup} must be called).
* @return If everything is okay so far, returns zero (but {@link #finishBackup} must
* still be called). If the backend dataset has unexpectedly become unavailable,
* such as when it is deleted after a period of device inactivity, returns {@link
* BackupManager#DATASET_UNAVAILABLE}; in this case, the transport should be
* reinitalized and the entire backup pass restarted. Any other nonzero value is a
* fatal error requiring that this package's backup be aborted and rescheduled.
*/
boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd,
int performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd,
boolean wipeAllFirst);
/**

View File

@@ -56,7 +56,7 @@ public class LocalTransport extends IBackupTransport.Stub {
return 0;
}
public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data,
public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data,
boolean wipeAllFirst) throws RemoteException {
if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);
@@ -99,7 +99,7 @@ public class LocalTransport extends IBackupTransport.Stub {
entity.write(buf, 0, dataSize);
} catch (IOException e) {
Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath());
return false;
return BackupConstants.TRANSPORT_ERROR;
} finally {
entity.close();
}
@@ -107,11 +107,11 @@ public class LocalTransport extends IBackupTransport.Stub {
entityFile.delete();
}
}
return true;
return BackupConstants.TRANSPORT_OK;
} catch (IOException e) {
// oops, something went wrong. abort the operation and return error.
Log.v(TAG, "Exception reading backup input:", e);
return false;
return BackupConstants.TRANSPORT_ERROR;
}
}

View File

@@ -57,6 +57,7 @@ import android.backup.IRestoreObserver;
import android.backup.IRestoreSession;
import android.backup.RestoreSet;
import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.LocalTransport;
import com.android.internal.backup.IBackupTransport;
@@ -101,6 +102,7 @@ class BackupManagerService extends IBackupManager.Stub {
private static final int BACKUP_AGENT_FAILURE_EVENT = 2823;
private static final int BACKUP_PACKAGE_EVENT = 2824;
private static final int BACKUP_SUCCESS_EVENT = 2825;
private static final int BACKUP_RESET_EVENT = 2826;
private static final int RESTORE_START_EVENT = 2830;
private static final int RESTORE_TRANSPORT_FAILURE_EVENT = 2831;
@@ -406,6 +408,47 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
// Reset all of our bookkeeping, in response to having been told that
// the backend data has been wiped [due to idle expiry, for example],
// so we must re-upload all saved settings.
void resetBackupState(File stateFileDir) {
synchronized (mQueueLock) {
// Wipe the "what we've ever backed up" tracking
try {
// close the ever-stored journal...
if (mEverStoredStream != null) {
mEverStoredStream.close();
}
// ... so we can delete it and start over
mEverStored.delete();
mEverStoredStream = new RandomAccessFile(mEverStored, "rwd");
} catch (IOException e) {
Log.e(TAG, "Unable to open known-stored file!");
mEverStoredStream = null;
}
mEverStoredApps.clear();
// Remove all the state files
for (File sf : stateFileDir.listFiles()) {
sf.delete();
}
// Enqueue a new backup of every participant
int N = mBackupParticipants.size();
for (int i=0; i<N; i++) {
int uid = mBackupParticipants.keyAt(i);
HashSet<ApplicationInfo> participants = mBackupParticipants.valueAt(i);
for (ApplicationInfo app: participants) {
try {
dataChanged(app.packageName);
} catch (RemoteException e) {
// can't happen; we're in the same process
}
}
}
}
}
// Add a transport to our set of available backends
private void registerTransport(String name, IBackupTransport transport) {
synchronized (mTransports) {
@@ -891,8 +934,22 @@ class BackupManagerService extends IBackupManager.Stub {
// If we haven't stored anything yet, we need to do an init
// operation along with recording the metadata blob.
boolean needInit = (mEverStoredApps.size() == 0);
processOneBackup(pmRequest, IBackupAgent.Stub.asInterface(pmAgent.onBind()),
int result = processOneBackup(pmRequest,
IBackupAgent.Stub.asInterface(pmAgent.onBind()),
mTransport, needInit);
if (result == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
// The backend reports that our dataset has been wiped. We need to
// reset all of our bookkeeping and instead run a new backup pass for
// everything.
EventLog.writeEvent(BACKUP_RESET_EVENT, mTransport.transportDirName());
resetBackupState(mStateDir);
backupNow();
return;
} else if (result != BackupConstants.TRANSPORT_OK) {
// Give up if we couldn't even process the metadata
Log.e(TAG, "Meta backup err " + result);
return;
}
// Now run all the backups in our queue
int count = mQueue.size();
@@ -953,7 +1010,7 @@ class BackupManagerService extends IBackupManager.Stub {
}
}
void processOneBackup(BackupRequest request, IBackupAgent agent,
int processOneBackup(BackupRequest request, IBackupAgent agent,
IBackupTransport transport, boolean doInit) {
final String packageName = request.appInfo.packageName;
if (DEBUG) Log.d(TAG, "processOneBackup doBackup(" + doInit + ") on " + packageName);
@@ -1007,7 +1064,7 @@ class BackupManagerService extends IBackupManager.Stub {
EventLog.writeEvent(BACKUP_AGENT_FAILURE_EVENT, packageName, e.toString());
backupDataName.delete();
newStateName.delete();
return;
return BackupConstants.TRANSPORT_ERROR;
} finally {
try { if (savedState != null) savedState.close(); } catch (IOException e) {}
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
@@ -1027,7 +1084,13 @@ class BackupManagerService extends IBackupManager.Stub {
// hold off on finishBackup() until the end, which implies holding off on
// renaming *all* the output state files (see below) until that happens.
if (!transport.performBackup(packInfo, backupData, doInit) ||
int performOkay = transport.performBackup(packInfo, backupData, doInit);
if (performOkay == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
Log.i(TAG, "Backend not initialized");
return performOkay;
}
if ((performOkay != 0) ||
!transport.finishBackup()) {
throw new Exception("Backup transport failed");
}
@@ -1044,10 +1107,12 @@ class BackupManagerService extends IBackupManager.Stub {
} catch (Exception e) {
Log.e(TAG, "Transport error backing up " + packageName, e);
EventLog.writeEvent(BACKUP_TRANSPORT_FAILURE_EVENT, packageName);
return;
return BackupConstants.TRANSPORT_ERROR;
} finally {
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
}
return BackupConstants.TRANSPORT_OK;
}
}
@@ -1590,7 +1655,6 @@ class BackupManagerService extends IBackupManager.Stub {
if (DEBUG) Log.v(TAG, "Scheduling immediate backup pass");
synchronized (mQueueLock) {
try {
if (DEBUG) Log.v(TAG, "sending immediate backup broadcast");
mRunBackupIntent.send();
} catch (PendingIntent.CanceledException e) {
// should never happen