Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9568fb21 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 26164 into eclair

* changes:
  Reset backup tracking in response to transport data-wipe notification
parents d3997e55 d55e18ac
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
/*
 * 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;
}
+7 −3
Original line number Diff line number Diff line
@@ -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);

    /**
+4 −4
Original line number Diff line number Diff line
@@ -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;
        }
    }

+70 −6
Original line number Diff line number Diff line
@@ -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